diff options
Diffstat (limited to 'apps')
604 files changed, 13520 insertions, 2914 deletions
diff --git a/apps/dav/.gitignore b/apps/dav/.gitignore new file mode 100644 index 00000000000..885b6b3e6de --- /dev/null +++ b/apps/dav/.gitignore @@ -0,0 +1 @@ +tests/travis/CalDAVTester diff --git a/apps/dav/appinfo/database.xml b/apps/dav/appinfo/database.xml new file mode 100644 index 00000000000..48641c2be6f --- /dev/null +++ b/apps/dav/appinfo/database.xml @@ -0,0 +1,624 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> +<database> + + <!-- +CREATE TABLE addressbooks ( + id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, + principaluri VARBINARY(255), + displayname VARCHAR(255), + uri VARBINARY(200), + description TEXT, + synctoken INT(11) UNSIGNED NOT NULL DEFAULT '1', + UNIQUE(principaluri(100), uri(100)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + --> + <table> + + <name>*dbprefix*addressbooks</name> + + <declaration> + + <field> + <name>id</name> + <type>integer</type> + <default>0</default> + <notnull>true</notnull> + <autoincrement>1</autoincrement> + <unsigned>true</unsigned> + <length>11</length> + </field> + + <field> + <name>principaluri</name> + <type>text</type> + </field> + <field> + <name>displayname</name> + <type>text</type> + </field> + <field> + <name>uri</name> + <type>text</type> + </field> + <field> + <name>description</name> + <type>text</type> + </field> + <field> + <name>synctoken</name> + <type>integer</type> + <default>1</default> + <notnull>true</notnull> + <unsigned>true</unsigned> + </field> + <index> + <name>addressbook_index</name> + <unique>true</unique> + <field> + <name>principaluri</name> + </field> + <field> + <name>uri</name> + </field> + </index> + </declaration> + </table> + + <!-- + +CREATE TABLE cards ( + id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, + addressbookid INT(11) UNSIGNED NOT NULL, + carddata MEDIUMBLOB, + uri VARBINARY(200), + lastmodified INT(11) UNSIGNED, + etag VARBINARY(32), + size INT(11) UNSIGNED NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + + --> + <table> + <name>*dbprefix*cards</name> + <declaration> + <field> + <name>id</name> + <type>integer</type> + <default>0</default> + <notnull>true</notnull> + <autoincrement>1</autoincrement> + <unsigned>true</unsigned> + <length>11</length> + </field> + <field> + <name>addressbookid</name> + <type>integer</type> + <default>0</default> + <notnull>true</notnull> + </field> + <field> + <name>carddata</name> + <type>blob</type> + </field> + <field> + <name>uri</name> + <type>text</type> + </field> + <field> + <name>lastmodified</name> + <type>integer</type> + <unsigned>true</unsigned> + <length>11</length> + </field> + <field> + <name>etag</name> + <type>text</type> + <length>32</length> + </field> + <field> + <name>size</name> + <type>integer</type> + <notnull>true</notnull> + <unsigned>true</unsigned> + <length>11</length> + </field> + </declaration> + </table> + + <!-- +CREATE TABLE addressbookchanges ( + id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, + uri VARBINARY(200) NOT NULL, + synctoken INT(11) UNSIGNED NOT NULL, + addressbookid INT(11) UNSIGNED NOT NULL, + operation TINYINT(1) NOT NULL, + INDEX addressbookid_synctoken (addressbookid, synctoken) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + --> + + <table> + <name>*dbprefix*addressbookchanges</name> + <declaration> + <field> + <name>id</name> + <type>integer</type> + <default>0</default> + <notnull>true</notnull> + <autoincrement>1</autoincrement> + <unsigned>true</unsigned> + <length>11</length> + </field> + <field> + <name>uri</name> + <type>text</type> + </field> + <field> + <name>synctoken</name> + <type>integer</type> + <default>1</default> + <notnull>true</notnull> + <unsigned>true</unsigned> + </field> + <field> + <name>addressbookid</name> + <type>integer</type> + <notnull>true</notnull> + </field> + <field> + <name>operation</name> + <type>integer</type> + <notnull>true</notnull> + <length>1</length> + </field> + + <index> + <name>addressbookid_synctoken</name> + <field> + <name>addressbookid</name> + </field> + <field> + <name>synctoken</name> + </field> + </index> + + </declaration> + </table> + + +<!-- +CREATE TABLE calendarobjects ( + id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, + calendardata MEDIUMBLOB, + uri VARBINARY(200), + calendarid INTEGER UNSIGNED NOT NULL, + lastmodified INT(11) UNSIGNED, + etag VARBINARY(32), + size INT(11) UNSIGNED NOT NULL, + componenttype VARBINARY(8), + firstoccurence INT(11) UNSIGNED, + lastoccurence INT(11) UNSIGNED, + uid VARBINARY(200), + UNIQUE(calendarid, uri) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +--> +<table> + <name>*dbprefix*calendarobjects</name> + <declaration> + <field> + <name>id</name> + <type>integer</type> + <default>0</default> + <notnull>true</notnull> + <autoincrement>1</autoincrement> + <unsigned>true</unsigned> + <length>11</length> + </field> + <field> + <name>calendardata</name> + <type>blob</type> + </field> + <field> + <name>uri</name> + <type>text</type> + </field> + <field> + <name>calendarid</name> + <type>integer</type> + <unsigned>true</unsigned> + <notnull>true</notnull> + </field> + <field> + <name>lastmodified</name> + <type>integer</type> + <unsigned>true</unsigned> + </field> + <field> + <name>etag</name> + <type>text</type> + <length>32</length> + </field> + <field> + <name>size</name> + <type>integer</type> + <notnull>true</notnull> + <unsigned>true</unsigned> + <length>11</length> + </field> + <field> + <name>componenttype</name> + <type>text</type> + </field> + <field> + <name>firstoccurence</name> + <type>integer</type> + <unsigned>true</unsigned> + </field> + <field> + <name>lastoccurence</name> + <type>integer</type> + <unsigned>true</unsigned> + </field> + <field> + <name>uid</name> + <type>text</type> + </field> + <index> + <name>calobjects_index</name> + <unique>true</unique> + <field> + <name>calendarid</name> + </field> + <field> + <name>uri</name> + </field> + </index> + </declaration> +</table> + <!-- + CREATE TABLE calendars ( + id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, + principaluri VARBINARY(100), + displayname VARCHAR(100), + uri VARBINARY(200), + synctoken INTEGER UNSIGNED NOT NULL DEFAULT '1', + description TEXT, + calendarorder INT(11) UNSIGNED NOT NULL DEFAULT '0', + calendarcolor VARBINARY(10), + timezone TEXT, + components VARBINARY(20), + transparent TINYINT(1) NOT NULL DEFAULT '0', + UNIQUE(principaluri, uri) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + --> +<table> + <name>*dbprefix*calendars</name> + <declaration> + <field> + <name>id</name> + <type>integer</type> + <default>0</default> + <notnull>true</notnull> + <autoincrement>1</autoincrement> + <unsigned>true</unsigned> + <length>11</length> + </field> + <field> + <name>principaluri</name> + <type>text</type> + </field> + <field> + <name>displayname</name> + <type>text</type> + </field> + <field> + <name>uri</name> + <type>text</type> + </field> + <field> + <name>synctoken</name> + <type>integer</type> + <default>1</default> + <notnull>true</notnull> + <unsigned>true</unsigned> + </field> + <field> + <name>description</name> + <type>text</type> + </field> + <field> + <name>calendarorder</name> + <type>integer</type> + <default>0</default> + <notnull>true</notnull> + <unsigned>true</unsigned> + </field> + <field> + <name>calendarcolor</name> + <type>text</type> + </field> + <field> + <name>timezone</name> + <type>text</type> + </field> + <field> + <name>components</name> + <type>text</type> + </field> + <field> + <name>transparent</name> + <type>integer</type> + <length>1</length> + <notnull>true</notnull> + <default>0</default> + </field> + <index> + <name>calendars_index</name> + <unique>true</unique> + <field> + <name>principaluri</name> + </field> + <field> + <name>uri</name> + </field> + </index> + </declaration> +</table> + <!-- + CREATE TABLE calendarchanges ( + id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, + uri VARBINARY(200) NOT NULL, + synctoken INT(11) UNSIGNED NOT NULL, + calendarid INT(11) UNSIGNED NOT NULL, + operation TINYINT(1) NOT NULL, + INDEX calendarid_synctoken (calendarid, synctoken) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + --> + <table> + <name>*dbprefix*calendarchanges</name> + <declaration> + <field> + <name>id</name> + <type>integer</type> + <default>0</default> + <notnull>true</notnull> + <autoincrement>1</autoincrement> + <unsigned>true</unsigned> + <length>11</length> + </field> + <field> + <name>uri</name> + <type>text</type> + </field> + <field> + <name>synctoken</name> + <type>integer</type> + <default>1</default> + <notnull>true</notnull> + <unsigned>true</unsigned> + </field> + <field> + <name>calendarid</name> + <type>integer</type> + <notnull>true</notnull> + </field> + <field> + <name>operation</name> + <type>integer</type> + <notnull>true</notnull> + <length>1</length> + </field> + + <index> + <name>calendarid_synctoken</name> + <field> + <name>calendarid</name> + </field> + <field> + <name>synctoken</name> + </field> + </index> + + </declaration> + </table> + + <!-- + CREATE TABLE calendarsubscriptions ( + id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, + uri VARBINARY(200) NOT NULL, + principaluri VARBINARY(100) NOT NULL, + source TEXT, + displayname VARCHAR(100), + refreshrate VARCHAR(10), + calendarorder INT(11) UNSIGNED NOT NULL DEFAULT '0', + calendarcolor VARBINARY(10), + striptodos TINYINT(1) NULL, + stripalarms TINYINT(1) NULL, + stripattachments TINYINT(1) NULL, + lastmodified INT(11) UNSIGNED, + UNIQUE(principaluri, uri) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + --> +<table> + <name>*dbprefix*calendarsubscriptions</name> + <declaration> + <field> + <name>id</name> + <type>integer</type> + <default>0</default> + <notnull>true</notnull> + <autoincrement>1</autoincrement> + <unsigned>true</unsigned> + <length>11</length> + </field> + <field> + <name>uri</name> + <type>text</type> + </field> + <field> + <name>principaluri</name> + <type>text</type> + </field> + <field> + <name>source</name> + <type>text</type> + </field> + <field> + <name>displayname</name> + <type>text</type> + <length>100</length> + </field> + <field> + <name>refreshrate</name> + <type>text</type> + <length>10</length> + </field> + <field> + <name>calendarorder</name> + <type>integer</type> + <default>0</default> + <notnull>true</notnull> + <unsigned>true</unsigned> + </field> + <field> + <name>calendarcolor</name> + <type>text</type> + </field> + <field> + <name>striptodos</name> + <type>integer</type> + <length>1</length> + </field> + <field> + <name>stripalarms</name> + <type>integer</type> + <length>1</length> + </field> + <field> + <name>stripattachments</name> + <type>integer</type> + <length>1</length> + </field> + <field> + <name>lastmodified</name> + <type>integer</type> + <unsigned>true</unsigned> + </field> + <index> + <name>calsub_index</name> + <unique>true</unique> + <field> + <name>principaluri</name> + </field> + <field> + <name>uri</name> + </field> + </index> + </declaration> +</table> + <!-- + CREATE TABLE schedulingobjects ( + id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, + principaluri VARBINARY(255), + calendardata MEDIUMBLOB, + uri VARBINARY(200), + lastmodified INT(11) UNSIGNED, + etag VARBINARY(32), + size INT(11) UNSIGNED NOT NULL + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + --> + + <table> + <name>*dbprefix*schedulingobjects</name> + <declaration> + <field> + <name>id</name> + <type>integer</type> + <default>0</default> + <notnull>true</notnull> + <autoincrement>1</autoincrement> + <unsigned>true</unsigned> + <length>11</length> + </field> + <field> + <name>principaluri</name> + <type>text</type> + </field> + <field> + <name>calendardata</name> + <type>blob</type> + </field> + <field> + <name>uri</name> + <type>text</type> + </field> + <field> + <name>lastmodified</name> + <type>integer</type> + <unsigned>true</unsigned> + </field> + <field> + <name>etag</name> + <type>text</type> + <length>32</length> + </field> + <field> + <name>size</name> + <type>integer</type> + <notnull>true</notnull> + <unsigned>true</unsigned> + <length>11</length> + </field> + + </declaration> + </table> + + <table> + <name>*dbprefix*dav_shares</name> + <declaration> + <field> + <name>id</name> + <type>integer</type> + <default>0</default> + <notnull>true</notnull> + <autoincrement>1</autoincrement> + <unsigned>true</unsigned> + <length>11</length> + </field> + <field> + <name>uri</name> + <type>text</type> + </field> + <field> + <name>principaluri</name> + <type>text</type> + </field> + <field> + <name>type</name> + <type>text</type> + </field> + <field> + <name>access</name> + <type>integer</type> + <length>1</length> + </field> + <field> + <name>resourceid</name> + <type>integer</type> + <notnull>true</notnull> + <unsigned>true</unsigned> + </field> + <index> + <name>dav_shares_index</name> + <unique>true</unique> + <field> + <name>principaluri</name> + </field> + <field> + <name>uri</name> + </field> + <field> + <name>type</name> + </field> + </index> + </declaration> + </table> +</database> diff --git a/apps/dav/appinfo/info.xml b/apps/dav/appinfo/info.xml index c80af15a29b..5f681e784fc 100644 --- a/apps/dav/appinfo/info.xml +++ b/apps/dav/appinfo/info.xml @@ -5,6 +5,7 @@ <description>ownCloud WebDAV endpoint</description> <licence>AGPL</licence> <author>owncloud.org</author> + <version>0.1.3</version> <requiremin>9.0</requiremin> <shipped>true</shipped> <standalone/> @@ -15,6 +16,7 @@ <remote> <files>appinfo/v1/webdav.php</files> <webdav>appinfo/v1/webdav.php</webdav> + <dav>appinfo/v2/remote.php</dav> </remote> <public> <webdav>appinfo/v1/publicwebdav.php</webdav> diff --git a/apps/dav/appinfo/register_command.php b/apps/dav/appinfo/register_command.php new file mode 100644 index 00000000000..7d57b944fb2 --- /dev/null +++ b/apps/dav/appinfo/register_command.php @@ -0,0 +1,10 @@ +<?php + +use OCA\DAV\Command\CreateAddressBook; +use OCA\DAV\Command\CreateCalendar; + +$dbConnection = \OC::$server->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/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 610230fc816..8324f962b8e 100644 --- a/apps/dav/appinfo/v1/webdav.php +++ b/apps/dav/appinfo/v1/webdav.php @@ -40,11 +40,15 @@ $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 -$authBackend = new \OCA\DAV\Connector\Sabre\Auth(); +$authBackend = new \OCA\DAV\Connector\Sabre\Auth( + \OC::$server->getSession(), + \OC::$server->getUserSession() +); $requestUri = \OC::$server->getRequest()->getRequestUri(); $server = $serverFactory->createServer($baseuri, $requestUri, $authBackend, function() { diff --git a/apps/dav/appinfo/v2/remote.php b/apps/dav/appinfo/v2/remote.php new file mode 100644 index 00000000000..02457bd3ccc --- /dev/null +++ b/apps/dav/appinfo/v2/remote.php @@ -0,0 +1,11 @@ +<?php + +// no php execution timeout for webdav +set_time_limit(0); + +// Turn off output buffering to prevent memory problems +\OC_Util::obEnd(); + +$request = \OC::$server->getRequest(); +$server = new \OCA\DAV\Server($request, $baseuri); +$server->exec(); diff --git a/apps/dav/command/createaddressbook.php b/apps/dav/command/createaddressbook.php new file mode 100644 index 00000000000..286871b39e2 --- /dev/null +++ b/apps/dav/command/createaddressbook.php @@ -0,0 +1,52 @@ +<?php + +namespace OCA\DAV\Command; + +use OCA\DAV\CardDAV\CardDavBackend; +use OCP\IDBConnection; +use OCP\IUserManager; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class CreateAddressBook extends Command { + + /** @var IUserManager */ + protected $userManager; + + /** @var \OCP\IDBConnection */ + protected $dbConnection; + + /** + * @param IUserManager $userManager + * @param IDBConnection $dbConnection + */ + function __construct(IUserManager $userManager, IDBConnection $dbConnection) { + parent::__construct(); + $this->userManager = $userManager; + $this->dbConnection = $dbConnection; + } + + protected function configure() { + $this + ->setName('dav:create-addressbook') + ->setDescription('Create a dav addressbook') + ->addArgument('user', + InputArgument::REQUIRED, + 'User for whom the addressbook will be created') + ->addArgument('name', + InputArgument::REQUIRED, + 'Name of the addressbook'); + } + + 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'); + $carddav = new CardDavBackend($this->dbConnection); + $carddav->createAddressBook("principals/$user", $name, []); + } +} 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 @@ +<?php + +namespace OCA\DAV\Command; + +use OCA\DAV\CalDAV\CalDavBackend; +use OCP\IDBConnection; +use OCP\IUserManager; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class CreateCalendar extends Command { + + /** @var IUserManager */ + protected $userManager; + + /** @var \OCP\IDBConnection */ + protected $dbConnection; + + /** + * @param IUserManager $userManager + * @param IDBConnection $dbConnection + */ + function __construct(IUserManager $userManager, IDBConnection $dbConnection) { + parent::__construct(); + $this->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, []); + } +} diff --git a/apps/dav/lib/caldav/caldavbackend.php b/apps/dav/lib/caldav/caldavbackend.php new file mode 100644 index 00000000000..08a2a70c56d --- /dev/null +++ b/apps/dav/lib/caldav/caldavbackend.php @@ -0,0 +1,1175 @@ +<?php +/** + * @author Thomas Müller <thomas.mueller@tmit.eu> + * + * @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 <http://www.gnu.org/licenses/> + * + */ + +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) { + $values = [ + 'principaluri' => $principalUri, + 'uri' => $calendarUri, + 'synctoken' => 1, + 'transparent' => 0, + 'components' => 'VEVENT,VTODO', + 'displayname' => $calendarUri + ]; + + // 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]; + } + } + + $query = $this->db->getQueryBuilder(); + $query->insert('calendars'); + foreach($values as $column => $value) { + $query->setValue($column, $query->createNamedParameter($value)); + } + $query->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('*PREFIX*calendarsubscriptions'); + } + + /** + * 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) { + $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'], + ]; + } + + /** + * 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) { + $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; + } + + /** + * Deletes a scheduling object from the inbox collection. + * + * @param string $principalUri + * @param string $objectUri + * @return void + */ + function deleteSchedulingObject($principalUri, $objectUri) { + $query = $this->db->getQueryBuilder(); + $query->delete('schedulingobjects') + ->where($query->expr()->eq('principaluri', $query->createNamedParameter($principalUri))) + ->andWhere($query->expr()->eq('uri', $query->createNamedParameter($objectUri))) + ->execute(); + } + + /** + * 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) { + $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(); + } + + /** + * 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/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 @@ +<?php + +namespace OCA\DAV\CardDAV; + +use OCA\DAV\CardDAV\Sharing\IShareableAddressBook; +use OCP\IUserManager; + +class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareableAddressBook { + + /** @var IUserManager */ + private $userManager; + + public function __construct(CardDavBackend $carddavBackend, array $addressBookInfo) { + parent::__construct($carddavBackend, $addressBookInfo); + } + + /** + * Updates the list of shares. + * + * The first array is a list of people that are to be added to the + * addressbook. + * + * Every element in the add array has the following properties: + * * href - A url. Usually a mailto: address + * * commonName - Usually a first and last name, or false + * * summary - A description of the share, can also be false + * * readOnly - A boolean value + * + * Every element in the remove array is just the address string. + * + * @param array $add + * @param array $remove + * @return void + */ + function updateShares(array $add, array $remove) { + /** @var CardDavBackend $carddavBackend */ + $carddavBackend = $this->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 @@ +<?php + +namespace OCA\DAV\CardDAV; + +class AddressBookRoot extends \Sabre\CardDAV\AddressBookRoot { + + /** + * This method returns a node for a principal. + * + * The passed array contains principal information, and is guaranteed to + * at least contain a uri item. Other properties may or may not be + * supplied by the authentication backend. + * + * @param array $principal + * @return \Sabre\DAV\INode + */ + function getChildForPrincipal(array $principal) { + + return new UserAddressBooks($this->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 new file mode 100644 index 00000000000..348c166a531 --- /dev/null +++ b/apps/dav/lib/carddav/carddavbackend.php @@ -0,0 +1,737 @@ +<?php + +/** + * @author Thomas Müller <thomas.mueller@tmit.eu> + * + * @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 <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\DAV\CardDAV; + +use OCA\DAV\Connector\Sabre\Principal; +use Sabre\CardDAV\Backend\BackendInterface; +use Sabre\CardDAV\Backend\SyncSupport; +use Sabre\CardDAV\Plugin; +use Sabre\DAV\Exception\BadRequest; + +class CardDavBackend implements BackendInterface, SyncSupport { + + /** @var Principal */ + private $principalBackend; + + public function __construct(\OCP\IDBConnection $db, Principal $principalBackend) { + $this->db = $db; + $this->principalBackend = $principalBackend; + } + + /** + * Returns the list of addressbooks for a specific user. + * + * Every addressbook should have the following properties: + * id - an arbitrary unique id + * uri - the 'basename' part of the url + * principaluri - Same as the passed parameter + * + * Any additional clark-notation property may be passed besides this. Some + * common ones are : + * {DAV:}displayname + * {urn:ietf:params:xml:ns:carddav}addressbook-description + * {http://calendarserver.org/ns/}getctag + * + * @param string $principalUri + * @return array + */ + function getAddressBooksForUser($principalUri) { + $query = $this->db->getQueryBuilder(); + $query->select(['id', 'uri', 'displayname', 'principaluri', 'description', 'synctoken']) + ->from('addressbooks') + ->where($query->expr()->eq('principaluri', $query->createParameter('principaluri'))) + ->setParameter('principaluri', $principalUri); + + $addressBooks = []; + + $result = $query->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(); + + // 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. + * + * 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 $addressBookId + * @param \Sabre\DAV\PropPatch $propPatch + * @return void + */ + function updateAddressBook($addressBookId, \Sabre\DAV\PropPatch $propPatch) { + $supportedProperties = [ + '{DAV:}displayname', + '{' . Plugin::NS_CARDDAV . '}addressbook-description', + ]; + + $propPatch->handle($supportedProperties, function($mutations) use ($addressBookId) { + + $updates = []; + foreach($mutations as $property=>$newValue) { + + switch($property) { + case '{DAV:}displayname' : + $updates['displayname'] = $newValue; + break; + case '{' . Plugin::NS_CARDDAV . '}addressbook-description' : + $updates['description'] = $newValue; + break; + } + } + $query = $this->db->getQueryBuilder(); + $query->update('addressbooks'); + + foreach($updates as $key=>$value) { + $query->set($key, $query->createNamedParameter($value)); + } + $query->where($query->expr()->eq('id', $query->createNamedParameter($addressBookId))) + ->execute(); + + $this->addChange($addressBookId, "", 2); + + return true; + + }); + } + + /** + * Creates a new address book + * + * @param string $principalUri + * @param string $url Just the 'basename' of the url. + * @param array $properties + * @throws BadRequest + */ + function createAddressBook($principalUri, $url, array $properties) { + $values = [ + 'displayname' => null, + 'description' => null, + 'principaluri' => $principalUri, + 'uri' => $url, + 'synctoken' => 1 + ]; + + foreach($properties as $property=>$newValue) { + + switch($property) { + case '{DAV:}displayname' : + $values['displayname'] = $newValue; + break; + case '{' . Plugin::NS_CARDDAV . '}addressbook-description' : + $values['description'] = $newValue; + break; + default : + throw new BadRequest('Unknown property: ' . $property); + } + + } + + // Fallback to make sure the displayname is set. Some clients may refuse + // to work with addressbooks not having a displayname. + if(is_null($values['displayname'])) { + $values['displayname'] = $url; + } + + $query = $this->db->getQueryBuilder(); + $query->insert('addressbooks') + ->values([ + 'uri' => $query->createParameter('uri'), + 'displayname' => $query->createParameter('displayname'), + 'description' => $query->createParameter('description'), + 'principaluri' => $query->createParameter('principaluri'), + 'synctoken' => $query->createParameter('synctoken'), + ]) + ->setParameters($values) + ->execute(); + } + + /** + * Deletes an entire addressbook and all its contents + * + * @param mixed $addressBookId + * @return void + */ + function deleteAddressBook($addressBookId) { + $query = $this->db->getQueryBuilder(); + $query->delete('cards') + ->where($query->expr()->eq('addressbookid', $query->createParameter('addressbookid'))) + ->setParameter('addressbookid', $addressBookId) + ->execute(); + + $query->delete('addressbookchanges') + ->where($query->expr()->eq('addressbookid', $query->createParameter('addressbookid'))) + ->setParameter('addressbookid', $addressBookId) + ->execute(); + + $query->delete('addressbooks') + ->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(); + } + + /** + * Returns all cards for a specific addressbook id. + * + * This method should return the following properties for each card: + * * carddata - raw vcard data + * * uri - Some unique url + * * lastmodified - A unix timestamp + * + * It's recommended to also return the following properties: + * * etag - A unique etag. This must change every time the card changes. + * * size - The size of the card in bytes. + * + * If these last two properties are provided, less time will be spent + * calculating them. If they are specified, you can also ommit carddata. + * This may speed up certain requests, especially with large cards. + * + * @param mixed $addressBookId + * @return array + */ + function getCards($addressBookId) { + $query = $this->db->getQueryBuilder(); + $query->select(['id', 'uri', 'lastmodified', 'etag', 'size', 'carddata']) + ->from('cards') + ->where($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId))); + + $cards = []; + + $result = $query->execute(); + while($row = $result->fetch()) { + $row['etag'] = '"' . $row['etag'] . '"'; + $row['carddata'] = $this->readBlob($row['carddata']); + $cards[] = $row; + } + $result->closeCursor(); + + return $cards; + } + + /** + * Returns a specfic card. + * + * The same set of properties must be returned as with getCards. The only + * exception is that 'carddata' is absolutely required. + * + * If the card does not exist, you must return false. + * + * @param mixed $addressBookId + * @param string $cardUri + * @return array + */ + function getCard($addressBookId, $cardUri) { + $query = $this->db->getQueryBuilder(); + $query->select(['id', 'uri', 'lastmodified', 'etag', 'size', 'carddata']) + ->from('cards') + ->where($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId))) + ->andWhere($query->expr()->eq('uri', $query->createNamedParameter($cardUri))) + ->setMaxResults(1); + + $result = $query->execute(); + $row = $result->fetch(); + if (!$row) { + return false; + } + $row['etag'] = '"' . $row['etag'] . '"'; + $row['carddata'] = $this->readBlob($row['carddata']); + + return $row; + } + + /** + * Returns a list of cards. + * + * This method should work identical to getCard, but instead return all the + * cards in the list as an array. + * + * If the backend supports this, it may allow for some speed-ups. + * + * @param mixed $addressBookId + * @param array $uris + * @return array + */ + function getMultipleCards($addressBookId, array $uris) { + $query = $this->db->getQueryBuilder(); + $query->select(['id', 'uri', 'lastmodified', 'etag', 'size', 'carddata']) + ->from('cards') + ->where($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId))) + ->andWhere($query->expr()->in('uri', $query->createParameter('uri'))) + ->setParameter('uri', $uris, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY); + + $cards = []; + + $result = $query->execute(); + while($row = $result->fetch()) { + $row['etag'] = '"' . $row['etag'] . '"'; + $row['carddata'] = $this->readBlob($row['carddata']); + $cards[] = $row; + } + $result->closeCursor(); + + return $cards; + } + + /** + * Creates a new card. + * + * The addressbook id will be passed as the first argument. This is the + * same id as it is returned from the getAddressBooksForUser method. + * + * The cardUri is a base uri, and doesn't include the full path. The + * cardData argument is the vcard body, and is passed as a string. + * + * It is possible to return an ETag from this method. This ETag is for the + * newly created resource, and must be enclosed with double quotes (that + * is, the string itself must contain the double quotes). + * + * You should only return the ETag if you store the carddata as-is. If a + * subsequent GET request on the same card does not have the same body, + * byte-by-byte and you did return an ETag here, clients tend to get + * confused. + * + * If you don't return an ETag, you can just return null. + * + * @param mixed $addressBookId + * @param string $cardUri + * @param string $cardData + * @return string|null + */ + function createCard($addressBookId, $cardUri, $cardData) { + $etag = md5($cardData); + + $query = $this->db->getQueryBuilder(); + $query->insert('cards') + ->values([ + 'carddata' => $query->createNamedParameter($cardData), + 'uri' => $query->createNamedParameter($cardUri), + 'lastmodified' => $query->createNamedParameter(time()), + 'addressbookid' => $query->createNamedParameter($addressBookId), + 'size' => $query->createNamedParameter(strlen($cardData)), + 'etag' => $query->createNamedParameter($etag), + ]) + ->execute(); + + $this->addChange($addressBookId, $cardUri, 1); + + return '"' . $etag . '"'; + } + + /** + * Updates a card. + * + * The addressbook id will be passed as the first argument. This is the + * same id as it is returned from the getAddressBooksForUser method. + * + * The cardUri is a base uri, and doesn't include the full path. The + * cardData argument is the vcard body, and is passed as a string. + * + * It is possible to return an ETag from this method. This ETag should + * match that of the updated resource, and must be enclosed with double + * quotes (that is: the string itself must contain the actual quotes). + * + * You should only return the ETag if you store the carddata as-is. If a + * subsequent GET request on the same card does not have the same body, + * byte-by-byte and you did return an ETag here, clients tend to get + * confused. + * + * If you don't return an ETag, you can just return null. + * + * @param mixed $addressBookId + * @param string $cardUri + * @param string $cardData + * @return string|null + */ + function updateCard($addressBookId, $cardUri, $cardData) { + + $etag = md5($cardData); + $query = $this->db->getQueryBuilder(); + $query->update('cards') + ->set('carddata', $query->createNamedParameter($cardData, \PDO::PARAM_LOB)) + ->set('lastmodified', $query->createNamedParameter(time())) + ->set('size', $query->createNamedParameter(strlen($cardData))) + ->set('etag', $query->createNamedParameter($etag)) + ->where($query->expr()->eq('uri', $query->createNamedParameter($cardUri))) + ->andWhere($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId))) + ->execute(); + + $this->addChange($addressBookId, $cardUri, 2); + + return '"' . $etag . '"'; + } + + /** + * Deletes a card + * + * @param mixed $addressBookId + * @param string $cardUri + * @return bool + */ + function deleteCard($addressBookId, $cardUri) { + $query = $this->db->getQueryBuilder(); + $ret = $query->delete('cards') + ->where($query->expr()->eq('addressbookid', $query->createNamedParameter($addressBookId))) + ->andWhere($query->expr()->eq('uri', $query->createNamedParameter($cardUri))) + ->execute(); + + $this->addChange($addressBookId, $cardUri, 3); + + return $ret === 1; + } + + /** + * The getChanges method returns all the changes that have happened, since + * the specified syncToken in the specified address book. + * + * 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 $addressBookId + * @param string $syncToken + * @param int $syncLevel + * @param int $limit + * @return array + */ + function getChangesForAddressBook($addressBookId, $syncToken, $syncLevel, $limit = null) { + // Current synctoken + $stmt = $this->db->prepare('SELECT `synctoken` FROM `*PREFIX*addressbooks` WHERE `id` = ?'); + $stmt->execute([ $addressBookId ]); + $currentToken = $stmt->fetchColumn(0); + + if (is_null($currentToken)) return null; + + $result = [ + 'syncToken' => $currentToken, + 'added' => [], + 'modified' => [], + 'deleted' => [], + ]; + + if ($syncToken) { + + $query = "SELECT `uri`, `operation` FROM `*PREFIX*addressbookchanges` WHERE `synctoken` >= ? AND `synctoken` < ? AND `addressbookid` = ? ORDER BY `synctoken`"; + if ($limit>0) { + $query .= " `LIMIT` " . (int)$limit; + } + + // Fetching all changes + $stmt = $this->db->prepare($query); + $stmt->execute([$syncToken, $currentToken, $addressBookId]); + + $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*cards` WHERE `addressbookid` = ?"; + $stmt = $this->db->prepare($query); + $stmt->execute([$addressBookId]); + + $result['added'] = $stmt->fetchAll(\PDO::FETCH_COLUMN); + } + return $result; + } + + /** + * Adds a change record to the addressbookchanges table. + * + * @param mixed $addressBookId + * @param string $objectUri + * @param int $operation 1 = add, 2 = modify, 3 = delete + * @return void + */ + protected function addChange($addressBookId, $objectUri, $operation) { + $sql = 'INSERT INTO `*PREFIX*addressbookchanges`(`uri`, `synctoken`, `addressbookid`, `operation`) SELECT ?, `synctoken`, ?, ? FROM `*PREFIX*addressbooks` WHERE `id` = ?'; + $stmt = $this->db->prepare($sql); + $stmt->execute([ + $objectUri, + $addressBookId, + $operation, + $addressBookId + ]); + $stmt = $this->db->prepare('UPDATE `*PREFIX*addressbooks` SET `synctoken` = `synctoken` + 1 WHERE `id` = ?'); + $stmt->execute([ + $addressBookId + ]); + } + + private function readBlob($cardData) { + if (is_resource($cardData)) { + return stream_get_contents($cardData); + } + + 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); + } + foreach($remove as $element) { + $this->unshare($path, $element); + } + } + + /** + * @param string $addressBookUri + * @param string $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; + } + + // remove the share if it already exists + $this->unshare($addressBookUri, $element); + + $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(); + } + + /** + * @param string $addressBookUri + * @param string $element + */ + 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 address book 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 @@ +<?php + +namespace OCA\DAV\CardDAV\Sharing; +use Sabre\CardDAV\IAddressBook; + +/** + * This interface represents a Calendar that can be shared with other users. + * + */ +interface IShareableAddressBook extends IAddressBook { + + /** + * Updates the list of shares. + * + * The first array is a list of people that are to be added to the + * addressbook. + * + * Every element in the add array has the following properties: + * * href - A url. Usually a mailto: address + * * commonName - Usually a first and last name, or false + * * summary - A description of the share, can also be false + * * readOnly - A boolean value + * + * Every element in the remove array is just the address string. + * + * @param array $add + * @param array $remove + * @return void + */ + function updateShares(array $add, array $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(); + +}
\ No newline at end of file diff --git a/apps/dav/lib/carddav/sharing/plugin.php b/apps/dav/lib/carddav/sharing/plugin.php new file mode 100644 index 00000000000..eeb5abc6d23 --- /dev/null +++ b/apps/dav/lib/carddav/sharing/plugin.php @@ -0,0 +1,218 @@ +<?php + +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; +use Sabre\DAV\XMLUtil; +use Sabre\HTTP\RequestInterface; +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. + * + * @var \Sabre\DAV\Server + */ + protected $server; + + /** + * This method should return a list of server-features. + * + * This is for example 'versioning' and is added to the DAV: header + * in an OPTIONS response. + * + * @return array + */ + function getFeatures() { + + return ['oc-addressbook-sharing']; + + } + + /** + * Returns a plugin name. + * + * Using this name other plugins will be able to access other plugins + * using Sabre\DAV\Server::getPlugin + * + * @return string + */ + function getPluginName() { + + return 'carddav-sharing'; + + } + + /** + * This initializes the plugin. + * + * This function is called by Sabre\DAV\Server, after + * addPlugin is called. + * + * This method should set up the required event subscriptions. + * + * @param Server $server + * @return void + */ + function initialize(Server $server) { + $this->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; + } + + // CSRF protection + $this->protectAgainstCSRF(); + + $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]; + + } + + 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/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 @@ +<?php + +namespace OCA\DAV\CardDAV; + +class UserAddressBooks extends \Sabre\CardDAV\UserAddressBooks { + + /** + * Returns a list of addressbooks + * + * @return array + */ + function getChildren() { + + $addressbooks = $this->carddavBackend->getAddressBooksForUser($this->principalUri); + $objs = []; + foreach($addressbooks as $addressbook) { + $objs[] = new AddressBook($this->carddavBackend, $addressbook); + } + return $objs; + + } + +} diff --git a/apps/dav/lib/connector/sabre/auth.php b/apps/dav/lib/connector/sabre/auth.php index 2e52a179d29..0394bfd6772 100644 --- a/apps/dav/lib/connector/sabre/auth.php +++ b/apps/dav/lib/connector/sabre/auth.php @@ -30,6 +30,8 @@ namespace OCA\DAV\Connector\Sabre; use Exception; +use OCP\ISession; +use OCP\IUserSession; use Sabre\DAV\Auth\Backend\AbstractBasic; use Sabre\DAV\Exception\NotAuthenticated; use Sabre\DAV\Exception\ServiceUnavailable; @@ -37,6 +39,21 @@ use Sabre\DAV\Exception\ServiceUnavailable; class Auth extends AbstractBasic { const DAV_AUTHENTICATED = 'AUTHENTICATED_TO_DAV_BACKEND'; + /** @var ISession */ + private $session; + /** @var IUserSession */ + private $userSession; + + /** + * @param ISession $session + * @param IUserSession $userSession + */ + public function __construct(ISession $session, + IUserSession $userSession) { + $this->session = $session; + $this->userSession = $userSession; + } + /** * Whether the user has initially authenticated via DAV * @@ -48,9 +65,9 @@ class Auth extends AbstractBasic { * @param string $username * @return bool */ - protected function isDavAuthenticated($username) { - return !is_null(\OC::$server->getSession()->get(self::DAV_AUTHENTICATED)) && - \OC::$server->getSession()->get(self::DAV_AUTHENTICATED) === $username; + public function isDavAuthenticated($username) { + return !is_null($this->session->get(self::DAV_AUTHENTICATED)) && + $this->session->get(self::DAV_AUTHENTICATED) === $username; } /** @@ -64,24 +81,21 @@ class Auth extends AbstractBasic { * @return bool */ protected function validateUserPass($username, $password) { - if (\OC_User::isLoggedIn() && - $this->isDavAuthenticated(\OC_User::getUser()) + if ($this->userSession->isLoggedIn() && + $this->isDavAuthenticated($this->userSession->getUser()->getUID()) ) { - \OC_Util::setupFS(\OC_User::getUser()); - \OC::$server->getSession()->close(); + \OC_Util::setupFS($this->userSession->getUser()->getUID()); + $this->session->close(); return true; } else { \OC_Util::setUpFS(); //login hooks may need early access to the filesystem - if(\OC_User::login($username, $password)) { - // make sure we use ownCloud's internal username here - // and not the HTTP auth supplied one, see issue #14048 - $ocUser = \OC_User::getUser(); - \OC_Util::setUpFS($ocUser); - \OC::$server->getSession()->set(self::DAV_AUTHENTICATED, $ocUser); - \OC::$server->getSession()->close(); + if($this->userSession->login($username, $password)) { + \OC_Util::setUpFS($this->userSession->getUser()->getUID()); + $this->session->set(self::DAV_AUTHENTICATED, $this->userSession->getUser()->getUID()); + $this->session->close(); return true; } else { - \OC::$server->getSession()->close(); + $this->session->close(); return false; } } @@ -95,10 +109,15 @@ class Auth extends AbstractBasic { * @return string|null */ public function getCurrentUser() { - $user = \OC_User::getUser(); - if($user && $this->isDavAuthenticated($user)) { + $user = $this->userSession->getUser() ? $this->userSession->getUser()->getUID() : null; + if($user !== null && $this->isDavAuthenticated($user)) { return $user; } + + if($user !== null && is_null($this->session->get(self::DAV_AUTHENTICATED))) { + return $user; + } + return null; } @@ -114,9 +133,9 @@ class Auth extends AbstractBasic { * @param string $realm * @return bool * @throws ServiceUnavailable + * @throws NotAuthenticated */ public function authenticate(\Sabre\DAV\Server $server, $realm) { - try { $result = $this->auth($server, $realm); return $result; @@ -136,12 +155,12 @@ class Auth extends AbstractBasic { */ private function auth(\Sabre\DAV\Server $server, $realm) { if (\OC_User::handleApacheAuth() || - (\OC_User::isLoggedIn() && is_null(\OC::$server->getSession()->get(self::DAV_AUTHENTICATED))) + ($this->userSession->isLoggedIn() && is_null($this->session->get(self::DAV_AUTHENTICATED))) ) { - $user = \OC_User::getUser(); + $user = $this->userSession->getUser()->getUID(); \OC_Util::setupFS($user); $this->currentUser = $user; - \OC::$server->getSession()->close(); + $this->session->close(); return true; } 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 @@ +<?php +/** + * @author Joas Schilling <nickvergessen@owncloud.com> + * + * @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 <http://www.gnu.org/licenses/> + * + */ + +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/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 @@ +<?php +/** + * @author Lukas Reschke <lukas@owncloud.com> + * + * @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 <http://www.gnu.org/licenses/> + * + */ + +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/file.php b/apps/dav/lib/connector/sabre/file.php index 9e515cdc687..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); } @@ -349,6 +357,7 @@ class File extends Node implements IFile { if (empty($info)) { throw new NotImplemented('Invalid chunk name'); } + $chunk_handler = new \OC_FileChunking($info); $bytesWritten = $chunk_handler->store($info['index'], $data); @@ -376,15 +385,17 @@ class File extends Node implements IFile { $exists = $this->fileView->file_exists($targetPath); try { - $this->emitPreHooks($exists, $targetPath); + $this->fileView->lockFile($targetPath, ILockingProvider::LOCK_SHARED); - $this->changeLock(ILockingProvider::LOCK_EXCLUSIVE); + $this->emitPreHooks($exists, $targetPath); + $this->fileView->changeLock($targetPath, ILockingProvider::LOCK_EXCLUSIVE); + /** @var \OC\Files\Storage\Storage $targetStorage */ + list($targetStorage, $targetInternalPath) = $this->fileView->resolvePath($targetPath); if ($needsPartFile) { // we first assembly the target file as a part file $partFile = $path . '/' . $info['name'] . '.ocTransferId' . $info['transferid'] . '.part'; - - + /** @var \OC\Files\Storage\Storage $targetStorage */ list($partStorage, $partInternalPath) = $this->fileView->resolvePath($partFile); @@ -392,8 +403,7 @@ class File extends Node implements IFile { // here is the final atomic rename $renameOkay = $targetStorage->moveFromStorage($partStorage, $partInternalPath, $targetInternalPath); - - $fileExists = $this->fileView->file_exists($targetPath); + $fileExists = $targetStorage->file_exists($targetInternalPath); if ($renameOkay === false || $fileExists === false) { \OCP\Util::writeLog('webdav', '\OC\Files\Filesystem::rename() failed', \OCP\Util::ERROR); // only delete if an error occurred and the target file was already created @@ -403,7 +413,7 @@ class File extends Node implements IFile { $partFile = null; $targetStorage->unlink($targetInternalPath); } - $this->changeLock(ILockingProvider::LOCK_SHARED); + $this->fileView->changeLock($targetPath, ILockingProvider::LOCK_SHARED); throw new Exception('Could not rename part file assembled from chunks'); } } else { @@ -419,7 +429,7 @@ class File extends Node implements IFile { } } - $this->changeLock(ILockingProvider::LOCK_SHARED); + $this->fileView->changeLock($targetPath, ILockingProvider::LOCK_SHARED); // since we skipped the view we need to scan and emit the hooks ourselves $this->fileView->getUpdater()->update($targetPath); @@ -427,6 +437,9 @@ class File extends Node implements IFile { $this->emitPostHooks($exists, $targetPath); $info = $this->fileView->getFileInfo($targetPath); + + $this->fileView->unlockFile($targetPath, ILockingProvider::LOCK_SHARED); + return $info->getEtag(); } catch (\Exception $e) { if ($partFile !== null) { @@ -469,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/filesplugin.php b/apps/dav/lib/connector/sabre/filesplugin.php index c9fc78a795f..d68397dcaa3 100644 --- a/apps/dav/lib/connector/sabre/filesplugin.php +++ b/apps/dav/lib/connector/sabre/filesplugin.php @@ -37,11 +37,14 @@ 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'; 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 @@ -96,9 +99,12 @@ 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; + $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']; @@ -132,6 +138,10 @@ class FilesPlugin extends \Sabre\DAV\ServerPlugin { if ($sourceDir !== $destinationDir) { $sourceFileInfo = $this->fileView->getFileInfo($source); + if ($sourceFileInfo === false) { + throw new \Sabre\DAV\Exception\NotFound($source . ' does not exist'); + } + if (!$sourceFileInfo->isDeletable()) { throw new \Sabre\DAV\Exception\Forbidden($source . " cannot be deleted"); } @@ -167,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) { @@ -197,6 +211,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/lockplugin.php b/apps/dav/lib/connector/sabre/lockplugin.php index c564e066f8e..8032d2b3fbf 100644 --- a/apps/dav/lib/connector/sabre/lockplugin.php +++ b/apps/dav/lib/connector/sabre/lockplugin.php @@ -39,18 +39,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} */ public function initialize(\Sabre\DAV\Server $server) { @@ -62,11 +50,11 @@ class LockPlugin extends ServerPlugin { public function getLock(RequestInterface $request) { // we cant listen on 'beforeMethod:PUT' due to order of operations with setting up the tree // so instead we limit ourselves to the PUT method manually - if ($request->getMethod() !== 'PUT') { + if ($request->getMethod() !== 'PUT' || isset($_SERVER['HTTP_OC_CHUNKED'])) { return; } try { - $node = $this->tree->getNodeForPath($request->getPath()); + $node = $this->server->tree->getNodeForPath($request->getPath()); } catch (NotFound $e) { return; } @@ -80,11 +68,11 @@ class LockPlugin extends ServerPlugin { } public function releaseLock(RequestInterface $request) { - if ($request->getMethod() !== 'PUT') { + if ($request->getMethod() !== 'PUT' || isset($_SERVER['HTTP_OC_CHUNKED'])) { 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/node.php b/apps/dav/lib/connector/sabre/node.php index 814aaceb077..daf82ba6f0d 100644 --- a/apps/dav/lib/connector/sabre/node.php +++ b/apps/dav/lib/connector/sabre/node.php @@ -207,6 +207,13 @@ abstract class Node implements \Sabre\DAV\INode { } /** + * @return string + */ + public function getInternalFileId() { + return $this->info->getId(); + } + + /** * @return string|null */ public function getDavPermissions() { @@ -238,6 +245,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/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/lib/connector/sabre/serverfactory.php b/apps/dav/lib/connector/sabre/serverfactory.php index b62f90ab802..0f0377e96bd 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); @@ -73,11 +107,19 @@ 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. + 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) { + // ensure the skeleton is copied + \OC::$server->getUserFolder(); + /** @var \OC\Files\View $view */ $view = $viewCallBack(); $rootInfo = $view->getFileInfo(''); diff --git a/apps/dav/lib/connector/sabre/tagsplugin.php b/apps/dav/lib/connector/sabre/tagsplugin.php index 7446d97790b..2f5937da25a 100644 --- a/apps/dav/lib/connector/sabre/tagsplugin.php +++ b/apps/dav/lib/connector/sabre/tagsplugin.php @@ -108,7 +108,7 @@ class TagsPlugin extends \Sabre\DAV\ServerPlugin public function initialize(\Sabre\DAV\Server $server) { $server->xmlNamespaces[self::NS_OWNCLOUD] = 'oc'; - $server->propertyMap[self::TAGS_PROPERTYNAME] = 'OC\\Connector\\Sabre\\TagList'; + $server->propertyMap[self::TAGS_PROPERTYNAME] = 'OCA\\DAV\\Connector\\Sabre\\TagList'; $this->server = $server; $this->server->on('propFind', array($this, 'handleGetProperties')); diff --git a/apps/dav/lib/files/custompropertiesbackend.php b/apps/dav/lib/files/custompropertiesbackend.php new file mode 100644 index 00000000000..83776997a52 --- /dev/null +++ b/apps/dav/lib/files/custompropertiesbackend.php @@ -0,0 +1,271 @@ +<?php +/** + * @author Lukas Reschke <lukas@owncloud.com> + * @author Morris Jobke <hey@morrisjobke.de> + * @author Thomas Müller <thomas.mueller@tmit.eu> + * @author Vincent Petry <pvince81@owncloud.com> + * + * @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 <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\DAV\Files; + +use OCP\IDBConnection; +use OCP\IUser; +use Sabre\DAV\PropertyStorage\Backend\BackendInterface; +use Sabre\DAV\PropFind; +use Sabre\DAV\PropPatch; +use Sabre\DAV\Tree; + +class CustomPropertiesBackend implements BackendInterface { + + /** + * Ignored properties + * + * @var array + */ + private $ignoredProperties = array( + '{DAV:}getcontentlength', + '{DAV:}getcontenttype', + '{DAV:}getetag', + '{DAV:}quota-used-bytes', + '{DAV:}quota-available-bytes', + '{DAV:}quota-available-bytes', + '{http://owncloud.org/ns}permissions', + '{http://owncloud.org/ns}downloadURL', + '{http://owncloud.org/ns}dDC', + '{http://owncloud.org/ns}size', + ); + + /** + * @var Tree + */ + private $tree; + + /** + * @var IDBConnection + */ + private $connection; + + /** + * @var IUser + */ + private $user; + + /** + * Properties cache + * + * @var array + */ + private $cache = []; + + /** + * @param Tree $tree node tree + * @param IDBConnection $connection database connection + * @param IUser $user owner of the tree and properties + */ + public function __construct( + Tree $tree, + IDBConnection $connection, + IUser $user) { + $this->tree = $tree; + $this->connection = $connection; + $this->user = $user->getUID(); + } + + /** + * Fetches properties for a path. + * + * @param string $path + * @param PropFind $propFind + * @return void + */ + public function propFind($path, PropFind $propFind) { + + $requestedProps = $propFind->get404Properties(); + + // these might appear + $requestedProps = array_diff( + $requestedProps, + $this->ignoredProperties + ); + + if (empty($requestedProps)) { + return; + } + + $props = $this->getProperties($path, $requestedProps); + foreach ($props as $propName => $propValue) { + $propFind->set($propName, $propValue); + } + } + + /** + * Updates properties for a path + * + * @param string $path + * @param PropPatch $propPatch + * + * @return void + */ + public function propPatch($path, PropPatch $propPatch) { + $propPatch->handleRemaining(function($changedProps) use ($path) { + return $this->updateProperties($path, $changedProps); + }); + } + + /** + * This method is called after a node is deleted. + * + * @param string $path path of node for which to delete properties + */ + public function delete($path) { + $statement = $this->connection->prepare( + 'DELETE FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ?' + ); + $statement->execute(array($this->user, $path)); + $statement->closeCursor(); + + unset($this->cache[$path]); + } + + /** + * This method is called after a successful MOVE + * + * @param string $source + * @param string $destination + * + * @return void + */ + public function move($source, $destination) { + $statement = $this->connection->prepare( + 'UPDATE `*PREFIX*properties` SET `propertypath` = ?' . + ' WHERE `userid` = ? AND `propertypath` = ?' + ); + $statement->execute(array($destination, $this->user, $source)); + $statement->closeCursor(); + } + + /** + * Returns a list of properties for this nodes.; + * @param string $path + * @param array $requestedProperties requested properties or empty array for "all" + * @return array + * @note The properties list is a list of propertynames the client + * requested, encoded as xmlnamespace#tagName, for example: + * http://www.example.org/namespace#author If the array is empty, all + * properties should be returned + */ + private function getProperties($path, array $requestedProperties) { + if (isset($this->cache[$path])) { + return $this->cache[$path]; + } + + // TODO: chunking if more than 1000 properties + $sql = 'SELECT * FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ?'; + + $whereValues = array($this->user, $path); + $whereTypes = array(null, null); + + if (!empty($requestedProperties)) { + // request only a subset + $sql .= ' AND `propertyname` in (?)'; + $whereValues[] = $requestedProperties; + $whereTypes[] = \Doctrine\DBAL\Connection::PARAM_STR_ARRAY; + } + + $result = $this->connection->executeQuery( + $sql, + $whereValues, + $whereTypes + ); + + $props = []; + while ($row = $result->fetch()) { + $props[$row['propertyname']] = $row['propertyvalue']; + } + + $result->closeCursor(); + + $this->cache[$path] = $props; + return $props; + } + + /** + * Update properties + * + * @param string $path node for which to update properties + * @param array $properties array of properties to update + * + * @return bool + */ + private function updateProperties($path, $properties) { + + $deleteStatement = 'DELETE FROM `*PREFIX*properties`' . + ' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?'; + + $insertStatement = 'INSERT INTO `*PREFIX*properties`' . + ' (`userid`,`propertypath`,`propertyname`,`propertyvalue`) VALUES(?,?,?,?)'; + + $updateStatement = 'UPDATE `*PREFIX*properties` SET `propertyvalue` = ?' . + ' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?'; + + // TODO: use "insert or update" strategy ? + $existing = $this->getProperties($path, array()); + $this->connection->beginTransaction(); + foreach ($properties as $propertyName => $propertyValue) { + // If it was null, we need to delete the property + if (is_null($propertyValue)) { + if (array_key_exists($propertyName, $existing)) { + $this->connection->executeUpdate($deleteStatement, + array( + $this->user, + $path, + $propertyName + ) + ); + } + } else { + if (!array_key_exists($propertyName, $existing)) { + $this->connection->executeUpdate($insertStatement, + array( + $this->user, + $path, + $propertyName, + $propertyValue + ) + ); + } else { + $this->connection->executeUpdate($updateStatement, + array( + $propertyValue, + $this->user, + $path, + $propertyName + ) + ); + } + } + } + + $this->connection->commit(); + unset($this->cache[$path]); + + return true; + } + +} diff --git a/apps/dav/lib/files/fileshome.php b/apps/dav/lib/files/fileshome.php new file mode 100644 index 00000000000..5e145a2b002 --- /dev/null +++ b/apps/dav/lib/files/fileshome.php @@ -0,0 +1,80 @@ +<?php + +namespace OCA\DAV\Files; + +use OCA\DAV\Connector\Sabre\Directory; +use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\ICollection; +use Sabre\DAV\SimpleCollection; +use Sabre\HTTP\URLUtil; + +class FilesHome implements ICollection { + + /** + * FilesHome constructor. + * + * @param array $principalInfo + */ + public function __construct($principalInfo) { + $this->principalInfo = $principalInfo; + } + + function createFile($name, $data = null) { + return $this->impl()->createFile($name, $data); + } + + function createDirectory($name) { + $this->impl()->createDirectory($name); + } + + function getChild($name) { + return $this->impl()->getChild($name); + } + + function getChildren() { + return $this->impl()->getChildren(); + } + + function childExists($name) { + return $this->impl()->childExists($name); + } + + function delete() { + $this->impl()->delete(); + } + + function getName() { + list(,$name) = URLUtil::splitPath($this->principalInfo['uri']); + return $name; + } + + function setName($name) { + throw new Forbidden('Permission denied to rename this folder'); + } + + /** + * Returns the last modification time, as a unix timestamp + * + * @return int + */ + function getLastModified() { + return $this->impl()->getLastModified(); + } + + /** + * @return Directory + */ + private function impl() { + // + // TODO: we need to mount filesystem of the give user + // + $user = \OC::$server->getUserSession()->getUser(); + if ($this->getName() !== $user->getUID()) { + return new SimpleCollection($this->getName()); + } + $view = \OC\Files\Filesystem::getView(); + $rootInfo = $view->getFileInfo(''); + $impl = new Directory($view, $rootInfo); + return $impl; + } +} diff --git a/apps/dav/lib/files/rootcollection.php b/apps/dav/lib/files/rootcollection.php new file mode 100644 index 00000000000..bbe3c784a53 --- /dev/null +++ b/apps/dav/lib/files/rootcollection.php @@ -0,0 +1,28 @@ +<?php + +namespace OCA\DAV\Files; + +use Sabre\DAVACL\AbstractPrincipalCollection; +use Sabre\DAVACL\IPrincipal; + +class RootCollection extends AbstractPrincipalCollection { + + /** + * This method returns a node for a principal. + * + * The passed array contains principal information, and is guaranteed to + * at least contain a uri item. Other properties may or may not be + * supplied by the authentication backend. + * + * @param array $principalInfo + * @return IPrincipal + */ + function getChildForPrincipal(array $principalInfo) { + return new FilesHome($principalInfo); + } + + function getName() { + return 'files'; + } + +} diff --git a/apps/dav/lib/rootcollection.php b/apps/dav/lib/rootcollection.php new file mode 100644 index 00000000000..672e0a98684 --- /dev/null +++ b/apps/dav/lib/rootcollection.php @@ -0,0 +1,49 @@ +<?php + +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\DAV\SimpleCollection; + +class RootCollection extends SimpleCollection { + + public function __construct() { + $config = \OC::$server->getConfig(); + $db = \OC::$server->getDatabaseConnection(); + $principalBackend = new Principal( + $config, + \OC::$server->getUserManager() + ); + // as soon as debug mode is enabled we allow listing of principals + $disableListing = !$config->getSystemValue('debug', false); + + // setup the first level of the dav tree + $principalCollection = new Collection($principalBackend); + $principalCollection->disableListing = $disableListing; + $filesCollection = new Files\RootCollection($principalBackend); + $filesCollection->disableListing = $disableListing; + $caldavBackend = new CalDavBackend($db); + $calendarRoot = new CalendarRoot($principalBackend, $caldavBackend); + $calendarRoot->disableListing = $disableListing; + + $cardDavBackend = new CardDavBackend(\OC::$server->getDatabaseConnection(), $principalBackend); + + $addressBookRoot = new AddressBookRoot($principalBackend, $cardDavBackend); + $addressBookRoot->disableListing = $disableListing; + + $children = [ + $principalCollection, + $filesCollection, + $calendarRoot, + $addressBookRoot, + ]; + + parent::__construct('root', $children); + } + +} diff --git a/apps/dav/lib/server.php b/apps/dav/lib/server.php new file mode 100644 index 00000000000..44afcf23df6 --- /dev/null +++ b/apps/dav/lib/server.php @@ -0,0 +1,85 @@ +<?php + +namespace OCA\DAV; + +use OCA\DAV\Connector\Sabre\Auth; +use OCA\DAV\Connector\Sabre\BlockLegacyClientPlugin; +use OCA\DAV\Files\CustomPropertiesBackend; +use OCP\IRequest; +use Sabre\DAV\Auth\Plugin; +use Sabre\HTTP\Util; + +class Server { + + /** @var IRequest */ + private $request; + + 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); + + // Backends + $authBackend = new Auth( + \OC::$server->getSession(), + \OC::$server->getUserSession() + ); + + // Set URL explicitly due to reverse-proxy situations + $this->server->httpRequest->setUrl($this->request->getRequestUri()); + $this->server->setBaseUri($this->baseUri); + + $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)); + + // 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()); + $this->server->addPlugin(new CardDAV\Sharing\Plugin($authBackend, \OC::$server->getRequest())); + + // addressbook plugins + $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 + $user = \OC::$server->getUserSession()->getUser(); + if (!is_null($user)) { + $this->server->addPlugin( + new \Sabre\DAV\PropertyStorage\Plugin( + new CustomPropertiesBackend( + $this->server->tree, + \OC::$server->getDatabaseConnection(), + \OC::$server->getUserSession()->getUser() + ) + ) + ); + } + }); + } + + public function exec() { + $this->server->exec(); + } +} 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 @@ +<?xml version="1.0" encoding="utf-8" ?> + <CS:share xmlns:D="DAV:" xmlns:CS="urn:ietf:params:xml:ns:carddav"> + <CS:set> + <D:href>principal:principals/admin</D:href> + <CS:read-write /> + </CS:set> + </CS:share> diff --git a/apps/dav/tests/travis/caldavtest/config/serverinfo.dtd b/apps/dav/tests/travis/caldavtest/config/serverinfo.dtd new file mode 100644 index 00000000000..d642f4f90cd --- /dev/null +++ b/apps/dav/tests/travis/caldavtest/config/serverinfo.dtd @@ -0,0 +1,43 @@ +<!-- + Copyright (c) 2006-2015 Apple Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<!ELEMENT serverinfo (host, path, nonsslport, sslport, unix?, + host2?, nonsslport2?, sslport2?, unix2?, + authtype?, waitcount?, waitdelay?, waitsuccess?, + features?, substitutions)? > + + <!ELEMENT host (#PCDATA)> + <!ELEMENT path (#PCDATA)> + <!ELEMENT nonsslport (#PCDATA)> + <!ELEMENT sslport (#PCDATA)> + <!ELEMENT unix (#PCDATA)> + <!ELEMENT host2 (#PCDATA)> + <!ELEMENT nonsslport2 (#PCDATA)> + <!ELEMENT sslport2 (#PCDATA)> + <!ELEMENT unix2 (#PCDATA)> + <!ELEMENT authtype (#PCDATA)> + <!ELEMENT waitdelay (#PCDATA)> + <!ELEMENT waitcount (#PCDATA)> + <!ELEMENT waitsuccess (#PCDATA)> + <!ELEMENT features (feature*)> + <!ELEMENT feature (#PCDATA)> + <!ELEMENT substitutions (substitution|repeat)*> + <!ELEMENT repeat (substitution+)> + <!ATTLIST repeat count CDATA "1"> + <!ELEMENT substitution (key, value)> + <!ELEMENT key (#PCDATA)> + <!ELEMENT value (#PCDATA)> + diff --git a/apps/dav/tests/travis/caldavtest/config/serverinfo.xml b/apps/dav/tests/travis/caldavtest/config/serverinfo.xml new file mode 100644 index 00000000000..b85a8639e4e --- /dev/null +++ b/apps/dav/tests/travis/caldavtest/config/serverinfo.xml @@ -0,0 +1,854 @@ +<?xml version="1.0" standalone="no"?> + +<!DOCTYPE serverinfo SYSTEM + "/home/deepdiver/Development/ownCloud/master/apps/dav/tests/travis/caldavtest/config/serverinfo.dtd"> + +<!-- + Copyright (c) 2006-2015 Apple Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<serverinfo> + <host>localhost</host> + <nonsslport>8888</nonsslport> + <authtype>basic</authtype> + <!-- <unix>/tmp/caldavd_requests/unsecured.sock</unix> --> + + <waitcount>120</waitcount> + <waitdelay>0.25</waitdelay> + <waitsuccess>30</waitsuccess> + + <features> + <!-- Generic WebDAV extensions --> + <feature>COPY Method</feature> <!-- COPY method --> + <feature>MOVE Method</feature> <!-- MOVE method --> + <feature>Extended MKCOL</feature> <!-- Extended MKCOL --> + + <!-- ACL related --> + <feature>ACL Method</feature> <!-- ACL method --> + <feature>acl-principal-prop-set REPORT</feature> <!-- ACL acl-principal-prop-set REPORT --> + <feature>principal-match REPORT</feature> <!-- ACL principal-match REPORT --> + <feature>principal-property-search REPORT</feature> <!-- ACL principal-property-search REPORT --> + <feature>principal-search-property-set REPORT</feature> <!-- ACL principal-search-property-set REPORT --> + <feature>calendarserver-principal-search REPORT</feature> <!-- ACL calendarserver-principal-search REPORT --> + + <feature>add-member</feature> <!-- Add-member used to create resources --> + <!-- <feature>auth-on-root</feature> --> <!-- Whether the server requires authentication on the root URI --> + <feature>brief</feature> <!-- Brief header for PROPFIND, REPORT --> + <feature>bulk-post</feature> <!-- Bulk POST requests --> + <feature>ctag</feature> <!-- ctag extension --> + <feature>current-user-principal</feature> <!-- current-user-principal extension --> + <feature>directory listing</feature> <!-- GET on collection --> + <feature>extended-principal-search</feature> <!-- Extended principal-property-search REPORT extension --> + <feature>expand-property</feature> <!-- Expand property REPORT --> + <feature>only-proxy-groups</feature> <!-- Group-membership only includes delegated-to groups --> + <feature>limits</feature> <!-- max-collections and max-resources limits --> + <feature>own-root</feature> <!-- / is owned by this service --> + <feature>prefer</feature> <!-- Prefer header overall support --> + <feature>prefer-minimal</feature> <!-- Prefer header return=minimal --> + <feature>prefer-representation</feature> <!-- Prefer header return=representation --> + <feature>prefer-noroot</feature> <!-- Prefer header depth-noroot --> + <feature>quota</feature> <!-- WebDAV QUOTA --> + <!-- <feature>quota-on-resources</feature> --> <!-- WebDAV QUOTA on calendar and address book object resources --> + <feature>resource-id</feature> <!-- WebDAV BIND DAV:resource-id property --> + <feature>sync-report</feature> <!-- WebDAV collection sync REPORT --> + <!-- <feature>sync-report-limit</feature> --> <!-- WebDAV collection sync REPORT DAV:limit support --> + <feature>sync-report-home</feature> <!-- WebDAV collection sync REPORT on Homes --> + <feature>sync-report-config-token</feature> <!-- Sync REPORT token includes configuration component --> + <feature>well-known</feature> <!-- well-known feature --> + + <!-- <feature>per-object-ACLs</feature> --> <!-- ACL for objects in calendar/address books --> + <!-- <feature>regular-collection</feature> --> <!-- Regular collections allowed in calendar/address book homes --> + + <feature>json-data</feature> <!-- jCal and jCard support --> + + <!-- CalendarServer specific extensions --> + <feature>control-api</feature> <!-- Control API support --> + + <!-- CalDAV specific extension --> + <feature>caldav</feature> <!-- Basic CalDAV feature enabler --> + <feature>attachments-collection</feature> <!-- Server uses a collection in same WebDAV tree to store attachments --> + <feature>auto-accept</feature> <!-- Auto-accept for rooms & locations --> + <feature>auto-accept-modes</feature> <!-- Auto-accept modes --> + <feature>client-fix-TRANSP</feature> <!-- fix client TRANSP --> + <!-- <feature>dropbox</feature> --> <!-- dropbox extension --> + <feature>default-alarms</feature> <!-- default alarms extension --> + <feature>EMAIL parameter</feature> <!-- Server normalizes cuaddress and adds EMAIL parameter --> + <feature>extended-freebusy</feature> <!-- Extended freebusy response --> + <feature>freebusy-url</feature> <!-- Freebusy URL --> + <feature>group-attendee-expansion</feature> <!-- Auto-expansion of group attendees --> + <feature>implicit-scheduling</feature> <!-- CalDAV scheduling - implicit --> + <feature>location-resource-tracking</feature> <!-- Server tracks who makes unscheduled changes to locations and resources --> + <feature>managed-attachments</feature> <!-- CalDAV Managed Attachments --> + <feature>maskuid</feature> <!-- maskuid extension --> + <feature>no-duplicate-uids</feature> <!-- duplicate UIDs in same home not supported --> + <feature>partstat-timestamp</feature> <!-- Time stamps when PARTSTAT changes extension --> + <!-- <feature>podding</feature> --> <!-- Podded server --> + <feature>private-comments</feature> <!-- private-comments extension --> + <feature>private-events</feature> <!-- private-events extension --> + <feature>proxy</feature> <!-- calendar-user-proxy extension --> + <!-- <feature>proxy-authz</feature> --> <!-- sudo user extension --> + <feature>recurrence-splitting</feature> <!-- Recurring components can be split --> + <feature>remove-duplicate-alarms</feature> <!-- Server removes any duplicate alarms on PUT --> + <feature>query-extended</feature> <!-- calendar-query-extended extension --> + <feature>shared-calendars</feature> <!-- Shared calendars extension --> + <feature>share-calendars-to-groups</feature> <!-- Share calendars to groups extension --> + <feature>schedule-changes</feature> <!-- schedule-changes property extension --> + <feature>split-calendars</feature> <!-- Calendars are split by component type --> + <feature>supported-component-sets</feature> <!-- CALDAV:supported-calendar-component-sets on calendar homes --> + <feature>supported-component-sets-one</feature> <!-- Only single component calendars allowed to be created --> + <feature>timerange-low-limit</feature> <!-- Time-range only valid one year back --> + <feature>timerange-high-limit</feature> <!-- Time-range only valid 5 years ahead --> + <feature>timezones-by-reference</feature> <!-- Timezones by reference enabled --> + <feature>timezone-service</feature> <!-- Timezone service extension for Wiki --> + <feature>timezone-std-service</feature> <!-- Timezone standard service extension --> + <!-- <feature>trash-collection</feature> --> <!-- Trash collection enabled --> + <feature>travel-time-busy</feature> <!-- Travel time appears as busy --> + <feature>vavailability</feature> <!-- VAVAILABILITY on inbox --> + <!-- <feature>vpoll</feature> --> <!-- VPOLL support for store and scheduling --> + <feature>webcal</feature> <!-- Internet calendar subscription via GET on calendar collection --> + + <!-- CardDAV specific extension --> + <feature>carddav</feature> <!-- Basic CardDAV feature enabler --> + <feature>default-addressbook</feature> <!-- Default address book behavior --> + <feature>shared-addressbooks</feature> <!-- Shared address books extension --> + <feature>shared-addressbook-groups</feature> <!-- Shared address book groups extension --> + <feature>directory-gateway</feature> <!-- Directory gateway extension --> + + </features> + + <substitutions> + <!-- Useful xpath shortcuts for verifiers --> + <substitution> + <key>$multistatus-response-prefix:</key> + <value>/{DAV:}multistatus/{DAV:}response</value> + </substitution> + <substitution> + <key>$multistatus-href-prefix:</key> + <value>/{DAV:}multistatus/{DAV:}response/{DAV:}href</value> + </substitution> + <substitution> + <key>$verify-response-prefix:</key> + <value>{DAV:}response/{DAV:}propstat/{DAV:}prop</value> + </substitution> + <substitution> + <key>$verify-property-prefix:</key> + <value>/{DAV:}multistatus/{DAV:}response/{DAV:}propstat/{DAV:}prop</value> + </substitution> + <substitution> + <key>$verify-bad-response:</key> + <value>/{DAV:}multistatus/{DAV:}response/{DAV:}status</value> + </substitution> + <substitution> + <key>$verify-error-response:</key> + <value>/{DAV:}multistatus/{DAV:}response/{DAV:}error</value> + </substitution> + <substitution> + <key>$CALDAV:</key> + <value>urn:ietf:params:xml:ns:caldav</value> + </substitution> + <substitution> + <key>$CARDDAV:</key> + <value>urn:ietf:params:xml:ns:carddav</value> + </substitution> + <substitution> + <key>$CS:</key> + <value>http://calendarserver.org/ns/</value> + </substitution> + + <!-- Server configuration settings --> + <!-- $host: and $hostssl: are implicitly added by CalDAVTester based + on the host/nonsslport/sslport values and ssl command line switch --> + + <!-- relative path to caldav root--> + <substitution> + <key>$root:</key> + <value>/remote.php/dav/</value> + </substitution> + + <!-- relative path to main principal collection--> + <substitution> + <key>$principalcollection:</key> + <value>$root:principals/</value> + </substitution> + + <!-- the core recored type collections--> + <substitution> + <key>$uidstype:</key> + <value>__uids__</value> + </substitution> + <substitution> + <key>$userstype:</key> + <value>users</value> + </substitution> + <substitution> + <key>$groupstype:</key> + <value>groups</value> + </substitution> + <substitution> + <key>$locationstype:</key> + <value>locations</value> + </substitution> + <substitution> + <key>$resourcestype:</key> + <value>resources</value> + </substitution> + + <!-- relative path to record type principal collections--> + <substitution> + <key>$principals_uids:</key> + <value>$principalcollection:$uidstype:/</value> + </substitution> + <substitution> + <key>$principals_users:</key> + <value>$principalcollection:$userstype:/</value> + </substitution> + <substitution> + <key>$principals_groups:</key> + <value>$principalcollection:$groupstype:/</value> + </substitution> + <substitution> + <key>$principals_resources:</key> + <value>$principalcollection:$resourcestype:/</value> + </substitution> + <substitution> + <key>$principals_locations:</key> + <value>$principalcollection:$locationstype:/</value> + </substitution> + + <!-- relative path to calendars collection--> + <substitution> + <key>$calendars:</key> + <value>$root:calendars/</value> + </substitution> + + <!-- relative path to record type calendar collections--> + <substitution> + <key>$calendars_uids:</key> + <value>$calendars:$uidstype:/</value> + </substitution> + <substitution> + <key>$calendars_users:</key> + <value>$calendars:$userstype:/</value> + </substitution> + <substitution> + <key>$calendars_resources:</key> + <value>$calendars:$resourcestype:/</value> + </substitution> + <substitution> + <key>$calendars_locations:</key> + <value>$calendars:$locationstype:/</value> + </substitution> + + <!-- primary calendar name--> + <substitution> + <key>$calendar:</key> + <value>calendar</value> + </substitution> + + <!-- primary tasks-only calendar name--> + <substitution> + <key>$tasks:</key> + <value>tasks</value> + </substitution> + + <!-- primary polls-only calendar name--> + <substitution> + <key>$polls:</key> + <value>polls</value> + </substitution> + + <!-- inbox name--> + <substitution> + <key>$inbox:</key> + <value>inbox</value> + </substitution> + + <!-- outbox name--> + <substitution> + <key>$outbox:</key> + <value>outbox</value> + </substitution> + + <!-- dropbox name--> + <substitution> + <key>$dropbox:</key> + <value>dropbox</value> + </substitution> + + <!-- attachments name--> + <substitution> + <key>$attachments:</key> + <value>dropbox</value> + </substitution> + + <!-- notification name--> + <substitution> + <key>$notification:</key> + <value>notification</value> + </substitution> + + <!-- freebusy name--> + <substitution> + <key>$freebusy:</key> + <value>freebusy</value> + </substitution> + + <!-- Sync home collection items - use "-" to include the home resource--> + <substitution> + <key>$calendar_home_items_initial_sync:</key> + <value>[-,$calendar:/,$tasks:/,$inbox:/,$outbox:/,$freebusy:,$notification:/]</value> + </substitution> + + <!-- Sync collection extra items - use "-" to include the collection--> + <substitution> + <key>$calendar_sync_extra_items:</key> + <value>[-]</value> + </substitution> + + <!-- Sync collection extra count - gets added to the totalcount value--> + <substitution> + <key>$calendar_sync_extra_count:</key> + <value>1</value> <!-- the request-uri resource is returned when no token passed--> + </substitution> + + <!-- server-to-server inbox--> + <substitution> + <key>$servertoserver:</key> + <value>$root:inbox</value> + </substitution> + + <!-- timezone service--> + <substitution> + <key>$timezoneservice:</key> + <value>$root:timezones</value> + </substitution> + + <!-- timezone std service--> + <substitution> + <key>$timezonestdservice:</key> + <value>$root:stdtimezones</value> + </substitution> + + <!-- relative path to addressbooks collection--> + <substitution> + <key>$addressbooks:</key> + <value>$root:addressbooks/</value> + </substitution> + + <!-- relative path to record type addressbook collections--> + <substitution> + <key>$addressbooks_uids:</key> + <value>$addressbooks:$uidstype:/</value> + </substitution> + <substitution> + <key>$addressbooks_users:</key> + <value>$addressbooks:$userstype:/</value> + </substitution> + + <!-- primary addressbook name --> + <substitution> + <key>$addressbook:</key> + <value>addressbook</value> + </substitution> + + <!-- directory name --> + <substitution> + <key>$directory:</key> + <value>$root:directory/</value> + </substitution> + + <!-- POST add-member URI suffix --> + <substitution> + <key>$add-member:</key> + <value>;add-member</value> + </substitution> + + <!-- user id for admin user --> + <substitution> + <key>$useradmin:</key> + <value>admin</value> + </substitution> + <!-- guid for admin user --> + <substitution> + <key>$useradminguid:</key> + <value>0C8BDE62-E600-4696-83D3-8B5ECABDFD2E</value> + </substitution> + <!-- password for admin user --> + <substitution> + <key>$pswdadmin:</key> + <value>admin</value> + </substitution> + + <!-- relative path to admin principal resource--> + <substitution> + <key>$principal_admin:</key> + <value>$principals_users:$useradmin:/</value> + </substitution> + <substitution> + <key>$principaluri_admin:</key> + <value>$principals_uids:$useradminguid:/</value> + </substitution> + + <!-- user id for apprentice user --> + <substitution> + <key>$userapprentice:</key> + <value>apprentice</value> + </substitution> + <!-- guid for apprentice user --> + <substitution> + <key>$userapprenticeguid:</key> + <value>29B6C503-11DF-43EC-8CCA-40C7003149CE</value> + </substitution> + <!-- password for admin user --> + <substitution> + <key>$pswdapprentice:</key> + <value>apprentice</value> + </substitution> + + <!-- relative path to apprentice principal resource--> + <substitution> + <key>$principal_apprentice:</key> + <value>$principals_users:$userapprentice:/</value> + </substitution> + <substitution> + <key>$principaluri_apprentice:</key> + <value>$principals_uids:$userapprenticeguid:/</value> + </substitution> + + <!-- user id for proxy user --> + <substitution> + <key>$userproxy:</key> + <value>superuser</value> + </substitution> + <!-- password for proxy user --> + <substitution> + <key>$pswdproxy:</key> + <value>superuser</value> + </substitution> + + <!-- Forty user accounts --> + <repeat count="40"> + <!-- user id --> + <substitution> + <key>$userid%d:</key> + <value>user%02d</value> + </substitution> + <!-- user guid --> + <substitution> + <key>$userguid%d:</key> + <value>10000000-0000-0000-0000-000000000%03d</value> + </substitution> + <!-- user name --> + <substitution> + <key>$username%d:</key> + <value>User %02d</value> + </substitution> + <!-- user name URI encoded --> + <substitution> + <key>$username-encoded%d:</key> + <value>User%%20%02d</value> + </substitution> + <!-- first name --> + <substitution> + <key>$firstname%d:</key> + <value>User</value> + </substitution> + <!-- last name --> + <substitution> + <key>$lastname%d:</key> + <value>%02d</value> + </substitution> + <!-- password --> + <substitution> + <key>$pswd%d:</key> + <value>user%02d</value> + </substitution> + <!-- relative path to user principal resource--> + <substitution> + <key>$principal%d:</key> + <value>$principals_users:$userid%d:/</value> + </substitution> + <substitution> + <key>$principaluri%d:</key> + <value>$principalcollection:$userid%d:/</value> + </substitution> + <substitution> + <key>$principal%dnoslash:</key> + <value>$principals_users:$userid%d:</value> + </substitution> + + <!-- relative path to user calendar home--> + <substitution> + <key>$calendarhome%d:</key> + <value>$calendars_uids:$userguid%d:</value> + </substitution> + <!-- relative path to user alternate calendar home--> + <substitution> + <key>$calendarhomealt%d:</key> + <value>$calendars_users:$userid%d:</value> + </substitution> + <!-- relative path to user calendar--> + <substitution> + <key>$calendarpath%d:</key> + <value>$calendarhome%d:/$calendar:</value> + </substitution> + <!-- relative path to user alternate calendar--> + <substitution> + <key>$calendarpathalt%d:</key> + <value>$calendarhomealt%d:/$calendar:</value> + </substitution> + <!-- relative path to user tasks calendar--> + <substitution> + <key>$taskspath%d:</key> + <value>$calendarhome%d:/$tasks:</value> + </substitution> + <!-- relative path to user polls calendar--> + <substitution> + <key>$pollspath%d:</key> + <value>$calendarhome%d:/$polls:</value> + </substitution> + <!-- relative path to user inbox--> + <substitution> + <key>$inboxpath%d:</key> + <value>$calendarhome%d:/$inbox:</value> + </substitution> + <!-- relative path to user outbox--> + <substitution> + <key>$outboxpath%d:</key> + <value>$calendarhome%d:/$outbox:</value> + </substitution> + <!-- relative path to user dropbox--> + <substitution> + <key>$dropboxpath%d:</key> + <value>$calendarhome%d:/$dropbox:</value> + </substitution> + <!-- relative path to user notification--> + <substitution> + <key>$notificationpath%d:</key> + <value>$calendarhome%d:/$notification:</value> + </substitution> + <!-- relative path to user freebusy--> + <substitution> + <key>$freebusypath%d:</key> + <value>$calendarhome%d:/$freebusy:</value> + </substitution> + <substitution> + <key>$email%d:</key> + <value>$userid%d:@example.com</value> + </substitution> + <!-- calendar user address of user--> + <substitution> + <key>$cuaddr%d:</key> + <value>mailto:$email%d:</value> + </substitution> + <substitution> + <key>$cuaddralt%d:</key> + <value>$cuaddr%d:</value> + </substitution> + <substitution> + <key>$cuaddraltnoslash%d:</key> + <value>$cuaddr%d:</value> + </substitution> + <substitution> + <key>$cuaddrurn%d:</key> + <value>urn:x-uid:$userguid%d:</value> + </substitution> + + <!-- relative path to user addressbook home--> + <substitution> + <key>$addressbookhome%d:</key> + <value>$addressbooks_uids:$userguid%d:</value> + </substitution> + <!-- relative path to user addressbook--> + <substitution> + <key>$addressbookpath%d:</key> + <value>$addressbookhome%d:/$addressbook:</value> + </substitution> + </repeat> + + <!-- Ten public accounts --> + <repeat count="10"> + <!-- user id --> + <substitution> + <key>$publicuserid%d:</key> + <value>public%02d</value> + </substitution> + <!-- user guid --> + <substitution> + <key>$publicuserguid%d:</key> + <value>50000000-0000-0000-0000-0000000000%02d</value> + </substitution> + <!-- user name --> + <substitution> + <key>$publicusername%d:</key> + <value>Public %02d</value> + </substitution> + <!-- password --> + <substitution> + <key>$publicpswd%d:</key> + <value>public%02d</value> + </substitution> + <!-- relative path to user principal resource--> + <substitution> + <key>$publicprincipal%d:</key> + <value>$principals_users:$publicuserid%d:/</value> + </substitution> + <substitution> + <key>$publicprincipaluri%d:</key> + <value>$principals_uids:$publicuserguid%d:/</value> + </substitution> + <!-- relative path to user calendar home--> + <substitution> + <key>$publiccalendarhome%d:</key> + <value>$calendars_uids:$publicuserguid%d:</value> + </substitution> + <!-- relative path to user calendar--> + <substitution> + <key>$publiccalendarpath%d:</key> + <value>$calendars_uids:$publicuserguid%d:/$calendar:</value> + </substitution> + <substitution> + <key>$publicemail%d:</key> + <value>$publicuserid%d:@example.com</value> + </substitution> + <!-- calendar user address of user--> + <substitution> + <key>$publiccuaddr%d:</key> + <value>mailto:$publicemail%d:</value> + </substitution> + <substitution> + <key>$publiccuaddralt%d:</key> + <value>$publiccuaddr%d:</value> + </substitution> + <substitution> + <key>$publiccuaddrurn%d:</key> + <value>urn:x-uid:$publicuserguid%d:</value> + </substitution> + </repeat> + + <!-- Twenty resource accounts --> + <repeat count="20"> + <substitution> + <key>$resourceid%d:</key> + <value>resource%02d</value> + </substitution> + <!-- resource guid--> + <substitution> + <key>$resourceguid%d:</key> + <value>40000000-0000-0000-0000-000000000%03d</value> + </substitution> + <!-- resource name--> + <substitution> + <key>$resourcename%d:</key> + <value>Resource %02d</value> + </substitution> + <!-- relative path to first resource calendar home--> + <substitution> + <key>$rcalendarhome%d:</key> + <value>$calendars_uids:$resourceguid%d:</value> + </substitution> + <!-- relative path to first resource calendar home--> + <substitution> + <key>$rcalendarpath%d:</key> + <value>$calendars_uids:$resourceguid%d:/$calendar:</value> + </substitution> + <!-- relative path to first resource inbox--> + <substitution> + <key>$rinboxpath%d:</key> + <value>$calendars_uids:$resourceguid%d:/$inbox:</value> + </substitution> + <!-- relative path to first resource outbox--> + <substitution> + <key>$routboxpath%d:</key> + <value>$calendars_uids:$resourceguid%d:/$outbox:</value> + </substitution> + <!-- relative path to first resource principal resource--> + <substitution> + <key>$rprincipal%d:</key> + <value>$principals_resources:$resourceid%d:/</value> + </substitution> + <substitution> + <key>$rprincipaluri%d:</key> + <value>$principals_uids:$resourceguid%d:/</value> + </substitution> + <substitution> + <key>$rcuaddralt%d:</key> + <value>$rcuaddrurn%d:</value> + </substitution> + <substitution> + <key>$rcuaddrurn%d:</key> + <value>urn:x-uid:$resourceguid%d:</value> + </substitution> + </repeat> + + <!-- Ten Location accounts --> + <repeat count="10"> + <substitution> + <key>$locationid%d:</key> + <value>location%02d</value> + </substitution> + <!-- location guid--> + <substitution> + <key>$locationguid%d:</key> + <value>30000000-0000-0000-0000-000000000%03d</value> + </substitution> + <!-- location name--> + <substitution> + <key>$locationname%d:</key> + <value>Location %02d</value> + </substitution> + <!-- relative path to first location calendar home--> + <substitution> + <key>$lcalendarhome%d:</key> + <value>$calendars_uids:$locationguid%d:</value> + </substitution> + <!-- relative path to first location calendar home--> + <substitution> + <key>$lcalendarpath%d:</key> + <value>$calendars_uids:$locationguid%d:/$calendar:</value> + </substitution> + <!-- relative path to first location inbox--> + <substitution> + <key>$linboxpath%d:</key> + <value>$calendars_uids:$locationguid%d:/$inbox:</value> + </substitution> + <!-- relative path to first location outbox--> + <substitution> + <key>$loutboxpath%d:</key> + <value>$calendars_uids:$locationguid%d:/$outbox:</value> + </substitution> + <!-- relative path to first location principal resource--> + <substitution> + <key>$lprincipal%d:</key> + <value>$principals_resources:$locationid%d:/</value> + </substitution> + <substitution> + <key>$lprincipaluri%d:</key> + <value>$principals_uids:$locationguid%d:/</value> + </substitution> + <substitution> + <key>$lcuaddralt%d:</key> + <value>$lprincipaluri%d:</value> + </substitution> + <substitution> + <key>$lcuaddrurn%d:</key> + <value>urn:x-uid:$locationguid%d:</value> + </substitution> + </repeat> + + + <!-- Ten Group accounts --> + <repeat count="40"> + <substitution> + <key>$groupid%d:</key> + <value>group%02d</value> + </substitution> + <!-- group guid--> + <substitution> + <key>$groupguid%d:</key> + <value>20000000-0000-0000-0000-000000000%03d</value> + </substitution> + <!-- group name--> + <substitution> + <key>$groupname%d:</key> + <value>Group %02d</value> + </substitution> + <!-- relative path to first group principal resource--> + <substitution> + <key>$gprincipal%d:</key> + <value>$principals_resources:$groupid%d:/</value> + </substitution> + <substitution> + <key>$gprincipaluri%d:</key> + <value>$principals_uids:$groupguid%d:/</value> + </substitution> + <substitution> + <key>$gemail%d:</key> + <value>$groupid%d:@example.com</value> + </substitution> + <substitution> + <key>$gcuaddralt%d:</key> + <value>$gprincipaluri%d:</value> + </substitution> + <substitution> + <key>$gcuaddrurn%d:</key> + <value>urn:x-uid:$groupguid%d:</value> + </substitution> + </repeat> + + <!-- User with non-ascii name --> + <substitution> + <key>$i18nid:</key> + <value>i18nuser</value> + </substitution> + <!-- group guid--> + <substitution> + <key>$i18nguid:</key> + <value>860B3EE9-6D7C-4296-9639-E6B998074A78</value> + </substitution> + <!-- group name--> + <substitution> + <key>$i18nname:</key> + <value>まだ</value> + </substitution> + <!-- password --> + <substitution> + <key>$i18npswd:</key> + <value>i18nuser</value> + </substitution> + <!-- relative path to user calendar--> + <substitution> + <key>$i18ncalendarpath:</key> + <value>$calendars_uids:$i18nguid:/$calendar:</value> + </substitution> + <substitution> + <key>$i18nemail:</key> + <value>$i18nid:@example.com</value> + </substitution> + <!-- CUAddrs --> + <substitution> + <key>$i18ncuaddr:</key> + <value>mailto:$i18nemail:</value> + </substitution> + <substitution> + <key>$i18ncuaddrurn:</key> + <value>urn:x-uid:$i18nguid:</value> + </substitution> + + <!-- relative path to disabled group principal resource--> + <substitution> + <key>$principaldisabled:</key> + <value>$principals_groups:disabledgroup/</value> + </substitution> + <substitution> + <key>$principaluridisabled:</key> + <value>$principals_uids:disabledgroup/</value> + </substitution> + <!-- calendar user address of disabled group--> + <substitution> + <key>$cuaddrdisabled:</key> + <value>$principals_uids:disabledgroup/</value> + </substitution> + + <!-- Override some of the above definitions for special cases --> + + <!-- calendar user address of second user--> + <substitution> + <key>$cuaddr2:</key> + <value>MAILTO:$email2:</value> + </substitution> + + </substitutions> +</serverinfo> diff --git a/apps/dav/tests/travis/caldavtest/tests/CardDAV/current-user-principal.xml b/apps/dav/tests/travis/caldavtest/tests/CardDAV/current-user-principal.xml new file mode 100644 index 00000000000..dd206bbcfb8 --- /dev/null +++ b/apps/dav/tests/travis/caldavtest/tests/CardDAV/current-user-principal.xml @@ -0,0 +1,150 @@ +<?xml version="1.0" standalone="no"?> + +<!DOCTYPE caldavtest SYSTEM "caldavtest.dtd"> + +<!-- + Copyright (c) 2006-2015 Apple Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<caldavtest> + <description>Test DAV:current-user-principal support</description> + + <require-feature> + <feature>carddav</feature> + </require-feature> + + <start/> + + <test-suite name='Check for the property on /'> + <require-feature> + <feature>own-root</feature> + </require-feature> + <test name='1'> + <description>Check for authenticated property on /</description> + <request> + <method>PROPFIND</method> + <ruri>$root:</ruri> + <header> + <name>Depth</name> + <value>0</value> + </header> + <data> + <content-type>text/xml; charset=utf-8</content-type> + <filepath>Resource/CardDAV/vcurrent-user-principal/1.xml</filepath> + </data> + <verify> + <callback>propfindItems</callback> + <arg> + <name>okprops</name> + <value><![CDATA[{DAV:}current-user-principal$<D:href xmlns:D="DAV:">$principaluri1:</D:href>]]></value> + </arg> + </verify> + </request> + </test> + <test name='3'> + <description>Check for authenticated property on / (user02)</description> + <request user="$userid2:" pswd="$pswd2:"> + <method>PROPFIND</method> + <ruri>$root:</ruri> + <header> + <name>Depth</name> + <value>0</value> + </header> + <data> + <content-type>text/xml; charset=utf-8</content-type> + <filepath>Resource/CardDAV/vcurrent-user-principal/1.xml</filepath> + </data> + <verify> + <callback>propfindItems</callback> + <arg> + <name>okprops</name> + <value><![CDATA[{DAV:}current-user-principal$<D:href xmlns:D="DAV:">$principaluri2:</D:href>]]></value> + </arg> + </verify> + </request> + </test> + </test-suite> + + <test-suite name='Check for the property on /principals/'> + <test name='1'> + <description>Check for authenticated property on /</description> + <request> + <method>PROPFIND</method> + <ruri>$principalcollection:</ruri> + <header> + <name>Depth</name> + <value>0</value> + </header> + <data> + <content-type>text/xml; charset=utf-8</content-type> + <filepath>Resource/CardDAV/vcurrent-user-principal/1.xml</filepath> + </data> + <verify> + <callback>propfindItems</callback> + <arg> + <name>okprops</name> + <value><![CDATA[{DAV:}current-user-principal$<D:href xmlns:D="DAV:">$principaluri1:</D:href>]]></value> + </arg> + </verify> + </request> + </test> + <test name='2'> + <description>Check for unauthenticated property on /</description> + <request auth="no"> + <method>PROPFIND</method> + <ruri>$principalcollection:</ruri> + <header> + <name>Depth</name> + <value>0</value> + </header> + <data> + <content-type>text/xml; charset=utf-8</content-type> + <filepath>Resource/CardDAV/vcurrent-user-principal/1.xml</filepath> + </data> + <verify> + <callback>statusCode</callback> + <arg> + <name>status</name> + <value>401</value> + </arg> + </verify> + </request> + </test> + <test name='3'> + <description>Check for authenticated property on / (user02)</description> + <request user="$userid2:" pswd="$pswd2:"> + <method>PROPFIND</method> + <ruri>$principalcollection:</ruri> + <header> + <name>Depth</name> + <value>0</value> + </header> + <data> + <content-type>text/xml; charset=utf-8</content-type> + <filepath>Resource/CardDAV/vcurrent-user-principal/1.xml</filepath> + </data> + <verify> + <callback>propfindItems</callback> + <arg> + <name>okprops</name> + <value><![CDATA[{DAV:}current-user-principal$<D:href xmlns:D="DAV:">$principaluri2:</D:href>]]></value> + </arg> + </verify> + </request> + </test> + </test-suite> + + <end/> +</caldavtest> diff --git a/apps/dav/tests/travis/carddavtester.sh b/apps/dav/tests/travis/carddavtester.sh new file mode 100644 index 00000000000..a128872f42a --- /dev/null +++ b/apps/dav/tests/travis/carddavtester.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +SCRIPT=`realpath $0` +SCRIPTPATH=`dirname $SCRIPT` + + +# start the server +php -S 127.0.0.1:8888 -t "$SCRIPTPATH/../../../.." & + + +if [ ! -f CalDAVTester/run.py ]; then + cd "$SCRIPTPATH" + git clone https://github.com/DeepDiver1975/CalDAVTester.git + cd "$SCRIPTPATH/CalDAVTester" + python run.py -s + cd "$SCRIPTPATH" +fi + +# create test user +cd "$SCRIPTPATH/../../../../" +OC_PASS=user01 php occ user:add --password-from-env user01 +OC_PASS=user02 php occ user:add --password-from-env user02 +cd "$SCRIPTPATH/../../../../" + +# run the tests +cd "$SCRIPTPATH/CalDAVTester" +PYTHONPATH="$SCRIPTPATH/pycalendar/src" python testcaldav.py --print-details-onfail -s "$SCRIPTPATH/caldavtest/config/serverinfo.xml" -o cdt.txt \ + "$SCRIPTPATH/caldavtest/tests/CardDAV/current-user-principal.xml" + diff --git a/apps/dav/tests/travis/litmus-v1.sh b/apps/dav/tests/travis/litmus-v1.sh new file mode 100644 index 00000000000..ab0690f392e --- /dev/null +++ b/apps/dav/tests/travis/litmus-v1.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +SCRIPT=`realpath $0` +SCRIPTPATH=`dirname $SCRIPT` + + +# start the server +php -S 127.0.0.1:8888 -t "$SCRIPTPATH/../../../.." & + + +# compile litmus +if [ ! -f /tmp/litmus/litmus-0.13.tar.gz ]; then + mkdir -p /tmp/litmus + wget -O /tmp/litmus/litmus-0.13.tar.gz http://www.webdav.org/neon/litmus/litmus-0.13.tar.gz + cd /tmp/litmus + tar -xzf litmus-0.13.tar.gz + cd /tmp/litmus/litmus-0.13 + ./configure + make +fi + +# run the tests +cd /tmp/litmus/litmus-0.13 +make URL=http://127.0.0.1:8888/remote.php/webdav CREDS="admin admin" TESTS="basic copymove props locks" check diff --git a/apps/dav/tests/travis/litmus-v2.sh b/apps/dav/tests/travis/litmus-v2.sh new file mode 100644 index 00000000000..892ad327d3b --- /dev/null +++ b/apps/dav/tests/travis/litmus-v2.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +SCRIPT=`realpath $0` +SCRIPTPATH=`dirname $SCRIPT` + + +# start the server +php -S 127.0.0.1:8888 -t "$SCRIPTPATH/../../../.." & + + +# compile litmus +if [ ! -f /tmp/litmus/litmus-0.13.tar.gz ]; then + mkdir -p /tmp/litmus + wget -O /tmp/litmus/litmus-0.13.tar.gz http://www.webdav.org/neon/litmus/litmus-0.13.tar.gz + cd /tmp/litmus + tar -xzf litmus-0.13.tar.gz + cd /tmp/litmus/litmus-0.13 + ./configure + make +fi + +# run the tests +cd /tmp/litmus/litmus-0.13 +make URL=http://127.0.0.1:8888/remote.php/dav/files/admin CREDS="admin admin" TESTS="basic copymove props locks" check diff --git a/apps/dav/tests/unit/bootstrap.php b/apps/dav/tests/unit/bootstrap.php new file mode 100644 index 00000000000..28f6b971dec --- /dev/null +++ b/apps/dav/tests/unit/bootstrap.php @@ -0,0 +1,13 @@ +<?php + +define('PHPUNIT_RUN', 1); + +require_once __DIR__.'/../../../../lib/base.php'; + +if(!class_exists('PHPUnit_Framework_TestCase')) { + require_once('PHPUnit/Autoload.php'); +} + +\OC_App::loadApp('dav'); + +OC_Hook::clear(); diff --git a/apps/dav/tests/unit/caldav/caldavbackendtest.php b/apps/dav/tests/unit/caldav/caldavbackendtest.php new file mode 100644 index 00000000000..258c5627ad9 --- /dev/null +++ b/apps/dav/tests/unit/caldav/caldavbackendtest.php @@ -0,0 +1,348 @@ +<?php +/** + * @author Lukas Reschke <lukas@owncloud.com> + * + * @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 <http://www.gnu.org/licenses/> + * + */ +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; + +/** + * 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', [ + '{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; + } + + private function createEvent($calendarId, $start = '20130912T130000Z', $end = '20130912T140000Z') { + + $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:$start +DTEND;VALUE=DATE-TIME:$end +CLASS:PUBLIC +END:VEVENT +END:VCALENDAR +EOD; + $uri0 = $this->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)); + } + + 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)); + } +} diff --git a/apps/dav/tests/unit/carddav/carddavbackendtest.php b/apps/dav/tests/unit/carddav/carddavbackendtest.php new file mode 100644 index 00000000000..dd5e205242a --- /dev/null +++ b/apps/dav/tests/unit/carddav/carddavbackendtest.php @@ -0,0 +1,224 @@ +<?php +/** + * @author Lukas Reschke <lukas@owncloud.com> + * + * @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 <http://www.gnu.org/licenses/> + * + */ +namespace OCA\DAV\Tests\Unit\CardDAV; + +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 */ + private $backend; + + 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, $principal); + + $this->tearDown(); + } + + public function tearDown() { + parent::tearDown(); + + if (is_null($this->backend)) { + return; + } + $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER); + foreach ($books as $book) { + $this->backend->deleteAddressBook($book['id']); + } + } + + public function testAddressBookOperations() { + + // create a new address book + $this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []); + + $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER); + $this->assertEquals(1, count($books)); + $this->assertEquals('Example', $books[0]['{DAV:}displayname']); + + // update it's display name + $patch = new PropPatch([ + '{DAV:}displayname' => 'Unit test', + '{urn:ietf:params:xml:ns:carddav}addressbook-description' => 'Addressbook used for unit testing' + ]); + $this->backend->updateAddressBook($books[0]['id'], $patch); + $patch->commit(); + $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER); + $this->assertEquals(1, count($books)); + $this->assertEquals('Unit test', $books[0]['{DAV:}displayname']); + $this->assertEquals('Addressbook used for unit testing', $books[0]['{urn:ietf:params:xml:ns:carddav}addressbook-description']); + + // delete the address book + $this->backend->deleteAddressBook($books[0]['id']); + $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER); + $this->assertEquals(0, count($books)); + } + + public function testCardOperations() { + // create a new address book + $this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []); + $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER); + $this->assertEquals(1, count($books)); + $bookId = $books[0]['id']; + + // create a card + $uri = $this->getUniqueID('card'); + $this->backend->createCard($bookId, $uri, ''); + + // get all the cards + $cards = $this->backend->getCards($bookId); + $this->assertEquals(1, count($cards)); + $this->assertEquals('', $cards[0]['carddata']); + + // get the cards + $card = $this->backend->getCard($bookId, $uri); + $this->assertNotNull($card); + $this->assertArrayHasKey('id', $card); + $this->assertArrayHasKey('uri', $card); + $this->assertArrayHasKey('lastmodified', $card); + $this->assertArrayHasKey('etag', $card); + $this->assertArrayHasKey('size', $card); + $this->assertEquals('', $card['carddata']); + + // update the card + $this->backend->updateCard($bookId, $uri, '***'); + $card = $this->backend->getCard($bookId, $uri); + $this->assertEquals('***', $card['carddata']); + + // delete the card + $this->backend->deleteCard($bookId, $uri); + $cards = $this->backend->getCards($bookId); + $this->assertEquals(0, count($cards)); + } + + public function testMultiCard() { + // create a new address book + $this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []); + $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER); + $this->assertEquals(1, count($books)); + $bookId = $books[0]['id']; + + // create a card + $uri0 = $this->getUniqueID('card'); + $this->backend->createCard($bookId, $uri0, ''); + $uri1 = $this->getUniqueID('card'); + $this->backend->createCard($bookId, $uri1, ''); + $uri2 = $this->getUniqueID('card'); + $this->backend->createCard($bookId, $uri2, ''); + + // get all the cards + $cards = $this->backend->getCards($bookId); + $this->assertEquals(3, count($cards)); + $this->assertEquals('', $cards[0]['carddata']); + $this->assertEquals('', $cards[1]['carddata']); + $this->assertEquals('', $cards[2]['carddata']); + + // get the cards + $cards = $this->backend->getMultipleCards($bookId, [$uri1, $uri2]); + $this->assertEquals(2, count($cards)); + foreach($cards as $card) { + $this->assertArrayHasKey('id', $card); + $this->assertArrayHasKey('uri', $card); + $this->assertArrayHasKey('lastmodified', $card); + $this->assertArrayHasKey('etag', $card); + $this->assertArrayHasKey('size', $card); + $this->assertEquals('', $card['carddata']); + } + + // delete the card + $this->backend->deleteCard($bookId, $uri0); + $this->backend->deleteCard($bookId, $uri1); + $this->backend->deleteCard($bookId, $uri2); + $cards = $this->backend->getCards($bookId); + $this->assertEquals(0, count($cards)); + } + + public function testSyncSupport() { + // create a new address book + $this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []); + $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER); + $this->assertEquals(1, count($books)); + $bookId = $books[0]['id']; + + // fist call without synctoken + $changes = $this->backend->getChangesForAddressBook($bookId, '', 1); + $syncToken = $changes['syncToken']; + + // add a change + $uri0 = $this->getUniqueID('card'); + $this->backend->createCard($bookId, $uri0, ''); + + // look for changes + $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)); + + // 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)); + + $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)); + } +} diff --git a/apps/dav/tests/unit/connector/sabre/BlockLegacyClientPluginTest.php b/apps/dav/tests/unit/connector/sabre/BlockLegacyClientPluginTest.php index 1e390cf15f7..3004c03b266 100644 --- a/apps/dav/tests/unit/connector/sabre/BlockLegacyClientPluginTest.php +++ b/apps/dav/tests/unit/connector/sabre/BlockLegacyClientPluginTest.php @@ -19,7 +19,7 @@ * */ -namespace Test\Connector\Sabre; +namespace OCA\DAV\Tests\Unit\Connector\Sabre; use OCA\DAV\Connector\Sabre\BlockLegacyClientPlugin; use Test\TestCase; diff --git a/apps/dav/tests/unit/connector/sabre/DummyGetResponsePluginTest.php b/apps/dav/tests/unit/connector/sabre/DummyGetResponsePluginTest.php index 1fd89c84ff6..d2d4a849a51 100644 --- a/apps/dav/tests/unit/connector/sabre/DummyGetResponsePluginTest.php +++ b/apps/dav/tests/unit/connector/sabre/DummyGetResponsePluginTest.php @@ -19,7 +19,7 @@ * */ -namespace Test\Connector\Sabre; +namespace OCA\DAV\Tests\Unit\Connector\Sabre; use OCA\DAV\Connector\Sabre\DummyGetResponsePlugin; use Test\TestCase; 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 @@ +<?php +/** + * @author Lukas Reschke <lukas@owncloud.com> + * + * @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 <http://www.gnu.org/licenses/> + * + */ +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('<?xml version="1.0" encoding="utf-8"?> +<d:prop xmlns:d="DAV:"><d:lockdiscovery><d:activelock><d:lockscope><d:exclusive/></d:lockscope><d:locktype><d:write/></d:locktype><d:lockroot><d:href>MyPath</d:href></d:lockroot><d:depth>infinity</d:depth><d:timeout>Second-1800</d:timeout><d:locktoken><d:href>opaquelocktoken:fe4f7f2437b151fbcb4e9f5c8118c6b1</d:href></d:locktoken><d:owner/></d:activelock></d:lockdiscovery></d:prop> +'); + + $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/MaintenancePluginTest.php b/apps/dav/tests/unit/connector/sabre/MaintenancePluginTest.php index c0acd4fc3de..34fa7f7eef9 100644 --- a/apps/dav/tests/unit/connector/sabre/MaintenancePluginTest.php +++ b/apps/dav/tests/unit/connector/sabre/MaintenancePluginTest.php @@ -19,7 +19,7 @@ * */ -namespace Test\Connector\Sabre; +namespace OCA\DAV\Tests\Unit\Connector\Sabre; use OCA\DAV\Connector\Sabre\MaintenancePlugin; use Test\TestCase; diff --git a/apps/dav/tests/unit/connector/sabre/auth.php b/apps/dav/tests/unit/connector/sabre/auth.php new file mode 100644 index 00000000000..d18747d732a --- /dev/null +++ b/apps/dav/tests/unit/connector/sabre/auth.php @@ -0,0 +1,357 @@ +<?php +/** + * @author Lukas Reschke <lukas@owncloud.com> + * + * @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 <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\DAV\Tests\Unit\Connector\Sabre; + +use Test\TestCase; +use OCP\ISession; +use OCP\IUserSession; + +/** + * Class Auth + * + * @package OCA\DAV\Connector\Sabre + */ +class Auth extends TestCase { + /** @var ISession */ + private $session; + /** @var \OCA\DAV\Connector\Sabre\Auth */ + private $auth; + /** @var IUserSession */ + private $userSession; + + public function setUp() { + parent::setUp(); + $this->session = $this->getMockBuilder('\OCP\ISession') + ->disableOriginalConstructor()->getMock(); + $this->userSession = $this->getMockBuilder('\OCP\IUserSession') + ->disableOriginalConstructor()->getMock(); + $this->auth = new \OCA\DAV\Connector\Sabre\Auth($this->session, $this->userSession); + } + + public function testIsDavAuthenticatedWithoutDavSession() { + $this->session + ->expects($this->once()) + ->method('get') + ->with('AUTHENTICATED_TO_DAV_BACKEND') + ->will($this->returnValue(null)); + + $this->assertFalse($this->invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser'])); + } + + public function testIsDavAuthenticatedWithWrongDavSession() { + $this->session + ->expects($this->exactly(2)) + ->method('get') + ->with('AUTHENTICATED_TO_DAV_BACKEND') + ->will($this->returnValue('AnotherUser')); + + $this->assertFalse($this->invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser'])); + } + + public function testIsDavAuthenticatedWithCorrectDavSession() { + $this->session + ->expects($this->exactly(2)) + ->method('get') + ->with('AUTHENTICATED_TO_DAV_BACKEND') + ->will($this->returnValue('MyTestUser')); + + $this->assertTrue($this->invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser'])); + } + + public function testValidateUserPassOfAlreadyDAVAuthenticatedUser() { + $user = $this->getMockBuilder('\OCP\IUser') + ->disableOriginalConstructor() + ->getMock(); + $user->expects($this->exactly(2)) + ->method('getUID') + ->will($this->returnValue('MyTestUser')); + $this->userSession + ->expects($this->once()) + ->method('isLoggedIn') + ->will($this->returnValue(true)); + $this->userSession + ->expects($this->exactly(2)) + ->method('getUser') + ->will($this->returnValue($user)); + $this->session + ->expects($this->exactly(2)) + ->method('get') + ->with('AUTHENTICATED_TO_DAV_BACKEND') + ->will($this->returnValue('MyTestUser')); + $this->session + ->expects($this->once()) + ->method('close'); + + $this->assertTrue($this->invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword'])); + } + + public function testValidateUserPassOfInvalidDAVAuthenticatedUser() { + $user = $this->getMockBuilder('\OCP\IUser') + ->disableOriginalConstructor() + ->getMock(); + $user->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('MyTestUser')); + $this->userSession + ->expects($this->once()) + ->method('isLoggedIn') + ->will($this->returnValue(true)); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($user)); + $this->session + ->expects($this->exactly(2)) + ->method('get') + ->with('AUTHENTICATED_TO_DAV_BACKEND') + ->will($this->returnValue('AnotherUser')); + $this->session + ->expects($this->once()) + ->method('close'); + + $this->assertFalse($this->invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword'])); + } + + public function testValidateUserPassOfInvalidDAVAuthenticatedUserWithValidPassword() { + $user = $this->getMockBuilder('\OCP\IUser') + ->disableOriginalConstructor() + ->getMock(); + $user->expects($this->exactly(3)) + ->method('getUID') + ->will($this->returnValue('MyTestUser')); + $this->userSession + ->expects($this->once()) + ->method('isLoggedIn') + ->will($this->returnValue(true)); + $this->userSession + ->expects($this->exactly(3)) + ->method('getUser') + ->will($this->returnValue($user)); + $this->session + ->expects($this->exactly(2)) + ->method('get') + ->with('AUTHENTICATED_TO_DAV_BACKEND') + ->will($this->returnValue('AnotherUser')); + $this->userSession + ->expects($this->once()) + ->method('login') + ->with('MyTestUser', 'MyTestPassword') + ->will($this->returnValue(true)); + $this->session + ->expects($this->once()) + ->method('set') + ->with('AUTHENTICATED_TO_DAV_BACKEND', 'MyTestUser'); + $this->session + ->expects($this->once()) + ->method('close'); + + $this->assertTrue($this->invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword'])); + } + + public function testValidateUserPassWithInvalidPassword() { + $this->userSession + ->expects($this->once()) + ->method('isLoggedIn') + ->will($this->returnValue(false)); + $this->userSession + ->expects($this->once()) + ->method('login') + ->with('MyTestUser', 'MyTestPassword') + ->will($this->returnValue(false)); + $this->session + ->expects($this->once()) + ->method('close'); + + $this->assertFalse($this->invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword'])); + } + + public function testGetCurrentUserWithoutBeingLoggedIn() { + $this->assertSame(null, $this->auth->getCurrentUser()); + } + + public function testGetCurrentUserWithValidDAVLogin() { + $user = $this->getMockBuilder('\OCP\IUser') + ->disableOriginalConstructor() + ->getMock(); + $user->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('MyTestUser')); + $this->userSession + ->expects($this->exactly(2)) + ->method('getUser') + ->will($this->returnValue($user)); + $this->session + ->expects($this->exactly(2)) + ->method('get') + ->with('AUTHENTICATED_TO_DAV_BACKEND') + ->will($this->returnValue('MyTestUser')); + + $this->assertSame('MyTestUser', $this->auth->getCurrentUser()); + } + + public function testGetCurrentUserWithoutAnyDAVLogin() { + $user = $this->getMockBuilder('\OCP\IUser') + ->disableOriginalConstructor() + ->getMock(); + $user->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('MyTestUser')); + $this->userSession + ->expects($this->exactly(2)) + ->method('getUser') + ->will($this->returnValue($user)); + $this->session + ->expects($this->exactly(2)) + ->method('get') + ->with('AUTHENTICATED_TO_DAV_BACKEND') + ->will($this->returnValue(null)); + + $this->assertSame('MyTestUser', $this->auth->getCurrentUser()); + } + + public function testGetCurrentUserWithWrongDAVUser() { + $user = $this->getMockBuilder('\OCP\IUser') + ->disableOriginalConstructor() + ->getMock(); + $user->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('MyWrongDavUser')); + $this->userSession + ->expects($this->exactly(2)) + ->method('getUser') + ->will($this->returnValue($user)); + $this->session + ->expects($this->exactly(3)) + ->method('get') + ->with('AUTHENTICATED_TO_DAV_BACKEND') + ->will($this->returnValue('AnotherUser')); + + $this->assertSame(null, $this->auth->getCurrentUser()); + } + + public function testAuthenticateAlreadyLoggedIn() { + $server = $this->getMockBuilder('\Sabre\DAV\Server') + ->disableOriginalConstructor() + ->getMock(); + $this->userSession + ->expects($this->once()) + ->method('isLoggedIn') + ->will($this->returnValue(true)); + $this->session + ->expects($this->once()) + ->method('get') + ->with('AUTHENTICATED_TO_DAV_BACKEND') + ->will($this->returnValue(null)); + $user = $this->getMockBuilder('\OCP\IUser') + ->disableOriginalConstructor() + ->getMock(); + $user->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('MyWrongDavUser')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($user)); + $this->session + ->expects($this->once()) + ->method('close'); + + $this->assertTrue($this->auth->authenticate($server, 'TestRealm')); + } + + /** + * @expectedException \Sabre\DAV\Exception\NotAuthenticated + * @expectedExceptionMessage No basic authentication headers were found + */ + public function testAuthenticateNoBasicAuthenticateHeadersProvided() { + $server = $this->getMockBuilder('\Sabre\DAV\Server') + ->disableOriginalConstructor() + ->getMock(); + $server->httpRequest = $this->getMockBuilder('\Sabre\HTTP\RequestInterface') + ->disableOriginalConstructor() + ->getMock(); + $server->httpResponse = $this->getMockBuilder('\Sabre\HTTP\ResponseInterface') + ->disableOriginalConstructor() + ->getMock(); + $this->auth->authenticate($server, 'TestRealm'); + } + + public function testAuthenticateValidCredentials() { + $server = $this->getMockBuilder('\Sabre\DAV\Server') + ->disableOriginalConstructor() + ->getMock(); + $server->httpRequest = $this->getMockBuilder('\Sabre\HTTP\RequestInterface') + ->disableOriginalConstructor() + ->getMock(); + $server->httpRequest + ->expects($this->once()) + ->method('getHeader') + ->with('Authorization') + ->will($this->returnValue('basic dXNlcm5hbWU6cGFzc3dvcmQ=')); + $server->httpResponse = $this->getMockBuilder('\Sabre\HTTP\ResponseInterface') + ->disableOriginalConstructor() + ->getMock(); + $this->userSession + ->expects($this->once()) + ->method('login') + ->with('username', 'password') + ->will($this->returnValue(true)); + $user = $this->getMockBuilder('\OCP\IUser') + ->disableOriginalConstructor() + ->getMock(); + $user->expects($this->exactly(2)) + ->method('getUID') + ->will($this->returnValue('MyTestUser')); + $this->userSession + ->expects($this->exactly(2)) + ->method('getUser') + ->will($this->returnValue($user)); + $this->assertTrue($this->auth->authenticate($server, 'TestRealm')); + } + + /** + * @expectedException \Sabre\DAV\Exception\NotAuthenticated + * @expectedExceptionMessage Username or password does not match + */ + public function testAuthenticateInvalidCredentials() { + $server = $this->getMockBuilder('\Sabre\DAV\Server') + ->disableOriginalConstructor() + ->getMock(); + $server->httpRequest = $this->getMockBuilder('\Sabre\HTTP\RequestInterface') + ->disableOriginalConstructor() + ->getMock(); + $server->httpRequest + ->expects($this->once()) + ->method('getHeader') + ->with('Authorization') + ->will($this->returnValue('basic dXNlcm5hbWU6cGFzc3dvcmQ=')); + $server->httpResponse = $this->getMockBuilder('\Sabre\HTTP\ResponseInterface') + ->disableOriginalConstructor() + ->getMock(); + $this->userSession + ->expects($this->once()) + ->method('login') + ->with('username', 'password') + ->will($this->returnValue(false)); + $this->auth->authenticate($server, 'TestRealm'); + } +} diff --git a/apps/dav/tests/unit/connector/sabre/copyetagheaderplugintest.php b/apps/dav/tests/unit/connector/sabre/copyetagheaderplugintest.php index 2080755cd51..74dd4edd8cf 100644 --- a/apps/dav/tests/unit/connector/sabre/copyetagheaderplugintest.php +++ b/apps/dav/tests/unit/connector/sabre/copyetagheaderplugintest.php @@ -1,6 +1,6 @@ <?php -namespace Tests\Connector\Sabre; +namespace OCA\DAV\Tests\Unit\Connector\Sabre; /** * Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> diff --git a/apps/dav/tests/unit/connector/sabre/custompropertiesbackend.php b/apps/dav/tests/unit/connector/sabre/custompropertiesbackend.php index 973a5d4c27b..e1bcc996908 100644 --- a/apps/dav/tests/unit/connector/sabre/custompropertiesbackend.php +++ b/apps/dav/tests/unit/connector/sabre/custompropertiesbackend.php @@ -1,6 +1,6 @@ <?php -namespace Tests\Connector\Sabre; +namespace OCA\DAV\Tests\Unit\Connector\Sabre; /** * Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> @@ -16,7 +16,7 @@ class CustomPropertiesBackend extends \Test\TestCase { private $server; /** - * @var \Sabre\DAV\ObjectTree + * @var \Sabre\DAV\Tree */ private $tree; diff --git a/apps/dav/tests/unit/connector/sabre/directory.php b/apps/dav/tests/unit/connector/sabre/directory.php index d85290df80a..75c4828641b 100644 --- a/apps/dav/tests/unit/connector/sabre/directory.php +++ b/apps/dav/tests/unit/connector/sabre/directory.php @@ -6,11 +6,16 @@ * later. * See the COPYING-README file. */ -class Test_OC_Connector_Sabre_Directory extends \Test\TestCase { - /** @var OC\Files\View | PHPUnit_Framework_MockObject_MockObject */ +namespace OCA\DAV\Tests\Unit\Connector\Sabre; + +use OCP\Files\ForbiddenException; + +class Directory extends \Test\TestCase { + + /** @var \OC\Files\View | \PHPUnit_Framework_MockObject_MockObject */ private $view; - /** @var OC\Files\FileInfo | PHPUnit_Framework_MockObject_MockObject */ + /** @var \OC\Files\FileInfo | \PHPUnit_Framework_MockObject_MockObject */ private $info; protected function setUp() { @@ -46,6 +51,25 @@ class Test_OC_Connector_Sabre_Directory extends \Test\TestCase { } /** + * @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(); + } + + /** * */ public function testDeleteFolderWhenAllowed() { 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 @@ +<?php +/** + * Copyright (c) 2015 Thomas Müller <deepdiver@owncloud.com> + * 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 = <<<EOD +<?xml version="1.0" encoding="utf-8"?> +<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:o="http://owncloud.org/ns"> + <o:retry xmlns:o="o:">false</o:retry> + <o:reason xmlns:o="o:">1234567890</o:reason> +</d:error> + +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 4c0af58ffea..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 @@ <?php - -namespace Test\Connector\Sabre\Exception; - -use OCA\DAV\Connector\Sabre\Exception\InvalidPath; - /** * Copyright (c) 2015 Thomas Müller <deepdiver@owncloud.com> * 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/exceptionloggerplugin.php b/apps/dav/tests/unit/connector/sabre/exceptionloggerplugin.php index d85aa5a9cc3..0c364df012b 100644 --- a/apps/dav/tests/unit/connector/sabre/exceptionloggerplugin.php +++ b/apps/dav/tests/unit/connector/sabre/exceptionloggerplugin.php @@ -7,7 +7,7 @@ * See the COPYING-README file. */ -namespace Test\Connector\Sabre; +namespace OCA\DAV\Tests\Unit\Connector\Sabre; use OCA\DAV\Connector\Sabre\Exception\InvalidPath; use OCA\DAV\Connector\Sabre\ExceptionLoggerPlugin as PluginToTest; diff --git a/apps/dav/tests/unit/connector/sabre/file.php b/apps/dav/tests/unit/connector/sabre/file.php index 9171fc3b786..399634f8bee 100644 --- a/apps/dav/tests/unit/connector/sabre/file.php +++ b/apps/dav/tests/unit/connector/sabre/file.php @@ -6,9 +6,10 @@ * See the COPYING-README file. */ -namespace Test\Connector\Sabre; +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; @@ -73,6 +74,10 @@ class File extends \Test\TestCase { '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' ], @@ -200,7 +205,9 @@ class File extends \Test\TestCase { $file = new \OCA\DAV\Connector\Sabre\File($view, $info); // put first chunk + $file->acquireLock(ILockingProvider::LOCK_SHARED); $this->assertNull($file->put('test data one')); + $file->releaseLock(ILockingProvider::LOCK_SHARED); $info = new \OC\Files\FileInfo('/test.txt-chunking-12345-2-1', null, null, [ 'permissions' => \OCP\Constants::PERMISSION_ALL @@ -443,12 +450,12 @@ class File extends \Test\TestCase { $thrown = false; try { // beforeMethod locks - $view->lockFile('/test.txt', ILockingProvider::LOCK_SHARED); + $file->acquireLock(ILockingProvider::LOCK_SHARED); $file->put($this->getStream('test data')); // afterMethod unlocks - $view->unlockFile('/test.txt', ILockingProvider::LOCK_SHARED); + $file->releaseLock(ILockingProvider::LOCK_SHARED); } catch (\Sabre\DAV\Exception\BadRequest $e) { $thrown = true; } @@ -505,7 +512,9 @@ class File extends \Test\TestCase { 'permissions' => \OCP\Constants::PERMISSION_ALL ], null); $file = new \OCA\DAV\Connector\Sabre\File($view, $info); + $file->acquireLock(ILockingProvider::LOCK_SHARED); $this->assertNull($file->put('test data one')); + $file->releaseLock(ILockingProvider::LOCK_SHARED); $info = new \OC\Files\FileInfo('/' . $this->user . '/files/test.txt-chunking-12345-2-1', null, null, [ 'permissions' => \OCP\Constants::PERMISSION_ALL @@ -515,7 +524,9 @@ class File extends \Test\TestCase { // action $thrown = false; try { + $file->acquireLock(ILockingProvider::LOCK_SHARED); $file->put($this->getStream('test data')); + $file->releaseLock(ILockingProvider::LOCK_SHARED); } catch (\OCA\DAV\Connector\Sabre\Exception\FileLocked $e) { $thrown = true; } @@ -685,6 +696,29 @@ class File extends \Test\TestCase { } /** + * @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 * * @param array $callData hook call data to check @@ -829,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/apps/dav/tests/unit/connector/sabre/filesplugin.php b/apps/dav/tests/unit/connector/sabre/filesplugin.php index a91ca7a4ff7..2e3338fefa1 100644 --- a/apps/dav/tests/unit/connector/sabre/filesplugin.php +++ b/apps/dav/tests/unit/connector/sabre/filesplugin.php @@ -1,6 +1,6 @@ <?php -namespace Tests\Connector\Sabre; +namespace OCA\DAV\Tests\Unit\Connector\Sabre; /** * Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> @@ -11,10 +11,13 @@ namespace Tests\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; 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 @@ -67,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"')); @@ -88,16 +94,33 @@ 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, + 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'); @@ -107,10 +130,13 @@ 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)); + $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()); } @@ -166,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)); @@ -207,6 +233,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 * @@ -251,4 +307,17 @@ class FilesPlugin extends \Test\TestCase { $this->plugin->checkMove('FolderA/test.txt', 'test.txt'); } + + /** + * @expectedException \Sabre\DAV\Exception\NotFound + * @expectedExceptionMessage FolderA/test.txt does not exist + */ + public function testMoveSrcNotExist() { + $this->view->expects($this->once()) + ->method('getFileInfo') + ->with('FolderA/test.txt') + ->willReturn(false); + + $this->plugin->checkMove('FolderA/test.txt', 'test.txt'); + } } diff --git a/apps/dav/tests/unit/connector/sabre/node.php b/apps/dav/tests/unit/connector/sabre/node.php index a9610fd84b3..cee64fb7dff 100644 --- a/apps/dav/tests/unit/connector/sabre/node.php +++ b/apps/dav/tests/unit/connector/sabre/node.php @@ -7,7 +7,7 @@ * See the COPYING-README file. */ -namespace Test\Connector\Sabre; +namespace OCA\DAV\Tests\Unit\Connector\Sabre; class Node extends \Test\TestCase { public function davPermissionsProvider() { diff --git a/apps/dav/tests/unit/connector/sabre/objecttree.php b/apps/dav/tests/unit/connector/sabre/objecttree.php index 2691385c1c1..3a56404e552 100644 --- a/apps/dav/tests/unit/connector/sabre/objecttree.php +++ b/apps/dav/tests/unit/connector/sabre/objecttree.php @@ -6,11 +6,10 @@ * See the COPYING-README file. */ -namespace Test\OCA\DAV\Connector\Sabre; +namespace OCA\DAV\Tests\Unit\Connector\Sabre; use OC\Files\FileInfo; -use OCA\DAV\Connector\Sabre\Directory; use OC\Files\Storage\Temporary; class TestDoubleFileView extends \OC\Files\View { @@ -103,7 +102,7 @@ class ObjectTree extends \Test\TestCase { $info = new FileInfo('', null, null, array(), null); - $rootDir = new Directory($view, $info); + $rootDir = new \OCA\DAV\Connector\Sabre\Directory($view, $info); $objectTree = $this->getMock('\OCA\DAV\Connector\Sabre\ObjectTree', array('nodeExists', 'getNodeForPath'), array($rootDir, $view)); diff --git a/apps/dav/tests/unit/connector/sabre/principal.php b/apps/dav/tests/unit/connector/sabre/principal.php index 3c0abeac3f1..2fbab124fb7 100644 --- a/apps/dav/tests/unit/connector/sabre/principal.php +++ b/apps/dav/tests/unit/connector/sabre/principal.php @@ -8,7 +8,7 @@ * See the COPYING-README file. */ -namespace Test\Connector\Sabre; +namespace OCA\DAV\Tests\Unit\Connector\Sabre; use \Sabre\DAV\PropPatch; use OCP\IUserManager; diff --git a/apps/dav/tests/unit/connector/sabre/quotaplugin.php b/apps/dav/tests/unit/connector/sabre/quotaplugin.php index 5d3364e1f8c..470fd9cbf85 100644 --- a/apps/dav/tests/unit/connector/sabre/quotaplugin.php +++ b/apps/dav/tests/unit/connector/sabre/quotaplugin.php @@ -1,12 +1,13 @@ <?php +namespace OCA\DAV\Tests\Unit\Connector\Sabre; /** * Copyright (c) 2013 Thomas Müller <thomas.mueller@tmit.eu> * This file is licensed under the Affero General Public License version 3 or * later. * See the COPYING-README file. */ -class Test_OC_Connector_Sabre_QuotaPlugin extends \Test\TestCase { +class QuotaPlugin extends \Test\TestCase { /** * @var \Sabre\DAV\Server 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)) { diff --git a/apps/dav/tests/unit/connector/sabre/requesttest/uploadtest.php b/apps/dav/tests/unit/connector/sabre/requesttest/uploadtest.php index 9a067f230a3..a2a8326f4ff 100644 --- a/apps/dav/tests/unit/connector/sabre/requesttest/uploadtest.php +++ b/apps/dav/tests/unit/connector/sabre/requesttest/uploadtest.php @@ -8,7 +8,9 @@ namespace OCA\DAV\Tests\Unit\Connector\Sabre\RequestTest; -use OC\AppFramework\Http; +use OC\Connector\Sabre\Exception\FileLocked; +use OCP\AppFramework\Http; +use OCP\Lock\ILockingProvider; class UploadTest extends RequestTest { public function testBasicUpload() { @@ -43,6 +45,34 @@ class UploadTest extends RequestTest { $this->assertEquals(3, $info->getSize()); } + /** + * @expectedException \OCA\DAV\Connector\Sabre\Exception\FileLocked + */ + public function testUploadOverWriteReadLocked() { + $user = $this->getUniqueID(); + $view = $this->setupUser($user, 'pass'); + + $view->file_put_contents('foo.txt', 'bar'); + + $view->lockFile('/foo.txt', ILockingProvider::LOCK_SHARED); + + $this->request($view, $user, 'pass', 'PUT', '/foo.txt', 'asd'); + } + + /** + * @expectedException \OCA\DAV\Connector\Sabre\Exception\FileLocked + */ + public function testUploadOverWriteWriteLocked() { + $user = $this->getUniqueID(); + $view = $this->setupUser($user, 'pass'); + + $view->file_put_contents('foo.txt', 'bar'); + + $view->lockFile('/foo.txt', ILockingProvider::LOCK_EXCLUSIVE); + + $this->request($view, $user, 'pass', 'PUT', '/foo.txt', 'asd'); + } + public function testChunkedUpload() { $user = $this->getUniqueID(); $view = $this->setupUser($user, 'pass'); @@ -107,4 +137,54 @@ class UploadTest extends RequestTest { $this->assertInstanceOf('\OC\Files\FileInfo', $info); $this->assertEquals(6, $info->getSize()); } + + /** + * @expectedException \OCA\DAV\Connector\Sabre\Exception\FileLocked + */ + public function testChunkedUploadOutOfOrderReadLocked() { + $user = $this->getUniqueID(); + $view = $this->setupUser($user, 'pass'); + + $this->assertFalse($view->file_exists('foo.txt')); + + $view->lockFile('/foo.txt', ILockingProvider::LOCK_SHARED); + + try { + $response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-1', 'bar', ['OC-Chunked' => '1']); + } catch (\OCA\DAV\Connector\Sabre\Exception\FileLocked $e) { + $this->fail('Didn\'t expect locked error for the first chunk on read lock'); + return; + } + + $this->assertEquals(Http::STATUS_CREATED, $response->getStatus()); + $this->assertFalse($view->file_exists('foo.txt')); + + // last chunk should trigger the locked error since it tries to assemble + $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-0', 'asd', ['OC-Chunked' => '1']); + } + + /** + * @expectedException \OCA\DAV\Connector\Sabre\Exception\FileLocked + */ + public function testChunkedUploadOutOfOrderWriteLocked() { + $user = $this->getUniqueID(); + $view = $this->setupUser($user, 'pass'); + + $this->assertFalse($view->file_exists('foo.txt')); + + $view->lockFile('/foo.txt', ILockingProvider::LOCK_EXCLUSIVE); + + try { + $response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-1', 'bar', ['OC-Chunked' => '1']); + } catch (\OCA\DAV\Connector\Sabre\Exception\FileLocked $e) { + $this->fail('Didn\'t expect locked error for the first chunk on write lock'); // maybe forbid this in the future for write locks only? + return; + } + + $this->assertEquals(Http::STATUS_CREATED, $response->getStatus()); + $this->assertFalse($view->file_exists('foo.txt')); + + // last chunk should trigger the locked error since it tries to assemble + $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-0', 'asd', ['OC-Chunked' => '1']); + } } diff --git a/apps/dav/tests/unit/connector/sabre/tagsplugin.php b/apps/dav/tests/unit/connector/sabre/tagsplugin.php index 4731e770cfa..f1f6cc40dab 100644 --- a/apps/dav/tests/unit/connector/sabre/tagsplugin.php +++ b/apps/dav/tests/unit/connector/sabre/tagsplugin.php @@ -1,6 +1,6 @@ <?php -namespace Tests\Connector\Sabre; +namespace OCA\DAV\Tests\Unit\Connector\Sabre; /** * Copyright (c) 2014 Vincent Petry <pvince81@owncloud.com> @@ -20,7 +20,7 @@ class TagsPlugin extends \Test\TestCase { private $server; /** - * @var \Sabre\DAV\ObjectTree + * @var \Sabre\DAV\Tree */ private $tree; diff --git a/apps/dav/tests/unit/phpunit.xml b/apps/dav/tests/unit/phpunit.xml new file mode 100644 index 00000000000..46c3cdfb345 --- /dev/null +++ b/apps/dav/tests/unit/phpunit.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8" ?> +<phpunit bootstrap="bootstrap.php" + verbose="true" + timeoutForSmallTests="900" + timeoutForMediumTests="900" + timeoutForLargeTests="900" + > + <testsuite name='unit'> + <directory suffix='test.php'>.</directory> + </testsuite> + <!-- filters for code coverage --> + <filter> + <whitelist> + <directory suffix=".php">../../dav</directory> + <exclude> + <directory suffix=".php">../../dav/tests</directory> + </exclude> + </whitelist> + </filter> + <logging> + <!-- and this is where your report will be written --> + <log type="coverage-clover" target="./clover.xml"/> + </logging> +</phpunit> + diff --git a/apps/encryption/appinfo/application.php b/apps/encryption/appinfo/application.php index 812f1042a8f..6275047252e 100644 --- a/apps/encryption/appinfo/application.php +++ b/apps/encryption/appinfo/application.php @@ -201,7 +201,8 @@ class Application extends \OCP\AppFramework\App { $c->query('KeyManager'), $c->query('Crypt'), $c->query('Session'), - $server->getSession() + $server->getSession(), + $c->query('Util') ); }); diff --git a/apps/encryption/appinfo/routes.php b/apps/encryption/appinfo/routes.php index 8fa163d0751..260337361e8 100644 --- a/apps/encryption/appinfo/routes.php +++ b/apps/encryption/appinfo/routes.php @@ -36,6 +36,11 @@ namespace OCA\Encryption\AppInfo; 'verb' => 'POST' ], [ + 'name' => 'Settings#setEncryptHomeStorage', + 'url' => '/ajax/setEncryptHomeStorage', + 'verb' => 'POST' + ], + [ 'name' => 'Recovery#changeRecoveryPassword', 'url' => '/ajax/changeRecoveryPassword', 'verb' => 'POST' diff --git a/apps/encryption/controller/settingscontroller.php b/apps/encryption/controller/settingscontroller.php index e5bb79a1d40..59e23087b3a 100644 --- a/apps/encryption/controller/settingscontroller.php +++ b/apps/encryption/controller/settingscontroller.php @@ -25,6 +25,7 @@ namespace OCA\Encryption\Controller; use OCA\Encryption\Crypto\Crypt; use OCA\Encryption\KeyManager; use OCA\Encryption\Session; +use OCA\Encryption\Util; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; @@ -57,6 +58,9 @@ class SettingsController extends Controller { /** @var ISession */ private $ocSession; + /** @var Util */ + private $util; + /** * @param string $AppName * @param IRequest $request @@ -67,6 +71,7 @@ class SettingsController extends Controller { * @param Crypt $crypt * @param Session $session * @param ISession $ocSession + * @param Util $util */ public function __construct($AppName, IRequest $request, @@ -76,7 +81,9 @@ class SettingsController extends Controller { KeyManager $keyManager, Crypt $crypt, Session $session, - ISession $ocSession) { + ISession $ocSession, + Util $util +) { parent::__construct($AppName, $request); $this->l = $l10n; $this->userSession = $userSession; @@ -85,6 +92,7 @@ class SettingsController extends Controller { $this->crypt = $crypt; $this->session = $session; $this->ocSession = $ocSession; + $this->util = $util; } @@ -143,4 +151,15 @@ class SettingsController extends Controller { } } + + /** + * @UseSession + * + * @param bool $encryptHomeStorage + * @return DataResponse + */ + public function setEncryptHomeStorage($encryptHomeStorage) { + $this->util->setEncryptHomeStorage($encryptHomeStorage); + return new DataResponse(); + } } diff --git a/apps/encryption/js/settings-admin.js b/apps/encryption/js/settings-admin.js index 39923718c21..9b00a4ec627 100644 --- a/apps/encryption/js/settings-admin.js +++ b/apps/encryption/js/settings-admin.js @@ -76,4 +76,13 @@ $(document).ready(function () { }); }); + $('#encryptHomeStorage').change(function() { + $.post( + OC.generateUrl('/apps/encryption/ajax/setEncryptHomeStorage'), + { + encryptHomeStorage: this.checked + } + ); + }); + }); diff --git a/apps/encryption/l10n/cs_CZ.js b/apps/encryption/l10n/cs_CZ.js index 661731c31d3..e057af58e94 100644 --- a/apps/encryption/l10n/cs_CZ.js +++ b/apps/encryption/l10n/cs_CZ.js @@ -28,8 +28,12 @@ OC.L10N.register( "one-time password for server-side-encryption" : "jednorázové heslo pro šifrování na straně serveru", "Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Tento soubor se nepodařilo dešifrovat, pravděpodobně je sdílený. Požádejte prosím majitele souboru, aby jej s vámi znovu sdílel.", "Can not read this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Soubor nelze načíst, pravděpodobně se jedná o sdílený soubor. Požádejte prosím vlastníka souboru, aby vám jej znovu sdílel.", + "Hey there,\n\nthe admin enabled server-side-encryption. Your files were encrypted using the password '%s'.\n\nPlease login to the web interface, go to the section 'ownCloud basic encryption module' of your personal settings and update your encryption password by entering this password into the 'old log-in password' field and your current login-password.\n\n" : "Ahoj!\n\nAdministrátor povolil šifrování dat na serveru. Vaše soubory byly zašifrovány za použití hesla '%s'.\n\nPřihlašte se do webového rozhraní, přejděte do nastavení 'základního šifrovacího modulu ownCloud' a aktualizujte šifrovací heslo zadáním hesla výše do pole 'původní přihlašovací heslo' a svého aktuálního přihlašovacího hesla.\n\n", "The share will expire on %s." : "Sdílení vyprší %s.", "Cheers!" : "Ať slouží!", + "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Ahoj!<br><br>Administrátor povolil šifrování dat na serveru. Vaše soubory byly zašifrovány za použití hesla <strong>%s<strong>.<br><br>Přihlašte se do webového rozhraní, přejděte do nastavení \"základního šifrovacího modulu ownCloud\" a aktualizujte šifrovací heslo zadáním hesla výše do pole \"původní přihlašovací heslo\" a svého aktuálního přihlašovacího hesla.<br><br>", + "Encrypt the home storage" : "Zašifrovat domovské úložiště", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "Povolení tohoto nastavení zašifruje všechny soubory uložené v hlavním úložišti, jinak budou šifrovány pouze soubory na externích úložištích.", "Enable recovery key" : "Povolit záchranný klíč", "Disable recovery key" : "Vypnout záchranný klíč", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "Záchranný klíč je dodatečný šifrovací klíč použitý pro\nšifrování souborů. S jeho pomocí lze obnovit soubory uživatele při zapomenutí hesla.", @@ -40,7 +44,7 @@ OC.L10N.register( "New recovery key password" : "Nové heslo záchranného klíče", "Repeat new recovery key password" : "Zopakujte nové heslo záchranného klíče", "Change Password" : "Změnit heslo", - "ownCloud basic encryption module" : "ownCloud základní šifrovací modul", + "ownCloud basic encryption module" : "základní šifrovací modul ownCloud", "Your private key password no longer matches your log-in password." : "Heslo vašeho soukromého klíče se již neshoduje s vaším přihlašovacím heslem.", "Set your old private key password to your current log-in password:" : "Změňte své staré heslo soukromého klíče na stejné, jako je vaše současné přihlašovací heslo:", " If you don't remember your old password you can ask your administrator to recover your files." : "Pokud si nepamatujete své původní heslo, můžete požádat správce o obnovu vašich souborů.", diff --git a/apps/encryption/l10n/cs_CZ.json b/apps/encryption/l10n/cs_CZ.json index 1b530d137ed..74206d2ef13 100644 --- a/apps/encryption/l10n/cs_CZ.json +++ b/apps/encryption/l10n/cs_CZ.json @@ -26,8 +26,12 @@ "one-time password for server-side-encryption" : "jednorázové heslo pro šifrování na straně serveru", "Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Tento soubor se nepodařilo dešifrovat, pravděpodobně je sdílený. Požádejte prosím majitele souboru, aby jej s vámi znovu sdílel.", "Can not read this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Soubor nelze načíst, pravděpodobně se jedná o sdílený soubor. Požádejte prosím vlastníka souboru, aby vám jej znovu sdílel.", + "Hey there,\n\nthe admin enabled server-side-encryption. Your files were encrypted using the password '%s'.\n\nPlease login to the web interface, go to the section 'ownCloud basic encryption module' of your personal settings and update your encryption password by entering this password into the 'old log-in password' field and your current login-password.\n\n" : "Ahoj!\n\nAdministrátor povolil šifrování dat na serveru. Vaše soubory byly zašifrovány za použití hesla '%s'.\n\nPřihlašte se do webového rozhraní, přejděte do nastavení 'základního šifrovacího modulu ownCloud' a aktualizujte šifrovací heslo zadáním hesla výše do pole 'původní přihlašovací heslo' a svého aktuálního přihlašovacího hesla.\n\n", "The share will expire on %s." : "Sdílení vyprší %s.", "Cheers!" : "Ať slouží!", + "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Ahoj!<br><br>Administrátor povolil šifrování dat na serveru. Vaše soubory byly zašifrovány za použití hesla <strong>%s<strong>.<br><br>Přihlašte se do webového rozhraní, přejděte do nastavení \"základního šifrovacího modulu ownCloud\" a aktualizujte šifrovací heslo zadáním hesla výše do pole \"původní přihlašovací heslo\" a svého aktuálního přihlašovacího hesla.<br><br>", + "Encrypt the home storage" : "Zašifrovat domovské úložiště", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "Povolení tohoto nastavení zašifruje všechny soubory uložené v hlavním úložišti, jinak budou šifrovány pouze soubory na externích úložištích.", "Enable recovery key" : "Povolit záchranný klíč", "Disable recovery key" : "Vypnout záchranný klíč", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "Záchranný klíč je dodatečný šifrovací klíč použitý pro\nšifrování souborů. S jeho pomocí lze obnovit soubory uživatele při zapomenutí hesla.", @@ -38,7 +42,7 @@ "New recovery key password" : "Nové heslo záchranného klíče", "Repeat new recovery key password" : "Zopakujte nové heslo záchranného klíče", "Change Password" : "Změnit heslo", - "ownCloud basic encryption module" : "ownCloud základní šifrovací modul", + "ownCloud basic encryption module" : "základní šifrovací modul ownCloud", "Your private key password no longer matches your log-in password." : "Heslo vašeho soukromého klíče se již neshoduje s vaším přihlašovacím heslem.", "Set your old private key password to your current log-in password:" : "Změňte své staré heslo soukromého klíče na stejné, jako je vaše současné přihlašovací heslo:", " If you don't remember your old password you can ask your administrator to recover your files." : "Pokud si nepamatujete své původní heslo, můžete požádat správce o obnovu vašich souborů.", diff --git a/apps/encryption/l10n/el.js b/apps/encryption/l10n/el.js index d27098ddb04..509e217a806 100644 --- a/apps/encryption/l10n/el.js +++ b/apps/encryption/l10n/el.js @@ -32,6 +32,8 @@ OC.L10N.register( "The share will expire on %s." : "Ο διαμοιρασμός θα λήξει σε %s.", "Cheers!" : "Χαιρετισμούς!", "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Χαίρετε,<br><br>ο διαχειριστής ενεργοποίησε την κρυπτογράφηση στο διακομιστή. Τα αρχεία σας κρυπτογραφήθηκαν με τον κωδικό <strong>%s</strong>.<br><br>Παρακαλούμε συνδεθείτε στη διεπαφή ιστού, πηγαίνετε στην ενότητα \"μονάδα βασικής κρυπτογράφησης ownCloud\" τωνπ ροσωπικών σας ρυθμίσεων και ενημερώστε τον κωδικό κρυπτογράφησης εισάγοντας αυτό τον κωδικό στο πεδίο \"παλιός κωδικός σύνδεσης\" και τον τωρινό σας κωδικό σύνδεσης.", + "Encrypt the home storage" : "Κρυπτογράφηση του κεντρικού χώρου αποθήκευσης", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "Η ενεργοποίηση αυτή της επιλογής κρυπτογραφεί όλα τα αρχεία που βρίσκονται στον κύριο αποθηκευτικό χώρο, αλλιώς μόνο τα αρχεία σε εξωτερικούς αποθηκευτικούς χώρους θα κρυπτογραφηθούν.", "Enable recovery key" : "Ενεργοποίηση κλειδιού ανάκτησης", "Disable recovery key" : "Απενεργοποίηση κλειδιού ανάκτησης", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "Το κλειδί ανάκτησης είναι ένα επιπλέον κλειδί κρυπτογράφησης που χρησιμοποιείται για να κρυπτογραφήσει αρχεία. Επιτρέπει την ανάκτηση των αρχείων ενός χρήστη αν αυτός/αυτή ξεχάσει τον κωδικό πρόσβασης.", diff --git a/apps/encryption/l10n/el.json b/apps/encryption/l10n/el.json index 3ed5e39b7c0..954d7490ce0 100644 --- a/apps/encryption/l10n/el.json +++ b/apps/encryption/l10n/el.json @@ -30,6 +30,8 @@ "The share will expire on %s." : "Ο διαμοιρασμός θα λήξει σε %s.", "Cheers!" : "Χαιρετισμούς!", "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Χαίρετε,<br><br>ο διαχειριστής ενεργοποίησε την κρυπτογράφηση στο διακομιστή. Τα αρχεία σας κρυπτογραφήθηκαν με τον κωδικό <strong>%s</strong>.<br><br>Παρακαλούμε συνδεθείτε στη διεπαφή ιστού, πηγαίνετε στην ενότητα \"μονάδα βασικής κρυπτογράφησης ownCloud\" τωνπ ροσωπικών σας ρυθμίσεων και ενημερώστε τον κωδικό κρυπτογράφησης εισάγοντας αυτό τον κωδικό στο πεδίο \"παλιός κωδικός σύνδεσης\" και τον τωρινό σας κωδικό σύνδεσης.", + "Encrypt the home storage" : "Κρυπτογράφηση του κεντρικού χώρου αποθήκευσης", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "Η ενεργοποίηση αυτή της επιλογής κρυπτογραφεί όλα τα αρχεία που βρίσκονται στον κύριο αποθηκευτικό χώρο, αλλιώς μόνο τα αρχεία σε εξωτερικούς αποθηκευτικούς χώρους θα κρυπτογραφηθούν.", "Enable recovery key" : "Ενεργοποίηση κλειδιού ανάκτησης", "Disable recovery key" : "Απενεργοποίηση κλειδιού ανάκτησης", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "Το κλειδί ανάκτησης είναι ένα επιπλέον κλειδί κρυπτογράφησης που χρησιμοποιείται για να κρυπτογραφήσει αρχεία. Επιτρέπει την ανάκτηση των αρχείων ενός χρήστη αν αυτός/αυτή ξεχάσει τον κωδικό πρόσβασης.", diff --git a/apps/encryption/l10n/fr.js b/apps/encryption/l10n/fr.js index f6016cc3ce6..59a36a73d7b 100644 --- a/apps/encryption/l10n/fr.js +++ b/apps/encryption/l10n/fr.js @@ -32,6 +32,8 @@ OC.L10N.register( "The share will expire on %s." : "Le partage expirera le %s.", "Cheers!" : "À bientôt !", "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Bonjour,\n<br><br>\nL'administrateur a activé le chiffrement sur le serveur. Vos fichiers ont été chiffrés avec le mot de passe suivant :\n\n<p style=\"font-family: monospace;\"><b>%s</b></p>\n\n<p>\nVeuillez suivre ces instructions :\n<ol>\n<li>Connectez-vous à l'interface web et trouvez la section <em>\"Module de chiffrement de base d'ownCloud\"</em> dans vos paramètres personnels;</li>\n<li>Entrez le mot de passe fourni ci-dessus dans le champ <em>\"Ancien mot de passe de connexion\"</em>;</li>\n<li>Entrez le mot de passe que vous utilisez actuellement pour vous connecter dans le champ <em>\"Actuel mot de passe de connexion\"</em>;</li>\n<li>Validez en cliquant sur le bouton <em>\"Mettre à jour le mot de passe de votre clef privée\"</em>.</li>\n</ol>\n</p>", + "Encrypt the home storage" : "Chiffrer l'espace de stockage principal", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "L'activation de cette option chiffre tous les fichiers du stockage principal, sinon seuls les espaces de stockage externes seront chiffrés", "Enable recovery key" : "Activer la clé de récupération", "Disable recovery key" : "Désactiver la clé de récupération", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "La clé de récupération est une clé supplémentaire utilisée pour chiffrer les fichiers. Elle permet de récupérer les fichiers des utilisateurs s'ils oublient leur mot de passe.", diff --git a/apps/encryption/l10n/fr.json b/apps/encryption/l10n/fr.json index 54a7431db30..b1fcfb35b27 100644 --- a/apps/encryption/l10n/fr.json +++ b/apps/encryption/l10n/fr.json @@ -30,6 +30,8 @@ "The share will expire on %s." : "Le partage expirera le %s.", "Cheers!" : "À bientôt !", "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Bonjour,\n<br><br>\nL'administrateur a activé le chiffrement sur le serveur. Vos fichiers ont été chiffrés avec le mot de passe suivant :\n\n<p style=\"font-family: monospace;\"><b>%s</b></p>\n\n<p>\nVeuillez suivre ces instructions :\n<ol>\n<li>Connectez-vous à l'interface web et trouvez la section <em>\"Module de chiffrement de base d'ownCloud\"</em> dans vos paramètres personnels;</li>\n<li>Entrez le mot de passe fourni ci-dessus dans le champ <em>\"Ancien mot de passe de connexion\"</em>;</li>\n<li>Entrez le mot de passe que vous utilisez actuellement pour vous connecter dans le champ <em>\"Actuel mot de passe de connexion\"</em>;</li>\n<li>Validez en cliquant sur le bouton <em>\"Mettre à jour le mot de passe de votre clef privée\"</em>.</li>\n</ol>\n</p>", + "Encrypt the home storage" : "Chiffrer l'espace de stockage principal", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "L'activation de cette option chiffre tous les fichiers du stockage principal, sinon seuls les espaces de stockage externes seront chiffrés", "Enable recovery key" : "Activer la clé de récupération", "Disable recovery key" : "Désactiver la clé de récupération", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "La clé de récupération est une clé supplémentaire utilisée pour chiffrer les fichiers. Elle permet de récupérer les fichiers des utilisateurs s'ils oublient leur mot de passe.", diff --git a/apps/encryption/l10n/id.js b/apps/encryption/l10n/id.js index 1247b35bad6..aa80555a274 100644 --- a/apps/encryption/l10n/id.js +++ b/apps/encryption/l10n/id.js @@ -1,7 +1,7 @@ OC.L10N.register( "encryption", { - "Missing recovery key password" : "Sandi kunci pemuliahan hilang", + "Missing recovery key password" : "Sandi kunci pemuliahan tidak ada", "Please repeat the recovery key password" : "Silakan ulangi sandi kunci pemulihan", "Repeated recovery key password does not match the provided recovery key password" : "Sandi kunci pemulihan yang diulangi tidak cocok dengan sandi kunci pemulihan yang diberikan", "Recovery key successfully enabled" : "Kunci pemulihan berhasil diaktifkan", @@ -32,6 +32,8 @@ OC.L10N.register( "The share will expire on %s." : "Pembagian akan berakhir pada %s.", "Cheers!" : "Horee!", "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Hai,<br><br>admin mengaktifkan server-side-encryption. Berkas-berkas Anda dienkripsi menggunakan sandi <strong>%s</strong>.<br><br>Silakan masuk di antarmuka web, pergi ke bagian 'modul enkripsi dasar ownCloud' pada pengaturan pribadi Anda dan perbarui sandi enkripsi Anda dengan memasukkan sandi ini kedalam kolom 'sandi masuk yang lama' dan sandi masuk yang baru.<br><br>", + "Encrypt the home storage" : "Enkripsi penyimpanan rumah", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "Mengaktifkan opsi ini akan mengenkripsi semua berkas yang disimpan pada penyimpanan utama, jika tidak diaktifkan maka hanya berkas pada penyimpanan eksternal saja yang akan dienkripsi.", "Enable recovery key" : "Aktifkan kunci pemulihan", "Disable recovery key" : "Nonaktifkan kunci pemulihan", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "Kunci pemulihan adalah kunci enkripsi tambahan yang digunakan untuk mengenkripsi berkas. Kunci pemulihan memungkinkan untuk memulihkan berkas-berkas pengguna ketika pengguna tersebut melupakan sandi mereka.", diff --git a/apps/encryption/l10n/id.json b/apps/encryption/l10n/id.json index 3771f7e935f..451ad5883a0 100644 --- a/apps/encryption/l10n/id.json +++ b/apps/encryption/l10n/id.json @@ -1,5 +1,5 @@ { "translations": { - "Missing recovery key password" : "Sandi kunci pemuliahan hilang", + "Missing recovery key password" : "Sandi kunci pemuliahan tidak ada", "Please repeat the recovery key password" : "Silakan ulangi sandi kunci pemulihan", "Repeated recovery key password does not match the provided recovery key password" : "Sandi kunci pemulihan yang diulangi tidak cocok dengan sandi kunci pemulihan yang diberikan", "Recovery key successfully enabled" : "Kunci pemulihan berhasil diaktifkan", @@ -30,6 +30,8 @@ "The share will expire on %s." : "Pembagian akan berakhir pada %s.", "Cheers!" : "Horee!", "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Hai,<br><br>admin mengaktifkan server-side-encryption. Berkas-berkas Anda dienkripsi menggunakan sandi <strong>%s</strong>.<br><br>Silakan masuk di antarmuka web, pergi ke bagian 'modul enkripsi dasar ownCloud' pada pengaturan pribadi Anda dan perbarui sandi enkripsi Anda dengan memasukkan sandi ini kedalam kolom 'sandi masuk yang lama' dan sandi masuk yang baru.<br><br>", + "Encrypt the home storage" : "Enkripsi penyimpanan rumah", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "Mengaktifkan opsi ini akan mengenkripsi semua berkas yang disimpan pada penyimpanan utama, jika tidak diaktifkan maka hanya berkas pada penyimpanan eksternal saja yang akan dienkripsi.", "Enable recovery key" : "Aktifkan kunci pemulihan", "Disable recovery key" : "Nonaktifkan kunci pemulihan", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "Kunci pemulihan adalah kunci enkripsi tambahan yang digunakan untuk mengenkripsi berkas. Kunci pemulihan memungkinkan untuk memulihkan berkas-berkas pengguna ketika pengguna tersebut melupakan sandi mereka.", diff --git a/apps/encryption/l10n/it.js b/apps/encryption/l10n/it.js index 9f94b409f57..699e4babd01 100644 --- a/apps/encryption/l10n/it.js +++ b/apps/encryption/l10n/it.js @@ -32,6 +32,8 @@ OC.L10N.register( "The share will expire on %s." : "La condivisione scadrà il %s.", "Cheers!" : "Saluti!", "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Ciao,<br><br>l'amministratore ha abilitato la cifratura lato server. I tuoi file sono stati cifrati utilizzando la password <strong>%s</strong>.<br><br>Accedi all'interfaccia web, vai alla sezione \"modulo di cifratura base di ownCloud\" dalle nelle tue impostazioni personali e aggiorna la tua password di cifratura digitando la password nel campo \"vecchia password di accesso\" e la tua nuova password.", + "Encrypt the home storage" : "Cifra l'archiviazione principale", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "L'abilitazione di questa opzione cifra tutti i file memorizzati sull'archiviazione principale, altrimenti saranno cifrati solo i file sull'archiviazione esterna.", "Enable recovery key" : "Abilita chiave di ripristino", "Disable recovery key" : "Disabilita chiave di ripristino", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "La chiave di ripristino è una chiave di cifratura aggiuntiva utilizzata per cifrare i file. Consente di ripristinare i file di un utente se l'utente dimentica la propria password.", diff --git a/apps/encryption/l10n/it.json b/apps/encryption/l10n/it.json index a117af8a317..b86893303c2 100644 --- a/apps/encryption/l10n/it.json +++ b/apps/encryption/l10n/it.json @@ -30,6 +30,8 @@ "The share will expire on %s." : "La condivisione scadrà il %s.", "Cheers!" : "Saluti!", "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Ciao,<br><br>l'amministratore ha abilitato la cifratura lato server. I tuoi file sono stati cifrati utilizzando la password <strong>%s</strong>.<br><br>Accedi all'interfaccia web, vai alla sezione \"modulo di cifratura base di ownCloud\" dalle nelle tue impostazioni personali e aggiorna la tua password di cifratura digitando la password nel campo \"vecchia password di accesso\" e la tua nuova password.", + "Encrypt the home storage" : "Cifra l'archiviazione principale", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "L'abilitazione di questa opzione cifra tutti i file memorizzati sull'archiviazione principale, altrimenti saranno cifrati solo i file sull'archiviazione esterna.", "Enable recovery key" : "Abilita chiave di ripristino", "Disable recovery key" : "Disabilita chiave di ripristino", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "La chiave di ripristino è una chiave di cifratura aggiuntiva utilizzata per cifrare i file. Consente di ripristinare i file di un utente se l'utente dimentica la propria password.", diff --git a/apps/encryption/l10n/ja.js b/apps/encryption/l10n/ja.js index 5c4f470def8..fdae19d72e5 100644 --- a/apps/encryption/l10n/ja.js +++ b/apps/encryption/l10n/ja.js @@ -25,10 +25,15 @@ OC.L10N.register( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." : "暗号化アプリの無効なプライベートキーです。あなたの暗号化されたファイルへアクセスするために、個人設定からプライベートキーのパスワードを更新してください。", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "暗号化アプリは有効ですが、あなたの暗号化キーは初期化されていません。ログアウトした後に、再度ログインしてください", "Encryption App is enabled and ready" : "暗号化アプリは有効になっており、準備が整いました", + "one-time password for server-side-encryption" : "サーバーサイド暗号化のワンタイムパスワード", "Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "このファイルを復号化できません、共有ファイルの可能性があります。ファイルの所有者にお願いして、ファイルを共有しなおしてもらってください。", "Can not read this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "このファイルを読み取ることができません、共有ファイルの可能性があります。ファイルの所有者にお願いして、ファイルを共有しなおしてもらってください。", + "Hey there,\n\nthe admin enabled server-side-encryption. Your files were encrypted using the password '%s'.\n\nPlease login to the web interface, go to the section 'ownCloud basic encryption module' of your personal settings and update your encryption password by entering this password into the 'old log-in password' field and your current login-password.\n\n" : "こんにちは、\n\n管理者がサーバーサイド暗号化を有効にしました。'%s'というパスワードであなたのファイルが暗号化されました。\n\nWeb画面からログインして、個人設定画面の'ownCloud 基本暗号化モジュール' セクションにいき、暗号化パスワードの更新をお願いします。 '旧ログインパスワード'部分に上記パスワードを入力し、現在のログインパスワードで更新します。\n", "The share will expire on %s." : "共有は %s で有効期限が切れます。", "Cheers!" : "それでは!", + "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "こんにちは、<br><br>管理者がサーバーサイド暗号化を有効にしました。<strong>%s</strong>というパスワードであなたのファイルが暗号化されました。<br><br>Web画面からログインして、個人設定画面の\"ownCloud 基本暗号化モジュール\"のセクションにいき、暗号化パスワードの更新をお願いします。 \"旧ログインパスワード”部分に上記パスワードを入力し、現在のログインパスワードで更新します。<br><br>", + "Encrypt the home storage" : "メインストレージ暗号化", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "このオプションを有効にすると、外部ストレージ接続ストレージだけが暗号化されるのではなく、メインストレージのファイル全てが暗号化されます。", "Enable recovery key" : "復旧キーを有効にする", "Disable recovery key" : "復旧キーを無効にする", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "復旧キーは、ファイルの暗号化に使う特別な暗号化キーです。ユーザがパスワードを忘れてしまった場合には、リカバリキーを使ってユーザのファイルを復元することができます。", diff --git a/apps/encryption/l10n/ja.json b/apps/encryption/l10n/ja.json index 9e04dd87f83..6b5811d5bce 100644 --- a/apps/encryption/l10n/ja.json +++ b/apps/encryption/l10n/ja.json @@ -23,10 +23,15 @@ "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." : "暗号化アプリの無効なプライベートキーです。あなたの暗号化されたファイルへアクセスするために、個人設定からプライベートキーのパスワードを更新してください。", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "暗号化アプリは有効ですが、あなたの暗号化キーは初期化されていません。ログアウトした後に、再度ログインしてください", "Encryption App is enabled and ready" : "暗号化アプリは有効になっており、準備が整いました", + "one-time password for server-side-encryption" : "サーバーサイド暗号化のワンタイムパスワード", "Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "このファイルを復号化できません、共有ファイルの可能性があります。ファイルの所有者にお願いして、ファイルを共有しなおしてもらってください。", "Can not read this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "このファイルを読み取ることができません、共有ファイルの可能性があります。ファイルの所有者にお願いして、ファイルを共有しなおしてもらってください。", + "Hey there,\n\nthe admin enabled server-side-encryption. Your files were encrypted using the password '%s'.\n\nPlease login to the web interface, go to the section 'ownCloud basic encryption module' of your personal settings and update your encryption password by entering this password into the 'old log-in password' field and your current login-password.\n\n" : "こんにちは、\n\n管理者がサーバーサイド暗号化を有効にしました。'%s'というパスワードであなたのファイルが暗号化されました。\n\nWeb画面からログインして、個人設定画面の'ownCloud 基本暗号化モジュール' セクションにいき、暗号化パスワードの更新をお願いします。 '旧ログインパスワード'部分に上記パスワードを入力し、現在のログインパスワードで更新します。\n", "The share will expire on %s." : "共有は %s で有効期限が切れます。", "Cheers!" : "それでは!", + "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "こんにちは、<br><br>管理者がサーバーサイド暗号化を有効にしました。<strong>%s</strong>というパスワードであなたのファイルが暗号化されました。<br><br>Web画面からログインして、個人設定画面の\"ownCloud 基本暗号化モジュール\"のセクションにいき、暗号化パスワードの更新をお願いします。 \"旧ログインパスワード”部分に上記パスワードを入力し、現在のログインパスワードで更新します。<br><br>", + "Encrypt the home storage" : "メインストレージ暗号化", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "このオプションを有効にすると、外部ストレージ接続ストレージだけが暗号化されるのではなく、メインストレージのファイル全てが暗号化されます。", "Enable recovery key" : "復旧キーを有効にする", "Disable recovery key" : "復旧キーを無効にする", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "復旧キーは、ファイルの暗号化に使う特別な暗号化キーです。ユーザがパスワードを忘れてしまった場合には、リカバリキーを使ってユーザのファイルを復元することができます。", diff --git a/apps/encryption/l10n/ko.js b/apps/encryption/l10n/ko.js index 50dd5857692..caaed725440 100644 --- a/apps/encryption/l10n/ko.js +++ b/apps/encryption/l10n/ko.js @@ -32,6 +32,8 @@ OC.L10N.register( "The share will expire on %s." : "이 공유는 %s 까지 유지됩니다.", "Cheers!" : "감사합니다!", "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "안녕하세요,<br><br>시스템 관리자가 서버 측 암호화를 활성화했습니다. 저장된 파일이 암호 <strong>%s</strong>으(로) 암호화되었습니다.<br><br>웹 인터페이스에 로그인하여 개인 설정의 'ownCloud 기본 암호화 모듈'로 이동한 다음, '이전 로그인 암호' 필드에 위 암호를 입력하고 현재 로그인 암호로 변경하여 암호화 암호를 업데이트하십시오.<br><br>", + "Encrypt the home storage" : "홈 저장소 암호화", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "이 옵션을 사용하면 주 저장소에 있는 모드 파일을 암호화하며, 사용하지 않으면 외부 저장소의 파일만 암호화합니다", "Enable recovery key" : "복구 키 활성화", "Disable recovery key" : "복구 키 비활성화", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "복구 키는 파일을 암호화하는 추가 키입니다. 사용자가 암호를 잊었을 때 복구할 수 있도록 해 줍니다.", diff --git a/apps/encryption/l10n/ko.json b/apps/encryption/l10n/ko.json index 88eab7837b8..c8e4779b29c 100644 --- a/apps/encryption/l10n/ko.json +++ b/apps/encryption/l10n/ko.json @@ -30,6 +30,8 @@ "The share will expire on %s." : "이 공유는 %s 까지 유지됩니다.", "Cheers!" : "감사합니다!", "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "안녕하세요,<br><br>시스템 관리자가 서버 측 암호화를 활성화했습니다. 저장된 파일이 암호 <strong>%s</strong>으(로) 암호화되었습니다.<br><br>웹 인터페이스에 로그인하여 개인 설정의 'ownCloud 기본 암호화 모듈'로 이동한 다음, '이전 로그인 암호' 필드에 위 암호를 입력하고 현재 로그인 암호로 변경하여 암호화 암호를 업데이트하십시오.<br><br>", + "Encrypt the home storage" : "홈 저장소 암호화", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "이 옵션을 사용하면 주 저장소에 있는 모드 파일을 암호화하며, 사용하지 않으면 외부 저장소의 파일만 암호화합니다", "Enable recovery key" : "복구 키 활성화", "Disable recovery key" : "복구 키 비활성화", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "복구 키는 파일을 암호화하는 추가 키입니다. 사용자가 암호를 잊었을 때 복구할 수 있도록 해 줍니다.", diff --git a/apps/encryption/l10n/lt_LT.js b/apps/encryption/l10n/lt_LT.js index 627be83860b..a27747055dd 100644 --- a/apps/encryption/l10n/lt_LT.js +++ b/apps/encryption/l10n/lt_LT.js @@ -1,21 +1,46 @@ OC.L10N.register( "encryption", { + "Missing recovery key password" : "Nėra atstatymo rakto slaptažodžio", + "Please repeat the recovery key password" : "Pakartokite atstatymo rakto slaptažodį", + "Repeated recovery key password does not match the provided recovery key password" : "Pakartotas atstatymo rakto slaptažodis nesutampa su atstatymo rakto slaptažodžiu", "Recovery key successfully enabled" : "Atkūrimo raktas sėkmingai įjungtas", "Could not enable recovery key. Please check your recovery key password!" : "Neišėjo įjungti jūsų atkūrimo rakto. Prašome jį patikrinti!", "Recovery key successfully disabled" : "Atkūrimo raktas sėkmingai išjungtas", "Could not disable recovery key. Please check your recovery key password!" : "Neišėjo išjungti jūsų atkūrimo rakto. Prašome jį patikrinti!", + "Missing parameters" : "Trūksta parametrų", + "Please provide the old recovery password" : "Įveskite seną atstatymo slaptažodį", + "Please provide a new recovery password" : "Įveskite naują atstatymo slaptažodį", + "Please repeat the new recovery password" : "Pakartokite naują atstatymo slaptažodį", "Password successfully changed." : "Slaptažodis sėkmingai pakeistas", "Could not change the password. Maybe the old password was not correct." : "Slaptažodis nebuvo pakeistas. Gali būti, kad buvo neteisingai suvestas senasis.", + "Recovery Key disabled" : "Atstatymo raktas išjungtas", + "Recovery Key enabled" : "Atstatymo raktas įjungtas", + "Could not enable the recovery key, please try again or contact your administrator" : "Nepavyko įjungti atstatymo rakto, bandykite dar kartą arba susisiekite su administratoriumi", + "Could not update the private key password." : "Nepavyko atnaujinti privataus rakto slaptažodžio.", + "The old password was not correct, please try again." : "Neteisingas senas slaptažodis, pakartokite.", + "The current log-in password was not correct, please try again." : "Esamas prisijungimo slaptažodis neteisingas, bandykite dar kartą.", "Private key password successfully updated." : "Privataus rakto slaptažodis buvo sėkmingai atnaujintas.", + "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one. Please run 'occ encryption:migrate' or contact your administrator" : "Reikalinga šifravimo raktų migracija iš senos versijos ( ownCloud <= 8.0) į naują. Įvykdykite komanda 'occ encryption:migrate' arba susisiekite su adminstratoriumi", "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." : "Netinkamas privatus raktas Šifravimo programai. Prašome atnaujinti savo privataus rakto slaptažodį asmeniniuose nustatymuose, kad atkurti prieigą prie šifruotų failų.", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "Šifravimo programa įjungta, bet Jūsų raktai nėra pritaikyti. Prašome atsijungti ir vėl prisijungti", + "Encryption App is enabled and ready" : "Šifravimo programėlė įjungta ir veikia", + "one-time password for server-side-encryption" : "Vienkartinis slaptažodis šifravimui serverio pusėje", "Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Failo iššifruoti nepavyko, gali būti jog jis yra pasidalintas su jumis. Paprašykite failo savininko, kad jums iš naujo pateiktų šį failą.", "The share will expire on %s." : "Bendrinimo laikas baigsis %s.", "Cheers!" : "Sveikinimai!", + "Enable recovery key" : "Įjungti atstatymo raktą", + "Disable recovery key" : "Išjungti atstatymo raktą", "Recovery key password" : "Atkūrimo rakto slaptažodis", + "Repeat recovery key password" : "Pakartokite atstatymo rakto slaptažodį", "Change recovery key password:" : "Pakeisti atkūrimo rakto slaptažodį:", + "Old recovery key password" : "Senas atstatymo rakto slaptažodis", + "New recovery key password" : "Naujas atstatymo rakto slaptažodis", + "Repeat new recovery key password" : "Pakartokite naują atstatymo rakto slaptažodį", "Change Password" : "Pakeisti slaptažodį", + "ownCloud basic encryption module" : "ownCloud bazinis šifravimo modulis", + "Your private key password no longer matches your log-in password." : "Privataus rakto slaptažodis nebe sutampa su prisijungimo slaptažodžiu.", + "Set your old private key password to your current log-in password:" : "Nustatyti Jūsų privataus rakto slaptažodį į Jūsų dabartinį slaptažodį.", " If you don't remember your old password you can ask your administrator to recover your files." : "Jei nepamenate savo seno slaptažodžio, galite paprašyti administratoriaus atkurti Jūsų failus.", "Old log-in password" : "Senas prisijungimo slaptažodis", "Current log-in password" : "Dabartinis prisijungimo slaptažodis", diff --git a/apps/encryption/l10n/lt_LT.json b/apps/encryption/l10n/lt_LT.json index 7a38dca5a97..b063eba7539 100644 --- a/apps/encryption/l10n/lt_LT.json +++ b/apps/encryption/l10n/lt_LT.json @@ -1,19 +1,44 @@ { "translations": { + "Missing recovery key password" : "Nėra atstatymo rakto slaptažodžio", + "Please repeat the recovery key password" : "Pakartokite atstatymo rakto slaptažodį", + "Repeated recovery key password does not match the provided recovery key password" : "Pakartotas atstatymo rakto slaptažodis nesutampa su atstatymo rakto slaptažodžiu", "Recovery key successfully enabled" : "Atkūrimo raktas sėkmingai įjungtas", "Could not enable recovery key. Please check your recovery key password!" : "Neišėjo įjungti jūsų atkūrimo rakto. Prašome jį patikrinti!", "Recovery key successfully disabled" : "Atkūrimo raktas sėkmingai išjungtas", "Could not disable recovery key. Please check your recovery key password!" : "Neišėjo išjungti jūsų atkūrimo rakto. Prašome jį patikrinti!", + "Missing parameters" : "Trūksta parametrų", + "Please provide the old recovery password" : "Įveskite seną atstatymo slaptažodį", + "Please provide a new recovery password" : "Įveskite naują atstatymo slaptažodį", + "Please repeat the new recovery password" : "Pakartokite naują atstatymo slaptažodį", "Password successfully changed." : "Slaptažodis sėkmingai pakeistas", "Could not change the password. Maybe the old password was not correct." : "Slaptažodis nebuvo pakeistas. Gali būti, kad buvo neteisingai suvestas senasis.", + "Recovery Key disabled" : "Atstatymo raktas išjungtas", + "Recovery Key enabled" : "Atstatymo raktas įjungtas", + "Could not enable the recovery key, please try again or contact your administrator" : "Nepavyko įjungti atstatymo rakto, bandykite dar kartą arba susisiekite su administratoriumi", + "Could not update the private key password." : "Nepavyko atnaujinti privataus rakto slaptažodžio.", + "The old password was not correct, please try again." : "Neteisingas senas slaptažodis, pakartokite.", + "The current log-in password was not correct, please try again." : "Esamas prisijungimo slaptažodis neteisingas, bandykite dar kartą.", "Private key password successfully updated." : "Privataus rakto slaptažodis buvo sėkmingai atnaujintas.", + "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one. Please run 'occ encryption:migrate' or contact your administrator" : "Reikalinga šifravimo raktų migracija iš senos versijos ( ownCloud <= 8.0) į naują. Įvykdykite komanda 'occ encryption:migrate' arba susisiekite su adminstratoriumi", "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." : "Netinkamas privatus raktas Šifravimo programai. Prašome atnaujinti savo privataus rakto slaptažodį asmeniniuose nustatymuose, kad atkurti prieigą prie šifruotų failų.", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "Šifravimo programa įjungta, bet Jūsų raktai nėra pritaikyti. Prašome atsijungti ir vėl prisijungti", + "Encryption App is enabled and ready" : "Šifravimo programėlė įjungta ir veikia", + "one-time password for server-side-encryption" : "Vienkartinis slaptažodis šifravimui serverio pusėje", "Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Failo iššifruoti nepavyko, gali būti jog jis yra pasidalintas su jumis. Paprašykite failo savininko, kad jums iš naujo pateiktų šį failą.", "The share will expire on %s." : "Bendrinimo laikas baigsis %s.", "Cheers!" : "Sveikinimai!", + "Enable recovery key" : "Įjungti atstatymo raktą", + "Disable recovery key" : "Išjungti atstatymo raktą", "Recovery key password" : "Atkūrimo rakto slaptažodis", + "Repeat recovery key password" : "Pakartokite atstatymo rakto slaptažodį", "Change recovery key password:" : "Pakeisti atkūrimo rakto slaptažodį:", + "Old recovery key password" : "Senas atstatymo rakto slaptažodis", + "New recovery key password" : "Naujas atstatymo rakto slaptažodis", + "Repeat new recovery key password" : "Pakartokite naują atstatymo rakto slaptažodį", "Change Password" : "Pakeisti slaptažodį", + "ownCloud basic encryption module" : "ownCloud bazinis šifravimo modulis", + "Your private key password no longer matches your log-in password." : "Privataus rakto slaptažodis nebe sutampa su prisijungimo slaptažodžiu.", + "Set your old private key password to your current log-in password:" : "Nustatyti Jūsų privataus rakto slaptažodį į Jūsų dabartinį slaptažodį.", " If you don't remember your old password you can ask your administrator to recover your files." : "Jei nepamenate savo seno slaptažodžio, galite paprašyti administratoriaus atkurti Jūsų failus.", "Old log-in password" : "Senas prisijungimo slaptažodis", "Current log-in password" : "Dabartinis prisijungimo slaptažodis", diff --git a/apps/encryption/l10n/nl.js b/apps/encryption/l10n/nl.js index 0655b6d29bd..39b8b52de0f 100644 --- a/apps/encryption/l10n/nl.js +++ b/apps/encryption/l10n/nl.js @@ -32,6 +32,8 @@ OC.L10N.register( "The share will expire on %s." : "De share vervalt op %s.", "Cheers!" : "Proficiat!", "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Hallo daar,<br><br>de beheerder heeft server-side versleuteling ingeschakeld. Uw bestanden werden versleuteld met het wachtwoord <strong>%s</strong>.<br><br>Login op de webinterface, ga naar 'ownCloud basis cryptomodule' in uw persoonlijke instellingen en pas uw cryptowachtwoord aan door dit wachtwoord in het \"oude inlog wachtwoord\" veld in te vullen alsmede in uw huidige inlogwachtwoord.<br><br>", + "Encrypt the home storage" : "Versleutel de eigen serveropslag", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "Het inschakelen van deze optie zorgt voor versleutelen van alle bestanden op do hoofdopslag, anders worden alleen bestanden op externe opslag versleuteld", "Enable recovery key" : "Activeer herstelsleutel", "Disable recovery key" : "Deactiveer herstelsleutel", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "De herstelsleutel is een extra cryptografische sleutel die wordt gebruikt om bestanden te versleutelen. Die maakt het mogelijk bestanden te herstellen als de gebruiker zijn of haar wachtwoord vergeet.", diff --git a/apps/encryption/l10n/nl.json b/apps/encryption/l10n/nl.json index 00f6e67822e..336e9727345 100644 --- a/apps/encryption/l10n/nl.json +++ b/apps/encryption/l10n/nl.json @@ -30,6 +30,8 @@ "The share will expire on %s." : "De share vervalt op %s.", "Cheers!" : "Proficiat!", "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Hallo daar,<br><br>de beheerder heeft server-side versleuteling ingeschakeld. Uw bestanden werden versleuteld met het wachtwoord <strong>%s</strong>.<br><br>Login op de webinterface, ga naar 'ownCloud basis cryptomodule' in uw persoonlijke instellingen en pas uw cryptowachtwoord aan door dit wachtwoord in het \"oude inlog wachtwoord\" veld in te vullen alsmede in uw huidige inlogwachtwoord.<br><br>", + "Encrypt the home storage" : "Versleutel de eigen serveropslag", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "Het inschakelen van deze optie zorgt voor versleutelen van alle bestanden op do hoofdopslag, anders worden alleen bestanden op externe opslag versleuteld", "Enable recovery key" : "Activeer herstelsleutel", "Disable recovery key" : "Deactiveer herstelsleutel", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "De herstelsleutel is een extra cryptografische sleutel die wordt gebruikt om bestanden te versleutelen. Die maakt het mogelijk bestanden te herstellen als de gebruiker zijn of haar wachtwoord vergeet.", diff --git a/apps/encryption/l10n/oc.js b/apps/encryption/l10n/oc.js index 8715fd378b8..db54a83db5e 100644 --- a/apps/encryption/l10n/oc.js +++ b/apps/encryption/l10n/oc.js @@ -2,7 +2,7 @@ OC.L10N.register( "encryption", { "Missing recovery key password" : "Senhal de la clau de recuperacion mancant", - "Please repeat the recovery key password" : "Répétez lo senhal de la clau de recuperacion", + "Please repeat the recovery key password" : "Repetètz lo senhal de la clau de recuperacion", "Repeated recovery key password does not match the provided recovery key password" : "Lo senhal de la clau de recuperacion e sa repeticion son pas identics.", "Recovery key successfully enabled" : "Clau de recuperacion activada amb succès", "Could not enable recovery key. Please check your recovery key password!" : "Impossible d'activar la clau de recuperacion. Verificatz lo senhal de vòstra clau de recuperacion !", @@ -25,10 +25,15 @@ OC.L10N.register( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." : "Vòstra clau privada pel chiframent es pas valida ! Metètz a jorn lo senhal de vòstra clau privada dins vòstres paramètres personals per recuperar l'accès a vòstres fichièrs chifrats.", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "L'aplicacion de chiframent es activada mas vòstras claus son pas inicializadas. Desconnectatz-vos e puèi reconnectatz-vos.", "Encryption App is enabled and ready" : "L'aplicacion de chiframent es activada e prèsta", + "one-time password for server-side-encryption" : "Senhal d'usatge unic pel chiframent costat servidor", "Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Impossible de deschifrar aqueste fichièr : s'agís probablament d'un fichièr partejat. Demandatz al proprietari del fichièr de lo partejar tornamai amb vos.", "Can not read this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Impossible de legir aqueste fichièr, s'agís probablament d'un fichièr partejat. Demandatz al proprietari del fichièr de lo repartejar amb vos. ", + "Hey there,\n\nthe admin enabled server-side-encryption. Your files were encrypted using the password '%s'.\n\nPlease login to the web interface, go to the section 'ownCloud basic encryption module' of your personal settings and update your encryption password by entering this password into the 'old log-in password' field and your current login-password.\n\n" : "Bonjorn,\n\nL'administrator a activat lo chiframent sul servidor. Vòstres fichièrs son estats chifrats amb lo senhal seguent :\n\n%s\n\nSeguissètz aquelas instruccions :\n\n1. Connectatz-vos a l'interfàcia web e trobatz la seccion \"Modul de chiframent de basa d'ownCloud\" dins vòstres paramètres personals ;\n\n2. Entratz lo senhal provesit çaisús dins lo camp \"Ancian senhal de connexion\";\n\n3. Entratz lo senhal qu'utilizatz actualament per vos connectar dins lo camp \"Senhal de connexion actual\" ;\n\n4. Validatz en clicant sul boton \"Metre a jorn lo senhal de vòstra clau privada\".\n", "The share will expire on %s." : "Lo partiment expirarà lo %s.", "Cheers!" : "A lèu !", + "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Bonjorn,\n<br><br>\nL'administrator a activat lo chiframent sul servidor. Vòstres fichièrs son estats chifrats amb lo senhal seguent :\n\n<p style=\"font-family: monospace;\"><b>%s</b></p>\n\n<p>\nSeguissètz aquelas instruccions :\n<ol>\n<li>Connectatz-vos a l'interfàcia web e trobatz la seccion <em>\"Modul de chiframent de basa d'ownCloud\"</em> dins vòstres paramètres personals;</li>\n<li>Entratz lo senhal provesit çaisús dins lo camp <em>\"Ancian senhal de connexion\"</em>;</li>\n<li>Entratz lo senhal qu'utilizatz actualament per vos connectar dins lo camp <em>\"Senhal de connexion actual\"</em>;</li>\n<li>Validatz en clicant sul boton <em>\"Metre a jorn lo senhal de vòstra clau privada\"</em>.</li>\n</ol>\n</p>", + "Encrypt the home storage" : "Chifrar l'espaci d'emmagazinatge principal", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "L'activacion d'aquesta opcion chifra totes los fichièrs de l'emmagazinatge principal, siquenon sols los espacis d'emmagazinatge extèrnes seràn chifrats", "Enable recovery key" : "Activar la clau de recuperacion", "Disable recovery key" : "Desactivar la clau de recuperacion", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "La clau de recuperacion es una clau suplementària utilizada per chifrar los fichièrs. Permet de recuperar los fichièrs dels utilizaires se doblidan lor senhal.", diff --git a/apps/encryption/l10n/oc.json b/apps/encryption/l10n/oc.json index ec4406dd77e..27e9a20f63d 100644 --- a/apps/encryption/l10n/oc.json +++ b/apps/encryption/l10n/oc.json @@ -1,6 +1,6 @@ { "translations": { "Missing recovery key password" : "Senhal de la clau de recuperacion mancant", - "Please repeat the recovery key password" : "Répétez lo senhal de la clau de recuperacion", + "Please repeat the recovery key password" : "Repetètz lo senhal de la clau de recuperacion", "Repeated recovery key password does not match the provided recovery key password" : "Lo senhal de la clau de recuperacion e sa repeticion son pas identics.", "Recovery key successfully enabled" : "Clau de recuperacion activada amb succès", "Could not enable recovery key. Please check your recovery key password!" : "Impossible d'activar la clau de recuperacion. Verificatz lo senhal de vòstra clau de recuperacion !", @@ -23,10 +23,15 @@ "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." : "Vòstra clau privada pel chiframent es pas valida ! Metètz a jorn lo senhal de vòstra clau privada dins vòstres paramètres personals per recuperar l'accès a vòstres fichièrs chifrats.", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "L'aplicacion de chiframent es activada mas vòstras claus son pas inicializadas. Desconnectatz-vos e puèi reconnectatz-vos.", "Encryption App is enabled and ready" : "L'aplicacion de chiframent es activada e prèsta", + "one-time password for server-side-encryption" : "Senhal d'usatge unic pel chiframent costat servidor", "Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Impossible de deschifrar aqueste fichièr : s'agís probablament d'un fichièr partejat. Demandatz al proprietari del fichièr de lo partejar tornamai amb vos.", "Can not read this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Impossible de legir aqueste fichièr, s'agís probablament d'un fichièr partejat. Demandatz al proprietari del fichièr de lo repartejar amb vos. ", + "Hey there,\n\nthe admin enabled server-side-encryption. Your files were encrypted using the password '%s'.\n\nPlease login to the web interface, go to the section 'ownCloud basic encryption module' of your personal settings and update your encryption password by entering this password into the 'old log-in password' field and your current login-password.\n\n" : "Bonjorn,\n\nL'administrator a activat lo chiframent sul servidor. Vòstres fichièrs son estats chifrats amb lo senhal seguent :\n\n%s\n\nSeguissètz aquelas instruccions :\n\n1. Connectatz-vos a l'interfàcia web e trobatz la seccion \"Modul de chiframent de basa d'ownCloud\" dins vòstres paramètres personals ;\n\n2. Entratz lo senhal provesit çaisús dins lo camp \"Ancian senhal de connexion\";\n\n3. Entratz lo senhal qu'utilizatz actualament per vos connectar dins lo camp \"Senhal de connexion actual\" ;\n\n4. Validatz en clicant sul boton \"Metre a jorn lo senhal de vòstra clau privada\".\n", "The share will expire on %s." : "Lo partiment expirarà lo %s.", "Cheers!" : "A lèu !", + "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Bonjorn,\n<br><br>\nL'administrator a activat lo chiframent sul servidor. Vòstres fichièrs son estats chifrats amb lo senhal seguent :\n\n<p style=\"font-family: monospace;\"><b>%s</b></p>\n\n<p>\nSeguissètz aquelas instruccions :\n<ol>\n<li>Connectatz-vos a l'interfàcia web e trobatz la seccion <em>\"Modul de chiframent de basa d'ownCloud\"</em> dins vòstres paramètres personals;</li>\n<li>Entratz lo senhal provesit çaisús dins lo camp <em>\"Ancian senhal de connexion\"</em>;</li>\n<li>Entratz lo senhal qu'utilizatz actualament per vos connectar dins lo camp <em>\"Senhal de connexion actual\"</em>;</li>\n<li>Validatz en clicant sul boton <em>\"Metre a jorn lo senhal de vòstra clau privada\"</em>.</li>\n</ol>\n</p>", + "Encrypt the home storage" : "Chifrar l'espaci d'emmagazinatge principal", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "L'activacion d'aquesta opcion chifra totes los fichièrs de l'emmagazinatge principal, siquenon sols los espacis d'emmagazinatge extèrnes seràn chifrats", "Enable recovery key" : "Activar la clau de recuperacion", "Disable recovery key" : "Desactivar la clau de recuperacion", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "La clau de recuperacion es una clau suplementària utilizada per chifrar los fichièrs. Permet de recuperar los fichièrs dels utilizaires se doblidan lor senhal.", diff --git a/apps/encryption/l10n/pt_BR.js b/apps/encryption/l10n/pt_BR.js index 09ed1910c1a..334bbf05282 100644 --- a/apps/encryption/l10n/pt_BR.js +++ b/apps/encryption/l10n/pt_BR.js @@ -32,6 +32,8 @@ OC.L10N.register( "The share will expire on %s." : "O compartilhamento irá expirar em %s.", "Cheers!" : "Saúde!", "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Olá,<br><br>o administrador habilitou criptografia-lado-servidor. Os seus arquivos foram criptografados usando a senha <strong>%s</strong>.<br><br>Por favor faça o login para a interface da Web, vá para a seção 'ownCloud módulo de criptografia básico' das suas definições pessoais e atualize sua senha de criptografia, inserindo esta senha no campo 'senha antiga de log-in' e sua atual senha-de-login..<br><br>", + "Encrypt the home storage" : "Criptografar a pasta de armazenamento home", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "Ativar essa opção de criptografia para todos os arquivos armazenados no armazenamento principal, caso contrário, apenas arquivos no armazenamento externo serão criptografados", "Enable recovery key" : "Habilitar recuperação de chave", "Disable recovery key" : "Dasabilitar chave de recuperação", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "A chave de recuperação é uma chave de encriptação extra que é utilizada para encriptar arquivos. Ela permite a recuperação de arquivos de um usuário esquecer sua senha.", diff --git a/apps/encryption/l10n/pt_BR.json b/apps/encryption/l10n/pt_BR.json index 1682ec44b28..794eb478c74 100644 --- a/apps/encryption/l10n/pt_BR.json +++ b/apps/encryption/l10n/pt_BR.json @@ -30,6 +30,8 @@ "The share will expire on %s." : "O compartilhamento irá expirar em %s.", "Cheers!" : "Saúde!", "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Olá,<br><br>o administrador habilitou criptografia-lado-servidor. Os seus arquivos foram criptografados usando a senha <strong>%s</strong>.<br><br>Por favor faça o login para a interface da Web, vá para a seção 'ownCloud módulo de criptografia básico' das suas definições pessoais e atualize sua senha de criptografia, inserindo esta senha no campo 'senha antiga de log-in' e sua atual senha-de-login..<br><br>", + "Encrypt the home storage" : "Criptografar a pasta de armazenamento home", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "Ativar essa opção de criptografia para todos os arquivos armazenados no armazenamento principal, caso contrário, apenas arquivos no armazenamento externo serão criptografados", "Enable recovery key" : "Habilitar recuperação de chave", "Disable recovery key" : "Dasabilitar chave de recuperação", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "A chave de recuperação é uma chave de encriptação extra que é utilizada para encriptar arquivos. Ela permite a recuperação de arquivos de um usuário esquecer sua senha.", diff --git a/apps/encryption/l10n/pt_PT.js b/apps/encryption/l10n/pt_PT.js index fc93818e9ec..a9e3c8bbbb4 100644 --- a/apps/encryption/l10n/pt_PT.js +++ b/apps/encryption/l10n/pt_PT.js @@ -29,6 +29,7 @@ OC.L10N.register( "Can not read this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Não é possível ler este ficheiro, provavelmente isto é um ficheiro compartilhado. Por favor, peça ao dono do ficheiro para voltar a partilhar o ficheiro consigo.", "The share will expire on %s." : "Esta partilha irá expirar em %s.", "Cheers!" : "Parabéns!", + "Encrypt the home storage" : "Encriptar o armazenamento do início", "Enable recovery key" : "Ativar a chave de recuperação", "Disable recovery key" : "Desativar a chave de recuperação", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "A chave de recuperação é uma chave de encriptação extra que é utilizada para encriptar os ficheiros. Esta permite a recuperação dos ficheiros do utilizador se este esquecer a sua senha.", diff --git a/apps/encryption/l10n/pt_PT.json b/apps/encryption/l10n/pt_PT.json index de139edfffa..e744a7bac6f 100644 --- a/apps/encryption/l10n/pt_PT.json +++ b/apps/encryption/l10n/pt_PT.json @@ -27,6 +27,7 @@ "Can not read this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Não é possível ler este ficheiro, provavelmente isto é um ficheiro compartilhado. Por favor, peça ao dono do ficheiro para voltar a partilhar o ficheiro consigo.", "The share will expire on %s." : "Esta partilha irá expirar em %s.", "Cheers!" : "Parabéns!", + "Encrypt the home storage" : "Encriptar o armazenamento do início", "Enable recovery key" : "Ativar a chave de recuperação", "Disable recovery key" : "Desativar a chave de recuperação", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "A chave de recuperação é uma chave de encriptação extra que é utilizada para encriptar os ficheiros. Esta permite a recuperação dos ficheiros do utilizador se este esquecer a sua senha.", diff --git a/apps/encryption/l10n/ru.js b/apps/encryption/l10n/ru.js index b326b71456d..ae2c1d1f4e0 100644 --- a/apps/encryption/l10n/ru.js +++ b/apps/encryption/l10n/ru.js @@ -32,6 +32,8 @@ OC.L10N.register( "The share will expire on %s." : "Доступ будет закрыт %s", "Cheers!" : "Всего наилучшего!", "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Привет,<br><br>администратор включил шифрование на стороне сервера. Ваши файлы были зашифрованы с помощью пароля <strong>%s</strong>.<br><br>Пожалуйста войдите в веб-приложение, в разделе \"ownCloud простой модуль шифрования\" в личных настройках вам нужно обновить пароль шифрования.<br><br>", + "Encrypt the home storage" : "Зашифровать домашнюю директорию", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "Данный параметр позволяет зашифровать все файлы, хранящиеся в главном хранилище, иначе только файлы на внешних хранилищах будут зашифрованы", "Enable recovery key" : "Включить ключ восстановления", "Disable recovery key" : "Отключить ключ восстановления", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "Ключ восстановления это дополнительный ключ, который используется для шифрования файлов. Он позволяет восстановить пользовательские файлы в случае утери пароля.", diff --git a/apps/encryption/l10n/ru.json b/apps/encryption/l10n/ru.json index f4a14cb841f..87cb27d1e4a 100644 --- a/apps/encryption/l10n/ru.json +++ b/apps/encryption/l10n/ru.json @@ -30,6 +30,8 @@ "The share will expire on %s." : "Доступ будет закрыт %s", "Cheers!" : "Всего наилучшего!", "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Привет,<br><br>администратор включил шифрование на стороне сервера. Ваши файлы были зашифрованы с помощью пароля <strong>%s</strong>.<br><br>Пожалуйста войдите в веб-приложение, в разделе \"ownCloud простой модуль шифрования\" в личных настройках вам нужно обновить пароль шифрования.<br><br>", + "Encrypt the home storage" : "Зашифровать домашнюю директорию", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "Данный параметр позволяет зашифровать все файлы, хранящиеся в главном хранилище, иначе только файлы на внешних хранилищах будут зашифрованы", "Enable recovery key" : "Включить ключ восстановления", "Disable recovery key" : "Отключить ключ восстановления", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "Ключ восстановления это дополнительный ключ, который используется для шифрования файлов. Он позволяет восстановить пользовательские файлы в случае утери пароля.", diff --git a/apps/encryption/l10n/sk_SK.js b/apps/encryption/l10n/sk_SK.js index 6b97ef32683..8b57e2c394b 100644 --- a/apps/encryption/l10n/sk_SK.js +++ b/apps/encryption/l10n/sk_SK.js @@ -16,22 +16,33 @@ OC.L10N.register( "Could not change the password. Maybe the old password was not correct." : "Nemožno zmeniť heslo. Pravdepodobne nebolo staré heslo zadané správne.", "Recovery Key disabled" : "Obnovovací kľúč je zakázaný", "Recovery Key enabled" : "Obnovovací kľúč je povolený", + "Could not enable the recovery key, please try again or contact your administrator" : "Nepodarilo sa zapnúť záchranný kľúč. Prosím, skúste to znova alebo kontaktujte svojho správcu", "Could not update the private key password." : "Nemožno aktualizovať heslo súkromného kľúča.", "The old password was not correct, please try again." : "Staré heslo nebolo zadané správne, prosím skúste to ešte raz.", "The current log-in password was not correct, please try again." : "Toto heslo nebolo správne, prosím skúste to ešte raz.", "Private key password successfully updated." : "Heslo súkromného kľúča je úspešne aktualizované.", + "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one. Please run 'occ encryption:migrate' or contact your administrator" : "Musíte migrovať vaše šifrovacie kľúče zo starého šifrovania (ownCloud <= 8,0) na nové. Spustite „occ encryption:migrate“ alebo sa obráťte na správcu", "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." : "Chybný súkromný kľúč na šifrovanie aplikácií. Zaktualizujte si heslo súkromného kľúča v svojom osobnom nastavení, aby ste znovu získali prístup k svojim zašifrovaným súborom.", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "Aplikácia na šifrovanie je zapnutá, ale vaše kľúče nie sú inicializované. Odhláste sa a znovu sa prihláste.", + "Encryption App is enabled and ready" : "Aplikácia Šifrovanie je zapnutá a pripravená", + "one-time password for server-side-encryption" : "jednorazové heslo na šifrovanie na strane servera", "Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Tento súbor sa nepodarilo dešifrovať, pravdepodobne je zdieľaný. Požiadajte majiteľa súboru, aby ho s vami znovu vyzdieľal.", + "Can not read this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Tento súbor sa nepodarilo prečítať, pravdepodobne je zdieľaný. Požiadajte majiteľa súboru, aby vám ho znova zdieľal.", "The share will expire on %s." : "Zdieľanie vyprší %s.", "Cheers!" : "Pekný deň!", + "Encrypt the home storage" : "Šifrovať domáce úložisko", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "Zapnutím tejto voľby zašifrujete všetky súbory v hlavnom úložisku, v opačnom prípade zašifrujete iba súbory na externom úložisku.", "Enable recovery key" : "Povoliť obnovovací kľúč", "Disable recovery key" : "Zakázať obnovovací kľúč", + "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "Záchranný kľúč je ďalší šifrovací kľúč, ktorý sa používa na šifrovanie súborov. Umožňuje záchranu súborov používateľa ak zabudne svoje heslo.", "Recovery key password" : "Heslo obnovovacieho kľúča", + "Repeat recovery key password" : "Zopakovať heslo k záchrannému kľúču", "Change recovery key password:" : "Zmeniť heslo obnovovacieho kľúča:", + "Old recovery key password" : "Staré heslo k záchrannému kľúču", "New recovery key password" : "Nové heslo obnovovacieho kľúča", "Repeat new recovery key password" : "Zopakujte nové heslo obnovovacieho kľúča", "Change Password" : "Zmeniť heslo", + "ownCloud basic encryption module" : "základný šifrovací modul ownCloud", "Your private key password no longer matches your log-in password." : "Heslo vášho súkromného kľúča sa nezhoduje v vašim prihlasovacím heslom.", "Set your old private key password to your current log-in password:" : "Zmeňte si vaše staré heslo súkromného kľúča na rovnaké, aké je vaše aktuálne prihlasovacie heslo:", " If you don't remember your old password you can ask your administrator to recover your files." : "Ak si nepamätáte svoje staré heslo, môžete požiadať administrátora o obnovenie svojich súborov.", diff --git a/apps/encryption/l10n/sk_SK.json b/apps/encryption/l10n/sk_SK.json index 92ef811db23..aa1fed9863d 100644 --- a/apps/encryption/l10n/sk_SK.json +++ b/apps/encryption/l10n/sk_SK.json @@ -14,22 +14,33 @@ "Could not change the password. Maybe the old password was not correct." : "Nemožno zmeniť heslo. Pravdepodobne nebolo staré heslo zadané správne.", "Recovery Key disabled" : "Obnovovací kľúč je zakázaný", "Recovery Key enabled" : "Obnovovací kľúč je povolený", + "Could not enable the recovery key, please try again or contact your administrator" : "Nepodarilo sa zapnúť záchranný kľúč. Prosím, skúste to znova alebo kontaktujte svojho správcu", "Could not update the private key password." : "Nemožno aktualizovať heslo súkromného kľúča.", "The old password was not correct, please try again." : "Staré heslo nebolo zadané správne, prosím skúste to ešte raz.", "The current log-in password was not correct, please try again." : "Toto heslo nebolo správne, prosím skúste to ešte raz.", "Private key password successfully updated." : "Heslo súkromného kľúča je úspešne aktualizované.", + "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one. Please run 'occ encryption:migrate' or contact your administrator" : "Musíte migrovať vaše šifrovacie kľúče zo starého šifrovania (ownCloud <= 8,0) na nové. Spustite „occ encryption:migrate“ alebo sa obráťte na správcu", "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." : "Chybný súkromný kľúč na šifrovanie aplikácií. Zaktualizujte si heslo súkromného kľúča v svojom osobnom nastavení, aby ste znovu získali prístup k svojim zašifrovaným súborom.", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "Aplikácia na šifrovanie je zapnutá, ale vaše kľúče nie sú inicializované. Odhláste sa a znovu sa prihláste.", + "Encryption App is enabled and ready" : "Aplikácia Šifrovanie je zapnutá a pripravená", + "one-time password for server-side-encryption" : "jednorazové heslo na šifrovanie na strane servera", "Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Tento súbor sa nepodarilo dešifrovať, pravdepodobne je zdieľaný. Požiadajte majiteľa súboru, aby ho s vami znovu vyzdieľal.", + "Can not read this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Tento súbor sa nepodarilo prečítať, pravdepodobne je zdieľaný. Požiadajte majiteľa súboru, aby vám ho znova zdieľal.", "The share will expire on %s." : "Zdieľanie vyprší %s.", "Cheers!" : "Pekný deň!", + "Encrypt the home storage" : "Šifrovať domáce úložisko", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "Zapnutím tejto voľby zašifrujete všetky súbory v hlavnom úložisku, v opačnom prípade zašifrujete iba súbory na externom úložisku.", "Enable recovery key" : "Povoliť obnovovací kľúč", "Disable recovery key" : "Zakázať obnovovací kľúč", + "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "Záchranný kľúč je ďalší šifrovací kľúč, ktorý sa používa na šifrovanie súborov. Umožňuje záchranu súborov používateľa ak zabudne svoje heslo.", "Recovery key password" : "Heslo obnovovacieho kľúča", + "Repeat recovery key password" : "Zopakovať heslo k záchrannému kľúču", "Change recovery key password:" : "Zmeniť heslo obnovovacieho kľúča:", + "Old recovery key password" : "Staré heslo k záchrannému kľúču", "New recovery key password" : "Nové heslo obnovovacieho kľúča", "Repeat new recovery key password" : "Zopakujte nové heslo obnovovacieho kľúča", "Change Password" : "Zmeniť heslo", + "ownCloud basic encryption module" : "základný šifrovací modul ownCloud", "Your private key password no longer matches your log-in password." : "Heslo vášho súkromného kľúča sa nezhoduje v vašim prihlasovacím heslom.", "Set your old private key password to your current log-in password:" : "Zmeňte si vaše staré heslo súkromného kľúča na rovnaké, aké je vaše aktuálne prihlasovacie heslo:", " If you don't remember your old password you can ask your administrator to recover your files." : "Ak si nepamätáte svoje staré heslo, môžete požiadať administrátora o obnovenie svojich súborov.", diff --git a/apps/encryption/l10n/sq.js b/apps/encryption/l10n/sq.js index d18e8bcbbfd..e608fb368f8 100644 --- a/apps/encryption/l10n/sq.js +++ b/apps/encryption/l10n/sq.js @@ -32,6 +32,8 @@ OC.L10N.register( "The share will expire on %s." : "Ndarja do të skadojë më %s.", "Cheers!" : "Gëzuar!", "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Njatjeta,<br><br>përgjegjësi aktivizoi fshehtëzim më anë shërbyesi. Kartelat tuaja qenë fshehtëzuar duke përdorur fjalëkalimin <strong>%s</strong>.<br><br>Ju lutemi, bëni hyrjen te ndërfaqja web, kaloni te ndarja \"modul i thjeshtë ownCloud për fshehtëzime\" e rregullimeve tuaja personale dhe përditësoni fjalëkalimin tuaj për fshehtëzime duke dhënë këtë fjalëkalim te fusha \"old log-in password\" dhe fjalëkalimin tuaj të tanishëm për hyrjet.<br><br>", + "Encrypt the home storage" : "Fshehtëzo depozitën bazë", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "Aktivizimi i kësaj mundësie fshehtëzon krejt kartelat e depozituara në depon bazë, përndryshe do të fshehtëzohen vetëm kartelat në depozitën e jashtme", "Enable recovery key" : "Aktivizo kyç rimarrjesh", "Disable recovery key" : "Çaktivizo kyç rimarrjesh", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "Kyçi i rimarrjeve është një kyç ekstra fshehtëzimesh që përdoret për të fshehtëzuar kartela. Ai lejon rimarrjen e një kartele të përdoruesit, nëse përdoruesi harron fjalëkalimin e vet.", diff --git a/apps/encryption/l10n/sq.json b/apps/encryption/l10n/sq.json index 7415195f955..2319f03ae4f 100644 --- a/apps/encryption/l10n/sq.json +++ b/apps/encryption/l10n/sq.json @@ -30,6 +30,8 @@ "The share will expire on %s." : "Ndarja do të skadojë më %s.", "Cheers!" : "Gëzuar!", "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Njatjeta,<br><br>përgjegjësi aktivizoi fshehtëzim më anë shërbyesi. Kartelat tuaja qenë fshehtëzuar duke përdorur fjalëkalimin <strong>%s</strong>.<br><br>Ju lutemi, bëni hyrjen te ndërfaqja web, kaloni te ndarja \"modul i thjeshtë ownCloud për fshehtëzime\" e rregullimeve tuaja personale dhe përditësoni fjalëkalimin tuaj për fshehtëzime duke dhënë këtë fjalëkalim te fusha \"old log-in password\" dhe fjalëkalimin tuaj të tanishëm për hyrjet.<br><br>", + "Encrypt the home storage" : "Fshehtëzo depozitën bazë", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "Aktivizimi i kësaj mundësie fshehtëzon krejt kartelat e depozituara në depon bazë, përndryshe do të fshehtëzohen vetëm kartelat në depozitën e jashtme", "Enable recovery key" : "Aktivizo kyç rimarrjesh", "Disable recovery key" : "Çaktivizo kyç rimarrjesh", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "Kyçi i rimarrjeve është një kyç ekstra fshehtëzimesh që përdoret për të fshehtëzuar kartela. Ai lejon rimarrjen e një kartele të përdoruesit, nëse përdoruesi harron fjalëkalimin e vet.", diff --git a/apps/encryption/l10n/th_TH.js b/apps/encryption/l10n/th_TH.js index 3c4a5d696fa..37f505060cc 100644 --- a/apps/encryption/l10n/th_TH.js +++ b/apps/encryption/l10n/th_TH.js @@ -32,6 +32,8 @@ OC.L10N.register( "The share will expire on %s." : "การแชร์จะหมดอายุในวันที่ %s", "Cheers!" : "ไชโย!", "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "นี่คุณ <br><br> ผู้ดูแลระบบเปิดใช้งานการเข้ารหัสฝั่งเซิร์ฟเวอร์ ไฟล์ของคุณจะถูกเข้ารหัสโดยใช้รหัสผ่าน <strong>%s</strong> <br><br>กรุณาเข้าสู่ระบบเว็บอินเตอร์เฟซไปที่ส่วน \"โมดูลการเข้ารหัส ownCloud พื้นฐาน\" ของการตั้งค่าส่วนบุคคลของคุณและอัพเดทการเข้ารหัสรหัสผ่านของคุณโดย ป้อนรหัสผ่านนี้ในช่อง \"รหัสผ่านเก่าที่เข้าสู่ระบบ\" และเข้าสู่ระบบด้วยรหัสผ่านปัจจุบันของคุณ<br><br>", + "Encrypt the home storage" : "การเข้ารหัสพื้นที่จัดเก็บหน้าโฮม", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "การเปิดใช้งานตัวเลือกนี้จะเข้ารหัสไฟล์ทั้งหมดที่เก็บไว้ในพื้นที่จัดเก็บข้อมูลหลัก มิฉะนั้นจะเข้ารหัสเฉพาะไฟล์ที่เป็นพื้นที่จัดเก็บข้อมูลภายนอก", "Enable recovery key" : "เปิดใช้งานการกู้คืนรหัส", "Disable recovery key" : "ปิดใช้งานรหัสการกู้คืนรหัส", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "รหัสการกู้คืนเป็นการเข้ารหัสลับพิเศษจะใช้ในการเข้ารหัสไฟล์ มันจะช่วยเรื่องการกู้คืนไฟล์ของผู้ใช้ที่ลืมรหัสผ่าน", diff --git a/apps/encryption/l10n/th_TH.json b/apps/encryption/l10n/th_TH.json index b69cdb8a871..b87b5a848e8 100644 --- a/apps/encryption/l10n/th_TH.json +++ b/apps/encryption/l10n/th_TH.json @@ -30,6 +30,8 @@ "The share will expire on %s." : "การแชร์จะหมดอายุในวันที่ %s", "Cheers!" : "ไชโย!", "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "นี่คุณ <br><br> ผู้ดูแลระบบเปิดใช้งานการเข้ารหัสฝั่งเซิร์ฟเวอร์ ไฟล์ของคุณจะถูกเข้ารหัสโดยใช้รหัสผ่าน <strong>%s</strong> <br><br>กรุณาเข้าสู่ระบบเว็บอินเตอร์เฟซไปที่ส่วน \"โมดูลการเข้ารหัส ownCloud พื้นฐาน\" ของการตั้งค่าส่วนบุคคลของคุณและอัพเดทการเข้ารหัสรหัสผ่านของคุณโดย ป้อนรหัสผ่านนี้ในช่อง \"รหัสผ่านเก่าที่เข้าสู่ระบบ\" และเข้าสู่ระบบด้วยรหัสผ่านปัจจุบันของคุณ<br><br>", + "Encrypt the home storage" : "การเข้ารหัสพื้นที่จัดเก็บหน้าโฮม", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "การเปิดใช้งานตัวเลือกนี้จะเข้ารหัสไฟล์ทั้งหมดที่เก็บไว้ในพื้นที่จัดเก็บข้อมูลหลัก มิฉะนั้นจะเข้ารหัสเฉพาะไฟล์ที่เป็นพื้นที่จัดเก็บข้อมูลภายนอก", "Enable recovery key" : "เปิดใช้งานการกู้คืนรหัส", "Disable recovery key" : "ปิดใช้งานรหัสการกู้คืนรหัส", "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "รหัสการกู้คืนเป็นการเข้ารหัสลับพิเศษจะใช้ในการเข้ารหัสไฟล์ มันจะช่วยเรื่องการกู้คืนไฟล์ของผู้ใช้ที่ลืมรหัสผ่าน", diff --git a/apps/encryption/l10n/zh_TW.js b/apps/encryption/l10n/zh_TW.js index 17893b44b67..d0c1e3dfee8 100644 --- a/apps/encryption/l10n/zh_TW.js +++ b/apps/encryption/l10n/zh_TW.js @@ -1,21 +1,52 @@ OC.L10N.register( "encryption", { + "Missing recovery key password" : "遺失還原金鑰密碼", + "Please repeat the recovery key password" : "請您再輸入新的還原金鑰密碼一次", + "Repeated recovery key password does not match the provided recovery key password" : "輸入的還原金鑰密碼與設定的並不相符", "Recovery key successfully enabled" : "還原金鑰已成功開啟", "Could not enable recovery key. Please check your recovery key password!" : "無法啟用還原金鑰。請檢查您的還原金鑰密碼!", "Recovery key successfully disabled" : "還原金鑰已成功停用", "Could not disable recovery key. Please check your recovery key password!" : "無法停用還原金鑰。請檢查您的還原金鑰密碼!", + "Missing parameters" : "遺失參數", + "Please provide the old recovery password" : "請提供舊的還原密碼", + "Please provide a new recovery password" : "請提供新的還原密碼", + "Please repeat the new recovery password" : "請您再輸入新的還原密碼", "Password successfully changed." : "成功變更密碼。", "Could not change the password. Maybe the old password was not correct." : "無法變更密碼,或許是輸入的舊密碼不正確。", + "Recovery Key disabled" : "還原金鑰停用", + "Recovery Key enabled" : "還原金鑰啟用", + "Could not enable the recovery key, please try again or contact your administrator" : "無法啟用還原金鑰功能,請重試或聯絡系統管理員", + "Could not update the private key password." : "無法更新私人金鑰密碼", + "The old password was not correct, please try again." : "舊密碼不正確,請再試一次", + "The current log-in password was not correct, please try again." : "目前登入的密碼不正確,請再試一次", "Private key password successfully updated." : "私人金鑰密碼已成功更新。", + "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one. Please run 'occ encryption:migrate' or contact your administrator" : "您需要搬移您的加密鑰匙從舊版的加密 (ownCloud <= 8.0) 到新版,請執行 'occ encryption:migrate' 或是聯絡系統管理員", "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." : "無效的檔案加密私鑰,請在個人設定中更新您的私鑰密語以存取加密的檔案。", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "檔案加密已啓用,但是您的金鑰尚未初始化,請重新登入一次", + "Encryption App is enabled and ready" : "加密應用程式已經被啟用", + "one-time password for server-side-encryption" : "一次性密碼用於伺服器端的加密", "Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "無法解密這個檔案,也許這是分享的檔案。請詢問檔案所有人重新分享檔案給您。", + "Can not read this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "無法檢視這個檔案,或許這是分享的檔案,請詢問這個檔案的擁有者並請他重新分享給您。", + "Hey there,\n\nthe admin enabled server-side-encryption. Your files were encrypted using the password '%s'.\n\nPlease login to the web interface, go to the section 'ownCloud basic encryption module' of your personal settings and update your encryption password by entering this password into the 'old log-in password' field and your current login-password.\n\n" : "嗨,請看這裡,\n\n系管理員啟用了伺服器端的加密功能,您的檔案將會使用密碼 '%s' 加密\n\n請從網頁登入,到 'ownCloud basic encryption module' 設置您的個人設定並透過更新加密密碼,將這個組密碼設定在 'old log-in password' 以及您的目前登入密碼\n", "The share will expire on %s." : "這個分享將會於 %s 過期", "Cheers!" : "太棒了!", + "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "嗨,請看這裡,<br><br>系管理員啟用了伺服器端的加密功能,您的檔案將會使用密碼<strong> '%s' </strong>加密,請從網頁登入,到 'ownCloud basic encryption module' 設置您的個人設定並透過更新加密密碼,將這個組密碼設定在 'old log-in password' 以及您的目前登入密碼<br><br>", + "Encrypt the home storage" : "加密家目錄空間", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "請啟用這個功能以用來加密主要儲存空間的檔案,否則只有再外部儲存的檔案會加密", + "Enable recovery key" : "啟用還原金鑰", + "Disable recovery key" : "關閉還原金鑰", + "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "加密金鑰是另一種加密檔案方式,當使用者忘記密碼時,可以用還原金鑰來還原檔案", "Recovery key password" : "還原金鑰密碼", + "Repeat recovery key password" : "再輸入還原金鑰密碼一次", "Change recovery key password:" : "變更還原金鑰密碼:", + "Old recovery key password" : "舊的還原金鑰密碼", + "New recovery key password" : "新的還原金鑰密碼", + "Repeat new recovery key password" : "再輸入新的還原金鑰密碼一次", "Change Password" : "變更密碼", + "ownCloud basic encryption module" : "ownCloud 基本加密模組", + "Your private key password no longer matches your log-in password." : "您的私人金鑰密碼不符合您的登入密碼", + "Set your old private key password to your current log-in password:" : "設定您的舊私人金鑰密碼到您現在的登入密碼:", " If you don't remember your old password you can ask your administrator to recover your files." : "如果您忘記舊密碼,可以請求管理員協助取回檔案。", "Old log-in password" : "舊登入密碼", "Current log-in password" : "目前的登入密碼", diff --git a/apps/encryption/l10n/zh_TW.json b/apps/encryption/l10n/zh_TW.json index ce2e07228fc..feee736980f 100644 --- a/apps/encryption/l10n/zh_TW.json +++ b/apps/encryption/l10n/zh_TW.json @@ -1,19 +1,50 @@ { "translations": { + "Missing recovery key password" : "遺失還原金鑰密碼", + "Please repeat the recovery key password" : "請您再輸入新的還原金鑰密碼一次", + "Repeated recovery key password does not match the provided recovery key password" : "輸入的還原金鑰密碼與設定的並不相符", "Recovery key successfully enabled" : "還原金鑰已成功開啟", "Could not enable recovery key. Please check your recovery key password!" : "無法啟用還原金鑰。請檢查您的還原金鑰密碼!", "Recovery key successfully disabled" : "還原金鑰已成功停用", "Could not disable recovery key. Please check your recovery key password!" : "無法停用還原金鑰。請檢查您的還原金鑰密碼!", + "Missing parameters" : "遺失參數", + "Please provide the old recovery password" : "請提供舊的還原密碼", + "Please provide a new recovery password" : "請提供新的還原密碼", + "Please repeat the new recovery password" : "請您再輸入新的還原密碼", "Password successfully changed." : "成功變更密碼。", "Could not change the password. Maybe the old password was not correct." : "無法變更密碼,或許是輸入的舊密碼不正確。", + "Recovery Key disabled" : "還原金鑰停用", + "Recovery Key enabled" : "還原金鑰啟用", + "Could not enable the recovery key, please try again or contact your administrator" : "無法啟用還原金鑰功能,請重試或聯絡系統管理員", + "Could not update the private key password." : "無法更新私人金鑰密碼", + "The old password was not correct, please try again." : "舊密碼不正確,請再試一次", + "The current log-in password was not correct, please try again." : "目前登入的密碼不正確,請再試一次", "Private key password successfully updated." : "私人金鑰密碼已成功更新。", + "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one. Please run 'occ encryption:migrate' or contact your administrator" : "您需要搬移您的加密鑰匙從舊版的加密 (ownCloud <= 8.0) 到新版,請執行 'occ encryption:migrate' 或是聯絡系統管理員", "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." : "無效的檔案加密私鑰,請在個人設定中更新您的私鑰密語以存取加密的檔案。", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "檔案加密已啓用,但是您的金鑰尚未初始化,請重新登入一次", + "Encryption App is enabled and ready" : "加密應用程式已經被啟用", + "one-time password for server-side-encryption" : "一次性密碼用於伺服器端的加密", "Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "無法解密這個檔案,也許這是分享的檔案。請詢問檔案所有人重新分享檔案給您。", + "Can not read this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "無法檢視這個檔案,或許這是分享的檔案,請詢問這個檔案的擁有者並請他重新分享給您。", + "Hey there,\n\nthe admin enabled server-side-encryption. Your files were encrypted using the password '%s'.\n\nPlease login to the web interface, go to the section 'ownCloud basic encryption module' of your personal settings and update your encryption password by entering this password into the 'old log-in password' field and your current login-password.\n\n" : "嗨,請看這裡,\n\n系管理員啟用了伺服器端的加密功能,您的檔案將會使用密碼 '%s' 加密\n\n請從網頁登入,到 'ownCloud basic encryption module' 設置您的個人設定並透過更新加密密碼,將這個組密碼設定在 'old log-in password' 以及您的目前登入密碼\n", "The share will expire on %s." : "這個分享將會於 %s 過期", "Cheers!" : "太棒了!", + "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "嗨,請看這裡,<br><br>系管理員啟用了伺服器端的加密功能,您的檔案將會使用密碼<strong> '%s' </strong>加密,請從網頁登入,到 'ownCloud basic encryption module' 設置您的個人設定並透過更新加密密碼,將這個組密碼設定在 'old log-in password' 以及您的目前登入密碼<br><br>", + "Encrypt the home storage" : "加密家目錄空間", + "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "請啟用這個功能以用來加密主要儲存空間的檔案,否則只有再外部儲存的檔案會加密", + "Enable recovery key" : "啟用還原金鑰", + "Disable recovery key" : "關閉還原金鑰", + "The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "加密金鑰是另一種加密檔案方式,當使用者忘記密碼時,可以用還原金鑰來還原檔案", "Recovery key password" : "還原金鑰密碼", + "Repeat recovery key password" : "再輸入還原金鑰密碼一次", "Change recovery key password:" : "變更還原金鑰密碼:", + "Old recovery key password" : "舊的還原金鑰密碼", + "New recovery key password" : "新的還原金鑰密碼", + "Repeat new recovery key password" : "再輸入新的還原金鑰密碼一次", "Change Password" : "變更密碼", + "ownCloud basic encryption module" : "ownCloud 基本加密模組", + "Your private key password no longer matches your log-in password." : "您的私人金鑰密碼不符合您的登入密碼", + "Set your old private key password to your current log-in password:" : "設定您的舊私人金鑰密碼到您現在的登入密碼:", " If you don't remember your old password you can ask your administrator to recover your files." : "如果您忘記舊密碼,可以請求管理員協助取回檔案。", "Old log-in password" : "舊登入密碼", "Current log-in password" : "目前的登入密碼", diff --git a/apps/encryption/lib/crypto/crypt.php b/apps/encryption/lib/crypto/crypt.php index c55fb00f838..c0dcc936bdf 100644 --- a/apps/encryption/lib/crypto/crypt.php +++ b/apps/encryption/lib/crypto/crypt.php @@ -2,6 +2,7 @@ /** * @author Björn Schießle <schiessle@owncloud.com> * @author Clark Tomlinson <fallen013@gmail.com> + * @author Joas Schilling <nickvergessen@owncloud.com> * @author Lukas Reschke <lukas@owncloud.com> * @author Thomas Müller <thomas.mueller@tmit.eu> * @@ -53,7 +54,7 @@ class Crypt { */ private $logger; /** - * @var IUser + * @var string */ private $user; /** @@ -73,7 +74,7 @@ class Crypt { */ public function __construct(ILogger $logger, IUserSession $userSession, IConfig $config) { $this->logger = $logger; - $this->user = $userSession && $userSession->isLoggedIn() ? $userSession->getUser() : false; + $this->user = $userSession && $userSession->isLoggedIn() ? $userSession->getUser()->getUID() : '"no user given"'; $this->config = $config; $this->supportedKeyFormats = ['hash', 'password']; } @@ -89,7 +90,7 @@ class Crypt { $res = $this->getOpenSSLPKey(); if (!$res) { - $log->error("Encryption Library couldn't generate users key-pair for {$this->user->getUID()}", + $log->error("Encryption Library couldn't generate users key-pair for {$this->user}", ['app' => 'encryption']); if (openssl_error_string()) { @@ -108,7 +109,7 @@ class Crypt { 'privateKey' => $privateKey ]; } - $log->error('Encryption library couldn\'t export users private key, please check your servers OpenSSL configuration.' . $this->user->getUID(), + $log->error('Encryption library couldn\'t export users private key, please check your servers OpenSSL configuration.' . $this->user, ['app' => 'encryption']); if (openssl_error_string()) { $log->error('Encryption Library:' . openssl_error_string(), diff --git a/apps/encryption/lib/crypto/encryption.php b/apps/encryption/lib/crypto/encryption.php index 1a05277e20d..d1140ce7cde 100644 --- a/apps/encryption/lib/crypto/encryption.php +++ b/apps/encryption/lib/crypto/encryption.php @@ -378,6 +378,12 @@ class Encryption implements IEncryptionModule { * @return boolean */ public function shouldEncrypt($path) { + if ($this->util->shouldEncryptHomeStorage() === false) { + $storage = $this->util->getStorage($path); + if ($storage->instanceOfStorage('\OCP\Files\IHomeStorage')) { + return false; + } + } $parts = explode('/', $path); if (count($parts) < 4) { return false; diff --git a/apps/encryption/lib/util.php b/apps/encryption/lib/util.php index a162dcde305..62907f8a460 100644 --- a/apps/encryption/lib/util.php +++ b/apps/encryption/lib/util.php @@ -94,12 +94,41 @@ class Util { $recoveryMode = $this->config->getUserValue($uid, 'encryption', 'recoveryEnabled', - 0); + '0'); return ($recoveryMode === '1'); } /** + * check if the home storage should be encrypted + * + * @return bool + */ + public function shouldEncryptHomeStorage() { + $encryptHomeStorage = $this->config->getAppValue( + 'encryption', + 'encryptHomeStorage', + '1' + ); + + return ($encryptHomeStorage === '1'); + } + + /** + * set the home storage encryption on/off + * + * @param bool $encryptHomeStorage + */ + public function setEncryptHomeStorage($encryptHomeStorage) { + $value = $encryptHomeStorage ? '1' : '0'; + $this->config->setAppValue( + 'encryption', + 'encryptHomeStorage', + $value + ); + } + + /** * check if master key is enabled * * @return bool @@ -157,4 +186,15 @@ class Util { return $owner; } + /** + * get storage of path + * + * @param string $path + * @return \OC\Files\Storage\Storage + */ + public function getStorage($path) { + $storage = $this->files->getMount($path)->getStorage(); + return $storage; + } + } diff --git a/apps/encryption/settings/settings-admin.php b/apps/encryption/settings/settings-admin.php index c7ac8c09c6b..8d55d587fed 100644 --- a/apps/encryption/settings/settings-admin.php +++ b/apps/encryption/settings/settings-admin.php @@ -25,12 +25,27 @@ $tmpl = new OCP\Template('encryption', 'settings-admin'); +$crypt = new \OCA\Encryption\Crypto\Crypt( + \OC::$server->getLogger(), + \OC::$server->getUserSession(), + \OC::$server->getConfig()); + +$util = new \OCA\Encryption\Util( + new \OC\Files\View(), + $crypt, + \OC::$server->getLogger(), + \OC::$server->getUserSession(), + \OC::$server->getConfig(), + \OC::$server->getUserManager()); + // Check if an adminRecovery account is enabled for recovering files after lost pwd $recoveryAdminEnabled = \OC::$server->getConfig()->getAppValue('encryption', 'recoveryAdminEnabled', '0'); $session = new \OCA\Encryption\Session(\OC::$server->getSession()); +$encryptHomeStorage = $util->shouldEncryptHomeStorage($user); $tmpl->assign('recoveryEnabled', $recoveryAdminEnabled); $tmpl->assign('initStatus', $session->getStatus()); +$tmpl->assign('encryptHomeStorage', $encryptHomeStorage); return $tmpl->fetchPage(); diff --git a/apps/encryption/templates/settings-admin.php b/apps/encryption/templates/settings-admin.php index 81c7f0607d8..e55aba6757c 100644 --- a/apps/encryption/templates/settings-admin.php +++ b/apps/encryption/templates/settings-admin.php @@ -9,56 +9,63 @@ style('encryption', 'settings-admin'); <?php if(!$_["initStatus"]): ?> <?php p($l->t("Encryption App is enabled but your keys are not initialized, please log-out and log-in again")); ?> <?php else: ?> - <p id="encryptionSetRecoveryKey"> - <?php $_["recoveryEnabled"] === '0' ? p($l->t("Enable recovery key")) : p($l->t("Disable recovery key")); ?> - <span class="msg"></span> - <br/> - <em> - <?php p($l->t("The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password.")) ?> - </em> - <br/> - <input type="password" - name="encryptionRecoveryPassword" - id="encryptionRecoveryPassword" - placeholder="<?php p($l->t("Recovery key password")); ?>"/> - <input type="password" - name="encryptionRecoveryPassword" - id="repeatEncryptionRecoveryPassword" - placeholder="<?php p($l->t("Repeat recovery key password")); ?>"/> - <input type="button" - name="enableRecoveryKey" - id="enableRecoveryKey" - status="<?php p($_["recoveryEnabled"]) ?>" - value="<?php $_["recoveryEnabled"] === '0' ? p($l->t("Enable recovery key")) : p($l->t("Disable recovery key")); ?>"/> - </p> - <br/><br/> - - <p name="changeRecoveryPasswordBlock" id="encryptionChangeRecoveryKey" <?php if($_['recoveryEnabled'] === '0') print_unescaped('class="hidden"');?>> - <?php p($l->t("Change recovery key password:")); ?> - <span class="msg"></span> - <br/> - <input - type="password" - name="changeRecoveryPassword" - id="oldEncryptionRecoveryPassword" - placeholder="<?php p($l->t("Old recovery key password")); ?>"/> + <p id="encryptHomeStorageSetting"> + <input type="checkbox" class="checkbox" name="encrypt_home_storage" id="encryptHomeStorage" + value="1" <?php if ($_['encryptHomeStorage']) print_unescaped('checked="checked"'); ?> /> + <label for="encryptHomeStorage"><?php p($l->t('Encrypt the home storage'));?></label></br> + <em><?php p( $l->t( "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" ) ); ?></em> + </p> <br /> - <input - type="password" - name="changeRecoveryPassword" - id="newEncryptionRecoveryPassword" - placeholder="<?php p($l->t("New recovery key password")); ?>"/> - <input - type="password" - name="changeRecoveryPassword" - id="repeatedNewEncryptionRecoveryPassword" - placeholder="<?php p($l->t("Repeat new recovery key password")); ?>"/> + <p id="encryptionSetRecoveryKey"> + <?php $_["recoveryEnabled"] === '0' ? p($l->t("Enable recovery key")) : p($l->t("Disable recovery key")); ?> + <span class="msg"></span> + <br/> + <em> + <?php p($l->t("The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password.")) ?> + </em> + <br/> + <input type="password" + name="encryptionRecoveryPassword" + id="encryptionRecoveryPassword" + placeholder="<?php p($l->t("Recovery key password")); ?>"/> + <input type="password" + name="encryptionRecoveryPassword" + id="repeatEncryptionRecoveryPassword" + placeholder="<?php p($l->t("Repeat recovery key password")); ?>"/> + <input type="button" + name="enableRecoveryKey" + id="enableRecoveryKey" + status="<?php p($_["recoveryEnabled"]) ?>" + value="<?php $_["recoveryEnabled"] === '0' ? p($l->t("Enable recovery key")) : p($l->t("Disable recovery key")); ?>"/> + </p> + <br/><br/> + + <p name="changeRecoveryPasswordBlock" id="encryptionChangeRecoveryKey" <?php if($_['recoveryEnabled'] === '0') print_unescaped('class="hidden"');?>> + <?php p($l->t("Change recovery key password:")); ?> + <span class="msg"></span> + <br/> + <input + type="password" + name="changeRecoveryPassword" + id="oldEncryptionRecoveryPassword" + placeholder="<?php p($l->t("Old recovery key password")); ?>"/> + <br /> + <input + type="password" + name="changeRecoveryPassword" + id="newEncryptionRecoveryPassword" + placeholder="<?php p($l->t("New recovery key password")); ?>"/> + <input + type="password" + name="changeRecoveryPassword" + id="repeatedNewEncryptionRecoveryPassword" + placeholder="<?php p($l->t("Repeat new recovery key password")); ?>"/> - <button - type="button" - name="submitChangeRecoveryKey"> + <button + type="button" + name="submitChangeRecoveryKey"> <?php p($l->t("Change Password")); ?> - </button> - </p> + </button> + </p> <?php endif; ?> </form> diff --git a/apps/encryption/tests/controller/SettingsControllerTest.php b/apps/encryption/tests/controller/SettingsControllerTest.php index 724a01522af..3b30e61a45b 100644 --- a/apps/encryption/tests/controller/SettingsControllerTest.php +++ b/apps/encryption/tests/controller/SettingsControllerTest.php @@ -56,6 +56,9 @@ class SettingsControllerTest extends TestCase { /** @var \PHPUnit_Framework_MockObject_MockObject */ private $ocSessionMock; + /** @var \PHPUnit_Framework_MockObject_MockObject */ + private $utilMock; + protected function setUp() { parent::setUp(); @@ -106,6 +109,10 @@ class SettingsControllerTest extends TestCase { $this->sessionMock = $this->getMockBuilder('OCA\Encryption\Session') ->disableOriginalConstructor()->getMock(); + $this->utilMock = $this->getMockBuilder('OCA\Encryption\Util') + ->disableOriginalConstructor() + ->getMock(); + $this->controller = new SettingsController( 'encryption', $this->requestMock, @@ -115,7 +122,8 @@ class SettingsControllerTest extends TestCase { $this->keyManagerMock, $this->cryptMock, $this->sessionMock, - $this->ocSessionMock + $this->ocSessionMock, + $this->utilMock ); } @@ -234,4 +242,10 @@ class SettingsControllerTest extends TestCase { $data['message']); } + function testSetEncryptHomeStorage() { + $value = true; + $this->utilMock->expects($this->once())->method('setEncryptHomeStorage')->with($value); + $this->controller->setEncryptHomeStorage($value); + } + } diff --git a/apps/encryption/tests/lib/MigrationTest.php b/apps/encryption/tests/lib/MigrationTest.php index be37020660c..65fefa262a7 100644 --- a/apps/encryption/tests/lib/MigrationTest.php +++ b/apps/encryption/tests/lib/MigrationTest.php @@ -2,6 +2,7 @@ /** * @author Björn Schießle <schiessle@owncloud.com> * @author Joas Schilling <nickvergessen@owncloud.com> + * @author Robin Appelman <icewind@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 diff --git a/apps/encryption/tests/lib/UtilTest.php b/apps/encryption/tests/lib/UtilTest.php index 723cc9fb910..d55b6b50b3e 100644 --- a/apps/encryption/tests/lib/UtilTest.php +++ b/apps/encryption/tests/lib/UtilTest.php @@ -39,6 +39,9 @@ class UtilTest extends TestCase { /** @var \PHPUnit_Framework_MockObject_MockObject */ private $userManagerMock; + /** @var \PHPUnit_Framework_MockObject_MockObject */ + private $mountMock; + /** @var Util */ private $instance; @@ -65,6 +68,7 @@ class UtilTest extends TestCase { protected function setUp() { parent::setUp(); + $this->mountMock = $this->getMock('\OCP\Files\Mount\IMountPoint'); $this->filesMock = $this->getMock('OC\Files\View'); $this->userManagerMock = $this->getMock('\OCP\IUserManager'); @@ -151,4 +155,52 @@ class UtilTest extends TestCase { ]; } + /** + * @dataProvider dataTestShouldEncryptHomeStorage + * @param $returnValue return value from getAppValue() + * @param $expected + */ + public function testShouldEncryptHomeStorage($returnValue, $expected) { + $this->configMock->expects($this->once())->method('getAppValue') + ->with('encryption', 'encryptHomeStorage', '1') + ->willReturn($returnValue); + + $this->assertSame($expected, + $this->instance->shouldEncryptHomeStorage()); + } + + public function dataTestShouldEncryptHomeStorage() { + return [ + ['1', true], + ['0', false] + ]; + } + + /** + * @dataProvider dataTestSetEncryptHomeStorage + * @param $value + * @param $expected + */ + public function testSetEncryptHomeStorage($value, $expected) { + $this->configMock->expects($this->once())->method('setAppValue') + ->with('encryption', 'encryptHomeStorage', $expected); + $this->instance->setEncryptHomeStorage($value); + } + + public function dataTestSetEncryptHomeStorage() { + return [ + [true, '1'], + [false, '0'] + ]; + } + + public function testGetStorage() { + $path = '/foo/bar.txt'; + $this->filesMock->expects($this->once())->method('getMount')->with($path) + ->willReturn($this->mountMock); + $this->mountMock->expects($this->once())->method('getStorage')->willReturn(true); + + $this->assertTrue($this->instance->getStorage($path)); + } + } diff --git a/apps/encryption/tests/lib/crypto/encryptionTest.php b/apps/encryption/tests/lib/crypto/encryptionTest.php index f76bdfb6d61..138c1bc9446 100644 --- a/apps/encryption/tests/lib/crypto/encryptionTest.php +++ b/apps/encryption/tests/lib/crypto/encryptionTest.php @@ -55,9 +55,14 @@ class EncryptionTest extends TestCase { /** @var \PHPUnit_Framework_MockObject_MockObject */ private $l10nMock; + /** @var \PHPUnit_Framework_MockObject_MockObject */ + private $storageMock; + public function setUp() { parent::setUp(); + $this->storageMock = $this->getMockBuilder('OCP\Files\Storage') + ->disableOriginalConstructor()->getMock(); $this->cryptMock = $this->getMockBuilder('OCA\Encryption\Crypto\Crypt') ->disableOriginalConstructor() ->getMock(); @@ -312,7 +317,17 @@ class EncryptionTest extends TestCase { * * @dataProvider dataTestShouldEncrypt */ - public function testShouldEncrypt($path, $expected) { + public function testShouldEncrypt($path, $shouldEncryptHomeStorage, $isHomeStorage, $expected) { + $this->utilMock->expects($this->once())->method('shouldEncryptHomeStorage') + ->willReturn($shouldEncryptHomeStorage); + + if ($shouldEncryptHomeStorage === false) { + $this->storageMock->expects($this->once())->method('instanceOfStorage') + ->with('\OCP\Files\IHomeStorage')->willReturn($isHomeStorage); + $this->utilMock->expects($this->once())->method('getStorage')->with($path) + ->willReturn($this->storageMock); + } + $this->assertSame($expected, $this->instance->shouldEncrypt($path) ); @@ -320,14 +335,17 @@ class EncryptionTest extends TestCase { public function dataTestShouldEncrypt() { return array( - array('/user1/files/foo.txt', true), - array('/user1/files_versions/foo.txt', true), - array('/user1/files_trashbin/foo.txt', true), - array('/user1/some_folder/foo.txt', false), - array('/user1/foo.txt', false), - array('/user1/files', false), - array('/user1/files_trashbin', false), - array('/user1/files_versions', false), + array('/user1/files/foo.txt', true, true, true), + array('/user1/files_versions/foo.txt', true, true, true), + array('/user1/files_trashbin/foo.txt', true, true, true), + array('/user1/some_folder/foo.txt', true, true, false), + array('/user1/foo.txt', true, true, false), + array('/user1/files', true, true, false), + array('/user1/files_trashbin', true, true, false), + array('/user1/files_versions', true, true, false), + // test if shouldEncryptHomeStorage is set to false + array('/user1/files/foo.txt', false, true, false), + array('/user1/files_versions/foo.txt', false, false, true), ); } 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/application.php b/apps/files/appinfo/application.php index 6ba77e09556..6aff517e17f 100644 --- a/apps/files/appinfo/application.php +++ b/apps/files/appinfo/application.php @@ -1,6 +1,6 @@ <?php /** - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Tobias Kaminsky <tobias@kaminsky.me> * @author Vincent Petry <pvince81@owncloud.com> * diff --git a/apps/files/appinfo/routes.php b/apps/files/appinfo/routes.php index 41aeec6a152..2bb913c30a6 100644 --- a/apps/files/appinfo/routes.php +++ b/apps/files/appinfo/routes.php @@ -2,7 +2,7 @@ /** * @author Bart Visscher <bartv@thisnet.nl> * @author Lukas Reschke <lukas@owncloud.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Tobias Kaminsky <tobias@kaminsky.me> * @author Tom Needham <tom@owncloud.com> * @author Vincent Petry <pvince81@owncloud.com> @@ -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/apicontroller.php b/apps/files/controller/apicontroller.php index ea5ee81a9f6..1ecd5294c66 100644 --- a/apps/files/controller/apicontroller.php +++ b/apps/files/controller/apicontroller.php @@ -3,7 +3,7 @@ * @author Joas Schilling <nickvergessen@owncloud.com> * @author Lukas Reschke <lukas@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Thomas Müller <thomas.mueller@tmit.eu> * @author Tobias Kaminsky <tobias@kaminsky.me> * @author Vincent Petry <pvince81@owncloud.com> 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 @@ +<?php +/** + * @author Lukas Reschke <lukas@owncloud.com> + * + * @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 <http://www.gnu.org/licenses/> + * + */ + +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 @@ -<?php -/** - * @author Björn Schießle <schiessle@owncloud.com> - * @author Frank Karlitschek <frank@owncloud.org> - * @author Jakob Sack <mail@jakobsack.de> - * @author Jan-Christoph Borchardt <hey@jancborchardt.net> - * @author Joas Schilling <nickvergessen@owncloud.com> - * @author Jörn Friedrich Dreyer <jfd@butonic.de> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Robin Appelman <icewind@owncloud.com> - * @author Roman Geber <rgeber@owncloudapps.com> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * @author Vincent Petry <pvince81@owncloud.com> - * - * @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 <http://www.gnu.org/licenses/> - * - */ - -// 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/js/favoritesfilelist.js b/apps/files/js/favoritesfilelist.js index 4e7db9f17ba..e6532ab188c 100644 --- a/apps/files/js/favoritesfilelist.js +++ b/apps/files/js/favoritesfilelist.js @@ -71,6 +71,10 @@ $(document).ready(function() { if (this._reloadCall) { this._reloadCall.abort(); } + + // there is only root + this._setCurrentDir('/', false); + this._reloadCall = $.ajax({ url: OC.generateUrl('/apps/files/api/v1/tags/{tagName}/files', {tagName: tagName}), type: 'GET', @@ -86,10 +90,9 @@ $(document).ready(function() { if (result.files) { this.setFiles(result.files.sort(this._sortComparator)); + return true; } - else { - // TODO: error handling - } + return false; } }); diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js index 77b85ecd7da..d419cb3a2c0 100644 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -18,7 +18,7 @@ * - TODO music upload button */ -/* global jQuery, oc_requesttoken, humanFileSize */ +/* global jQuery, oc_requesttoken, humanFileSize, FileList */ /** * Function that will allow us to know if Ajax uploads are supported @@ -48,6 +48,26 @@ function supportAjaxUploadWithProgress() { } /** + * Add form data into the given form data + * + * @param {Array|Object} formData form data which can either be an array or an object + * @param {Object} newData key-values to add to the form data + * + * @return updated form data + */ +function addFormData(formData, newData) { + // in IE8, formData is an array instead of object + if (_.isArray(formData)) { + _.each(newData, function(value, key) { + formData.push({name: key, value: value}); + }); + } else { + formData = _.extend(formData, newData); + } + return formData; +} + +/** * keeps track of uploads in progress and implements callbacks for the conflicts dialog * @namespace */ @@ -143,9 +163,9 @@ OC.Upload = { data.data.append('resolution', 'replace'); } else { if (!data.formData) { - data.formData = []; + data.formData = {}; } - data.formData.push({name:'resolution', value:'replace'}); //hack for ie8 + addFormData(data.formData, {resolution: 'replace'}); } data.submit(); }, @@ -159,9 +179,9 @@ OC.Upload = { data.data.append('resolution', 'autorename'); } else { if (!data.formData) { - data.formData = []; + data.formData = {}; } - data.formData.push({name:'resolution', value:'autorename'}); //hack for ie8 + addFormData(data.formData, {resolution: 'autorename'}); } data.submit(); }, @@ -185,7 +205,7 @@ OC.Upload = { * @param {function} callbacks.onCancel */ checkExistingFiles: function (selection, callbacks) { - var fileList = OCA.Files.App.fileList; + var fileList = FileList; var conflicts = []; // only keep non-conflicting uploads selection.uploads = _.filter(selection.uploads, function(upload) { @@ -402,17 +422,19 @@ OC.Upload = { submit: function(e, data) { OC.Upload.rememberUpload(data); if (!data.formData) { - data.formData = []; + data.formData = {}; } var fileDirectory = ''; if(typeof data.files[0].relativePath !== 'undefined') { fileDirectory = data.files[0].relativePath; } - // FIXME: prevent re-adding the same - data.formData.push({name: 'requesttoken', value: oc_requesttoken}); - data.formData.push({name: 'dir', value: data.targetDir || FileList.getCurrentDirectory()}); - data.formData.push({name: 'file_directory', value: fileDirectory}); + + addFormData(data.formData, { + requesttoken: oc_requesttoken, + dir: data.targetDir || FileList.getCurrentDirectory(), + file_directory: fileDirectory + }); }, fail: function(e, data) { OC.Upload.log('fail', e, data); diff --git a/apps/files/js/fileactions.js b/apps/files/js/fileactions.js index 079c5330ec2..6a767d48a28 100644 --- a/apps/files/js/fileactions.js +++ b/apps/files/js/fileactions.js @@ -589,7 +589,7 @@ context.fileList.showFileBusyState(filename, false); }; - context.fileList.showFileBusyState(downloadFileaction, true); + context.fileList.showFileBusyState(filename, true); OCA.Files.Files.handleDownload(url, disableLoadingState); } } diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 4f5fdf242d9..d1f68d98eab 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -390,12 +390,15 @@ * Update the details view to display the given file * * @param {string} fileName file name from the current list + * @param {boolean} [show=true] whether to open the sidebar if it was closed */ - _updateDetailsView: function(fileName) { + _updateDetailsView: function(fileName, show) { if (!this._detailsView) { return; } + // show defaults to true + show = _.isUndefined(show) || !!show; var oldFileInfo = this._detailsView.getFileInfo(); if (oldFileInfo) { // TODO: use more efficient way, maybe track the highlight @@ -413,7 +416,7 @@ return; } - if (this._detailsView.$el.hasClass('disappear')) { + if (show && this._detailsView.$el.hasClass('disappear')) { OC.Apps.showAppSidebar(this._detailsView.$el); } @@ -764,7 +767,7 @@ */ elementToFile: function($el){ $el = $($el); - return { + var data = { id: parseInt($el.attr('data-id'), 10), name: $el.attr('data-file'), mimetype: $el.attr('data-mime'), @@ -774,6 +777,15 @@ etag: $el.attr('data-etag'), permissions: parseInt($el.attr('data-permissions'), 10) }; + var icon = $el.attr('data-icon'); + if (icon) { + data.icon = icon; + } + var mountType = $el.attr('data-mounttype'); + if (mountType) { + data.mountType = mountType; + } + return data; }, /** @@ -896,11 +908,12 @@ mtime = parseInt(fileData.mtime, 10), mime = fileData.mimetype, path = fileData.path, + dataIcon = null, linkUrl; options = options || {}; if (isNaN(mtime)) { - mtime = new Date().getTime() + mtime = new Date().getTime(); } if (type === 'dir') { @@ -908,6 +921,7 @@ if (fileData.mountType && fileData.mountType.indexOf('external') === 0) { icon = OC.MimeType.getIconUrl('dir-external'); + dataIcon = icon; } } @@ -923,6 +937,11 @@ "data-permissions": fileData.permissions || this.getDirectoryPermissions() }); + if (dataIcon) { + // icon override + tr.attr('data-icon', dataIcon); + } + if (fileData.mountType) { tr.attr('data-mounttype', fileData.mountType); } @@ -1174,7 +1193,7 @@ // display actions this.fileActions.display(filenameTd, !options.silent, this); - if (fileData.isPreviewAvailable) { + if (fileData.isPreviewAvailable && 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 @@ -1771,7 +1790,7 @@ tr.remove(); tr = self.add(fileInfo, {updateSummary: false, silent: true}); self.$fileList.trigger($.Event('fileActionsReady', {fileList: self, $files: $(tr)})); - self._updateDetailsView(fileInfo.name); + self._updateDetailsView(fileInfo.name, false); } }); } else { @@ -2114,15 +2133,16 @@ this.hideIrrelevantUIWhenNoFilesMatch(); } var that = this; + filter = filter.toLowerCase(); this.$fileList.find('tr').each(function(i,e) { var $e = $(e); - if ($e.data('file').toString().toLowerCase().indexOf(filter.toLowerCase()) === -1) { + if ($e.data('file').toString().toLowerCase().indexOf(filter) === -1) { $e.addClass('hidden'); - that.$container.trigger('scroll'); } else { $e.removeClass('hidden'); } }); + that.$container.trigger('scroll'); }, hideIrrelevantUIWhenNoFilesMatch:function() { if (this._filter && this.fileSummary.summary.totalDirs + this.fileSummary.summary.totalFiles === 0) { diff --git a/apps/files/js/files.js b/apps/files/js/files.js index 9ab7609cc40..ae38511ec05 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -295,7 +295,12 @@ } }; - OC.redirect(url + '&downloadStartSecret=' + randomToken); + if (url.indexOf('?') >= 0) { + url += '&'; + } else { + url += '?'; + } + OC.redirect(url + 'downloadStartSecret=' + randomToken); OC.Util.waitFor(checkForDownloadCookie, 500); } }; diff --git a/apps/files/js/mainfileinfodetailview.js b/apps/files/js/mainfileinfodetailview.js index abf7da52ff4..69c796e492f 100644 --- a/apps/files/js/mainfileinfodetailview.js +++ b/apps/files/js/mainfileinfodetailview.js @@ -128,8 +128,8 @@ $iconDiv.addClass('icon-loading icon-32'); this.loadPreview(this.model.getFullPath(), this.model.get('mimetype'), this.model.get('etag'), $iconDiv, $container, this.model.isImage()); } else { - // TODO: special icons / shared / external - $iconDiv.css('background-image', 'url("' + OC.MimeType.getIconUrl('dir') + '")'); + var iconUrl = this.model.get('icon') || OC.MimeType.getIconUrl('dir'); + $iconDiv.css('background-image', 'url("' + iconUrl + '")'); OC.Util.scaleFixForIE8($iconDiv); } this.$el.find('[title]').tooltip({placement: 'bottom'}); diff --git a/apps/files/js/newfilemenu.js b/apps/files/js/newfilemenu.js index 0a67aba202b..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,7 +60,20 @@ console.warn('Missing upload element "file_upload_start"'); } - this._fileList = options && options.fileList; + this.fileList = options && options.fileList; + + this._menuItems = [{ + id: 'folder', + displayName: t('files', 'Folder'), + templateName: t('files', 'New folder'), + iconClass: 'icon-folder', + fileType: 'folder', + actionHandler: function(name) { + self.fileList.createDirectory(name); + } + }]; + + OC.Plugins.attach('OCA.Files.NewFileMenu', this); }, template: function(data) { @@ -127,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; @@ -163,7 +181,14 @@ if (checkInput()) { var newname = $input.val(); - self._createFile(fileType, newname); + + /* Find the right actionHandler that should be called. + * Actions is retrieved by using `actionSpec.id` */ + action = _.filter(self._menuItems, function(item) { + return item.id == $target.attr('data-action'); + }).pop(); + action.actionHandler(newname); + $form.remove(); $target.find('.displayname').removeClass('hidden'); OC.hideMenus(); @@ -172,23 +197,21 @@ }, /** - * Creates a file with the given type and name. - * This calls the matching methods on the attached file list. - * - * @param {string} fileType file type - * @param {string} name file name - */ - _createFile: function(fileType, name) { - switch(fileType) { - case 'file': - this._fileList.createFile(name); - break; - case 'folder': - this._fileList.createDirectory(name); - break; - default: - console.warn('Unknown file type "' + fileType + '"'); - } + * Add a new item menu entry in the “New” file menu (in + * last position). By clicking on the item, the + * `actionHandler` function is called. + * + * @param {Object} actionSpec item’s properties + */ + addMenuEntry: function(actionSpec) { + this._menuItems.push({ + id: actionSpec.id, + displayName: actionSpec.displayName, + templateName: actionSpec.templateName, + iconClass: actionSpec.iconClass, + fileType: actionSpec.fileType, + actionHandler: actionSpec.actionHandler, + }); }, /** @@ -198,19 +221,7 @@ this.$el.html(this.template({ uploadMaxHumanFileSize: 'TODO', uploadLabel: t('files', 'Upload'), - items: [{ - id: 'file', - displayName: t('files', 'Text file'), - templateName: t('files', 'New text file.txt'), - iconClass: 'icon-filetype-text', - fileType: 'file' - }, { - id: 'folder', - displayName: t('files', 'Folder'), - templateName: t('files', 'New folder'), - iconClass: 'icon-folder', - fileType: 'folder' - }] + items: this._menuItems })); OC.Util.scaleFixForIE8(this.$('.svg')); }, 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 <strong>created</strong>" : "تم <strong> إنشاء</strong> ملف جديد أو مجلد ", "A file or folder has been <strong>changed</strong>" : "تم <strong> تغيير</strong> ملف أو مجلد", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "استخدم هذا العنوان لـ <a href=\"%s\" target=\"_blank\">الدخول الى ملفاتك عن طريق WebDAV</a>", 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 <strong>created</strong>" : "تم <strong> إنشاء</strong> ملف جديد أو مجلد ", "A file or folder has been <strong>changed</strong>" : "تم <strong> تغيير</strong> ملف أو مجلد", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "استخدم هذا العنوان لـ <a href=\"%s\" target=\"_blank\">الدخول الى ملفاتك عن طريق WebDAV</a>", diff --git a/apps/files/l10n/ast.js b/apps/files/l10n/ast.js index ffba40ec793..5dfcae172ea 100644 --- a/apps/files/l10n/ast.js +++ b/apps/files/l10n/ast.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Favoritos", "Home" : "Casa", "Close" : "Zarrar", + "Upload cancelled." : "Xuba encaboxada.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Nun pudo xubise {filename}, paez que ye un directoriu o tien 0 bytes", "Total file size {size1} exceeds upload limit {size2}" : "El tamañu de ficheru total {size1} perpasa la llende de xuba {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Nun hai abondu espaciu llibre, tas xubiendo {size1} pero namái falta {size2}", - "Upload cancelled." : "Xuba encaboxada.", "Could not get result from server." : "Nun pudo obtenese'l resultáu del sirvidor.", "File upload is in progress. Leaving the page now will cancel the upload." : "La xuba del ficheru ta en progresu. Si dexes agora la páxina, va encaboxase la xuba.", "Actions" : "Aiciones", @@ -45,6 +45,7 @@ OC.L10N.register( "Pending" : "Pendiente", "Unable to determine date" : "Imposible determinar la fecha", "This operation is forbidden" : "La operación ta prohibida", + "This directory is unavailable, please check the logs or contact the administrator" : "Esti direutoriu nun ta disponible, por favor verifica'l rexistru o contacta l'alministrador", "Error moving file." : "Fallu moviendo'l ficheru.", "Error moving file" : "Fallu moviendo'l ficheru", "Error" : "Fallu", @@ -53,6 +54,7 @@ OC.L10N.register( "Could not create file" : "Nun pudo crease'l ficheru", "Could not create folder" : "Nun pudo crease la carpeta", "Error deleting file." : "Fallu desaniciando'l ficheru.", + "No entries in this folder match '{filter}'" : "Nun concasa nenguna entrada nesta carpeta '{filter}'", "Name" : "Nome", "Size" : "Tamañu", "Modified" : "Modificáu", @@ -64,15 +66,25 @@ OC.L10N.register( "New" : "Nuevu", "\"{name}\" is an invalid file name." : "\"{name}\" ye un nome de ficheru inválidu.", "File name cannot be empty." : "El nome de ficheru nun pue quedar baleru.", + "Storage of {owner} is full, files can not be updated or synced anymore!" : "L'almacenamientu de {owner} ta completu, ¡yá nun se pueden anovar o sincronizar ficheros!", "Your storage is full, files can not be updated or synced anymore!" : "L'almacenamientu ta completu, ¡yá nun se pueden anovar o sincronizar ficheros!", + "Storage of {owner} is almost full ({usedSpacePercent}%)" : "L'almacenamientu de {owner} ta casi completu ({usedSpacePercent}%)", "Your storage is almost full ({usedSpacePercent}%)" : "L'almacenamientu ta casi completu ({usedSpacePercent}%)", + "_matches '{filter}'_::_match '{filter}'_" : ["concasa '{filter}'","concasa '{filter}'"], + "Path" : "Camín", + "_%n byte_::_%n bytes_" : ["%n bytes","%n bytes"], + "Favorited" : "Favoritos", "Favorite" : "Favoritu", - "Upload" : "Xubir", "Text file" : "Ficheru de testu", + "New text file.txt" : "Nuevu testu ficheru.txt", "Folder" : "Carpeta", "New folder" : "Nueva carpeta", + "{newname} already exists" : "{newname} yá existe", + "Upload" : "Xubir", + "An error occurred while trying to update the tags" : "Hebo un fallu mientres s'intentaba actualizar les etiquetes", "A new file or folder has been <strong>created</strong>" : "<strong>Creóse</strong> un ficheru o carpeta nuevos", "A file or folder has been <strong>changed</strong>" : "<strong>Camudóse</strong> un ficheru o carpeta", + "Limit notifications about creation and changes to your <strong>favorite files</strong> <em>(Stream only)</em>" : "Llendar les notificaciones tocantes a creación y cambeos a tos <strong>ficheros favoritos</strong <em>(namás Stream)</em>", "A file or folder has been <strong>deleted</strong>" : "<strong>Desanicióse</strong> un ficheru o carpeta", "A file or folder has been <strong>restored</strong>" : "<strong>Restauróse</strong> un ficheru o carpeta", "You created %1$s" : "Creasti %1$s", @@ -84,6 +96,9 @@ OC.L10N.register( "%2$s deleted %1$s" : "%2$s desanició %1$s", "You restored %1$s" : "Recuperóse %1$s", "%2$s restored %1$s" : "%2$s recuperó %1$s", + "Changed by %2$s" : "Modificáu por %2$s", + "Deleted by %2$s" : "Desaniciáu por %2$s", + "Restored by %2$s" : "Recuperáu por %2$s", "%s could not be renamed as it has been deleted" : "%s nun pue renomase dempués de desaniciase", "%s could not be renamed" : "Nun se puede renomar %s ", "Upload (max. %s)" : "Xuba (máx. %s)", @@ -95,9 +110,15 @@ OC.L10N.register( "WebDAV" : "WebDAV", "Use this address to <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Usa esta direición <a href=\"%s\" target=\"_blank\">p'acceder a los ficheros a traviés de WebDAV</a>", "Cancel upload" : "Encaboxar xuba", + "No files in here" : "Nun hai nengún ficheru equí", + "Upload some content or sync with your devices!" : "¡Xuba algún conteníu o sincroniza colos sos preseos!", + "No entries found in this folder" : "Nenguna entrada en esta carpeta", + "Select all" : "Esbillar too", "Upload too large" : "La xuba ye abondo grande", "The files you are trying to upload exceed the maximum size for file uploads on this server." : "Los ficheros que tas intentando xubir perpasen el tamañu máximu pa les xubíes de ficheros nesti servidor.", "Files are being scanned, please wait." : "Tan escaniándose los ficheros, espera por favor.", - "Currently scanning" : "Anguaño escaneando" + "Currently scanning" : "Anguaño escaneando", + "No favorites" : "Nengún favoritu", + "Files and folders you mark as favorite will show up here" : "Los ficheros y carpetes que marque como favoritos apaecerán equí" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files/l10n/ast.json b/apps/files/l10n/ast.json index 353511d5586..a0934808529 100644 --- a/apps/files/l10n/ast.json +++ b/apps/files/l10n/ast.json @@ -28,10 +28,10 @@ "Favorites" : "Favoritos", "Home" : "Casa", "Close" : "Zarrar", + "Upload cancelled." : "Xuba encaboxada.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Nun pudo xubise {filename}, paez que ye un directoriu o tien 0 bytes", "Total file size {size1} exceeds upload limit {size2}" : "El tamañu de ficheru total {size1} perpasa la llende de xuba {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Nun hai abondu espaciu llibre, tas xubiendo {size1} pero namái falta {size2}", - "Upload cancelled." : "Xuba encaboxada.", "Could not get result from server." : "Nun pudo obtenese'l resultáu del sirvidor.", "File upload is in progress. Leaving the page now will cancel the upload." : "La xuba del ficheru ta en progresu. Si dexes agora la páxina, va encaboxase la xuba.", "Actions" : "Aiciones", @@ -43,6 +43,7 @@ "Pending" : "Pendiente", "Unable to determine date" : "Imposible determinar la fecha", "This operation is forbidden" : "La operación ta prohibida", + "This directory is unavailable, please check the logs or contact the administrator" : "Esti direutoriu nun ta disponible, por favor verifica'l rexistru o contacta l'alministrador", "Error moving file." : "Fallu moviendo'l ficheru.", "Error moving file" : "Fallu moviendo'l ficheru", "Error" : "Fallu", @@ -51,6 +52,7 @@ "Could not create file" : "Nun pudo crease'l ficheru", "Could not create folder" : "Nun pudo crease la carpeta", "Error deleting file." : "Fallu desaniciando'l ficheru.", + "No entries in this folder match '{filter}'" : "Nun concasa nenguna entrada nesta carpeta '{filter}'", "Name" : "Nome", "Size" : "Tamañu", "Modified" : "Modificáu", @@ -62,15 +64,25 @@ "New" : "Nuevu", "\"{name}\" is an invalid file name." : "\"{name}\" ye un nome de ficheru inválidu.", "File name cannot be empty." : "El nome de ficheru nun pue quedar baleru.", + "Storage of {owner} is full, files can not be updated or synced anymore!" : "L'almacenamientu de {owner} ta completu, ¡yá nun se pueden anovar o sincronizar ficheros!", "Your storage is full, files can not be updated or synced anymore!" : "L'almacenamientu ta completu, ¡yá nun se pueden anovar o sincronizar ficheros!", + "Storage of {owner} is almost full ({usedSpacePercent}%)" : "L'almacenamientu de {owner} ta casi completu ({usedSpacePercent}%)", "Your storage is almost full ({usedSpacePercent}%)" : "L'almacenamientu ta casi completu ({usedSpacePercent}%)", + "_matches '{filter}'_::_match '{filter}'_" : ["concasa '{filter}'","concasa '{filter}'"], + "Path" : "Camín", + "_%n byte_::_%n bytes_" : ["%n bytes","%n bytes"], + "Favorited" : "Favoritos", "Favorite" : "Favoritu", - "Upload" : "Xubir", "Text file" : "Ficheru de testu", + "New text file.txt" : "Nuevu testu ficheru.txt", "Folder" : "Carpeta", "New folder" : "Nueva carpeta", + "{newname} already exists" : "{newname} yá existe", + "Upload" : "Xubir", + "An error occurred while trying to update the tags" : "Hebo un fallu mientres s'intentaba actualizar les etiquetes", "A new file or folder has been <strong>created</strong>" : "<strong>Creóse</strong> un ficheru o carpeta nuevos", "A file or folder has been <strong>changed</strong>" : "<strong>Camudóse</strong> un ficheru o carpeta", + "Limit notifications about creation and changes to your <strong>favorite files</strong> <em>(Stream only)</em>" : "Llendar les notificaciones tocantes a creación y cambeos a tos <strong>ficheros favoritos</strong <em>(namás Stream)</em>", "A file or folder has been <strong>deleted</strong>" : "<strong>Desanicióse</strong> un ficheru o carpeta", "A file or folder has been <strong>restored</strong>" : "<strong>Restauróse</strong> un ficheru o carpeta", "You created %1$s" : "Creasti %1$s", @@ -82,6 +94,9 @@ "%2$s deleted %1$s" : "%2$s desanició %1$s", "You restored %1$s" : "Recuperóse %1$s", "%2$s restored %1$s" : "%2$s recuperó %1$s", + "Changed by %2$s" : "Modificáu por %2$s", + "Deleted by %2$s" : "Desaniciáu por %2$s", + "Restored by %2$s" : "Recuperáu por %2$s", "%s could not be renamed as it has been deleted" : "%s nun pue renomase dempués de desaniciase", "%s could not be renamed" : "Nun se puede renomar %s ", "Upload (max. %s)" : "Xuba (máx. %s)", @@ -93,9 +108,15 @@ "WebDAV" : "WebDAV", "Use this address to <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Usa esta direición <a href=\"%s\" target=\"_blank\">p'acceder a los ficheros a traviés de WebDAV</a>", "Cancel upload" : "Encaboxar xuba", + "No files in here" : "Nun hai nengún ficheru equí", + "Upload some content or sync with your devices!" : "¡Xuba algún conteníu o sincroniza colos sos preseos!", + "No entries found in this folder" : "Nenguna entrada en esta carpeta", + "Select all" : "Esbillar too", "Upload too large" : "La xuba ye abondo grande", "The files you are trying to upload exceed the maximum size for file uploads on this server." : "Los ficheros que tas intentando xubir perpasen el tamañu máximu pa les xubíes de ficheros nesti servidor.", "Files are being scanned, please wait." : "Tan escaniándose los ficheros, espera por favor.", - "Currently scanning" : "Anguaño escaneando" + "Currently scanning" : "Anguaño escaneando", + "No favorites" : "Nengún favoritu", + "Files and folders you mark as favorite will show up here" : "Los ficheros y carpetes que marque como favoritos apaecerán equí" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file 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 <strong>created</strong>" : "Yeni fayl və ya direktoriya <strong>yaradılmışdır</strong>", "A file or folder has been <strong>changed</strong>" : "Fayl və ya direktoriya <strong>dəyişdirilib</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Bu ünvanı <a href=\"%s\" target=\"_blank\">WebDAV vasitəsilə fayllarınızı əldə etmək üçün</a> 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 <strong>created</strong>" : "Yeni fayl və ya direktoriya <strong>yaradılmışdır</strong>", "A file or folder has been <strong>changed</strong>" : "Fayl və ya direktoriya <strong>dəyişdirilib</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Bu ünvanı <a href=\"%s\" target=\"_blank\">WebDAV vasitəsilə fayllarınızı əldə etmək üçün</a> 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 <strong>created</strong>" : "Нов файл или папка беше <strong>създаден/а</strong>", "A file or folder has been <strong>changed</strong>" : "Файл или папка беше <strong>променен/а</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Използвай този адрес, за да получиш <a href=\"%s\" target=\"_blank\">достъп до своите файлове чрез WebDAV</a>.", 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 <strong>created</strong>" : "Нов файл или папка беше <strong>създаден/а</strong>", "A file or folder has been <strong>changed</strong>" : "Файл или папка беше <strong>променен/а</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Използвай този адрес, за да получиш <a href=\"%s\" target=\"_blank\">достъп до своите файлове чрез WebDAV</a>.", 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 <strong>created</strong>" : "একটি ফাইল বা ফোলডার <strong>তৈরি</strong> করা হয়েছে", "A file or folder has been <strong>changed</strong>" : "একটি ফাইল বা ফোলডার <strong>পরিবরতন</strong> করা হয়েছে", "A file or folder has been <strong>deleted</strong>" : "একটি ফাইল বা ফোলডার <strong>মোছা</strong> হয়েছে", 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 <strong>created</strong>" : "একটি ফাইল বা ফোলডার <strong>তৈরি</strong> করা হয়েছে", "A file or folder has been <strong>changed</strong>" : "একটি ফাইল বা ফোলডার <strong>পরিবরতন</strong> করা হয়েছে", "A file or folder has been <strong>deleted</strong>" : "একটি ফাইল বা ফোলডার <strong>মোছা</strong> হয়েছে", 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 <strong>created</strong>" : "S'ha <strong>creat</strong> un nou fitxer o una nova carpeta", "A file or folder has been <strong>changed</strong>" : "S'ha <strong>canviat</strong> 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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Useu aquesta adreça per <a href=\"%s\" target=\"_blank\">accedir als fitxers via WebDAV</a>", 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 <strong>created</strong>" : "S'ha <strong>creat</strong> un nou fitxer o una nova carpeta", "A file or folder has been <strong>changed</strong>" : "S'ha <strong>canviat</strong> 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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Useu aquesta adreça per <a href=\"%s\" target=\"_blank\">accedir als fitxers via WebDAV</a>", diff --git a/apps/files/l10n/cs_CZ.js b/apps/files/l10n/cs_CZ.js index 10f9d49984f..3c6bdc05a1b 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 <strong>created</strong>" : "Byl <strong>vytvořen</strong> nový soubor nebo složka", "A file or folder has been <strong>changed</strong>" : "Soubor nebo složka byla <strong>změněna</strong>", @@ -105,9 +105,9 @@ 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í.", + "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Použijte tuto adresu pro <a href=\"%s\" target=\"_blank\">přístup k vašim souborům přes WebDAV</a>", diff --git a/apps/files/l10n/cs_CZ.json b/apps/files/l10n/cs_CZ.json index cc475fbfd5c..bf9170f2ee3 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 <strong>created</strong>" : "Byl <strong>vytvořen</strong> nový soubor nebo složka", "A file or folder has been <strong>changed</strong>" : "Soubor nebo složka byla <strong>změněna</strong>", @@ -103,9 +103,9 @@ "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í.", + "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Použijte tuto adresu pro <a href=\"%s\" target=\"_blank\">přístup k vašim souborům přes WebDAV</a>", 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 84d342e85d9..307a58e74f0 100644 --- a/apps/files/l10n/da.js +++ b/apps/files/l10n/da.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Foretrukne", "Home" : "Hjemme", "Close" : "Luk", + "Upload cancelled." : "Upload afbrudt.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Kan ikke upload {filename} da det er enten en mappe eller indholder 0 bytes.", "Total file size {size1} exceeds upload limit {size2}" : "Den totale filstørrelse {size1} er større end uploadgrænsen {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Der er ikke tilstrækkeligt friplads. Du uplaoder {size1} men der er kun {size2} tilbage", - "Upload cancelled." : "Upload afbrudt.", "Could not get result from server." : "Kunne ikke hente resultat fra server.", "File upload is in progress. Leaving the page now will cancel the upload." : "Fil upload kører. Hvis du forlader siden nu, vil uploadet blive annuleret.", "Actions" : "Handlinger", @@ -75,12 +75,12 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"], "Favorited" : "Gjort til foretrukken", "Favorite" : "Foretrukken", - "{newname} already exists" : "{newname} eksistere allerede", - "Upload" : "Upload", "Text file" : "Tekstfil", "New text file.txt" : "Ny tekst file.txt", "Folder" : "Mappe", "New folder" : "Ny Mappe", + "{newname} already exists" : "{newname} eksistere allerede", + "Upload" : "Upload", "An error occurred while trying to update the tags" : "Der opstod en fejl under forsøg på at opdatere mærkerne", "A new file or folder has been <strong>created</strong>" : "En ny fil eller mapper er blevet <strong>oprettet</strong>", "A file or folder has been <strong>changed</strong>" : "En fil eller mappe er blevet <strong>ændret</strong>", @@ -96,15 +96,16 @@ OC.L10N.register( "%2$s deleted %1$s" : "%2$s slettede %1$s", "You restored %1$s" : "Du gendannede %1$s", "%2$s restored %1$s" : "%2$s gendannede %1$s", + "Changed by %2$s" : "Ændret af %2$s", + "Deleted by %2$s" : "Slettet af %2$s", + "Restored by %2$s" : "Gendannet af %2$s", "%s could not be renamed as it has been deleted" : "%s kunne ikke omdøbes, da den er blevet slettet", "%s could not be renamed" : "%s kunne ikke omdøbes", "Upload (max. %s)" : "Upload (max. %s)", "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Brug denne adresse for at <a href=\"%s\" target=\"_blank\">tilgå dine filer via WebDAV</a>", diff --git a/apps/files/l10n/da.json b/apps/files/l10n/da.json index 53de8656af2..ae5d9655536 100644 --- a/apps/files/l10n/da.json +++ b/apps/files/l10n/da.json @@ -28,10 +28,10 @@ "Favorites" : "Foretrukne", "Home" : "Hjemme", "Close" : "Luk", + "Upload cancelled." : "Upload afbrudt.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Kan ikke upload {filename} da det er enten en mappe eller indholder 0 bytes.", "Total file size {size1} exceeds upload limit {size2}" : "Den totale filstørrelse {size1} er større end uploadgrænsen {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Der er ikke tilstrækkeligt friplads. Du uplaoder {size1} men der er kun {size2} tilbage", - "Upload cancelled." : "Upload afbrudt.", "Could not get result from server." : "Kunne ikke hente resultat fra server.", "File upload is in progress. Leaving the page now will cancel the upload." : "Fil upload kører. Hvis du forlader siden nu, vil uploadet blive annuleret.", "Actions" : "Handlinger", @@ -73,12 +73,12 @@ "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"], "Favorited" : "Gjort til foretrukken", "Favorite" : "Foretrukken", - "{newname} already exists" : "{newname} eksistere allerede", - "Upload" : "Upload", "Text file" : "Tekstfil", "New text file.txt" : "Ny tekst file.txt", "Folder" : "Mappe", "New folder" : "Ny Mappe", + "{newname} already exists" : "{newname} eksistere allerede", + "Upload" : "Upload", "An error occurred while trying to update the tags" : "Der opstod en fejl under forsøg på at opdatere mærkerne", "A new file or folder has been <strong>created</strong>" : "En ny fil eller mapper er blevet <strong>oprettet</strong>", "A file or folder has been <strong>changed</strong>" : "En fil eller mappe er blevet <strong>ændret</strong>", @@ -94,15 +94,16 @@ "%2$s deleted %1$s" : "%2$s slettede %1$s", "You restored %1$s" : "Du gendannede %1$s", "%2$s restored %1$s" : "%2$s gendannede %1$s", + "Changed by %2$s" : "Ændret af %2$s", + "Deleted by %2$s" : "Slettet af %2$s", + "Restored by %2$s" : "Gendannet af %2$s", "%s could not be renamed as it has been deleted" : "%s kunne ikke omdøbes, da den er blevet slettet", "%s could not be renamed" : "%s kunne ikke omdøbes", "Upload (max. %s)" : "Upload (max. %s)", "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Brug denne adresse for at <a href=\"%s\" target=\"_blank\">tilgå dine filer via WebDAV</a>", 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 <strong>created</strong>" : "Eine neue Datei oder ein neuer Ordner wurde <strong>erstellt</strong>", "A file or folder has been <strong>changed</strong>" : "Eine Datei oder ein Ordner wurde <strong>geändert</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Benutze diese Adresse, um <a href=\"%s\" target=\"_blank\">über WebDAV auf Deine Dateien zuzugreifen</a>", 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 <strong>created</strong>" : "Eine neue Datei oder ein neuer Ordner wurde <strong>erstellt</strong>", "A file or folder has been <strong>changed</strong>" : "Eine Datei oder ein Ordner wurde <strong>geändert</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Benutze diese Adresse, um <a href=\"%s\" target=\"_blank\">über WebDAV auf Deine Dateien zuzugreifen</a>", 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 <strong>created</strong>" : "Eine neue Datei oder ein neuer Ordner wurde <strong>erstellt</strong>", "A file or folder has been <strong>changed</strong>" : "Eine Datei oder ein Ordner hat sich <strong>geändert</strong>", "A file or folder has been <strong>deleted</strong>" : "Eine Datei oder ein Ordner wurde <strong>gelöscht</strong>", 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 <strong>created</strong>" : "Eine neue Datei oder ein neuer Ordner wurde <strong>erstellt</strong>", "A file or folder has been <strong>changed</strong>" : "Eine Datei oder ein Ordner hat sich <strong>geändert</strong>", "A file or folder has been <strong>deleted</strong>" : "Eine Datei oder ein Ordner wurde <strong>gelöscht</strong>", 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 <strong>created</strong>" : "Eine neue Datei oder ein neuer Ordner wurde <strong>erstellt</strong>", "A file or folder has been <strong>changed</strong>" : "Eine Datei oder ein Ordner wurde <strong>geändert</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Benutzen Sie diese Adresse, um <a href=\"%s\" target=\"_blank\">über WebDAV auf Ihre Dateien zuzugreifen</a>", 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 <strong>created</strong>" : "Eine neue Datei oder ein neuer Ordner wurde <strong>erstellt</strong>", "A file or folder has been <strong>changed</strong>" : "Eine Datei oder ein Ordner wurde <strong>geändert</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Benutzen Sie diese Adresse, um <a href=\"%s\" target=\"_blank\">über WebDAV auf Ihre Dateien zuzugreifen</a>", diff --git a/apps/files/l10n/el.js b/apps/files/l10n/el.js index 063c9f0fe44..6c8e2cbff33 100644 --- a/apps/files/l10n/el.js +++ b/apps/files/l10n/el.js @@ -10,7 +10,7 @@ OC.L10N.register( "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" : "Σφάλμα δημιουργίας φακέλου", + "Error when creating the folder" : "Σφάλμα κατά τη δημιουργία του φακέλου", "Unable to set upload directory." : "Αδυναμία ορισμού καταλόγου αποστολής.", "Invalid Token" : "Μη έγκυρο Token", "No file was uploaded. Unknown error" : "Δεν ανέβηκε κάποιο αρχείο. Άγνωστο σφάλμα", @@ -21,19 +21,19 @@ OC.L10N.register( "No file was uploaded" : "Κανένα αρχείο δεν στάλθηκε", "Missing a temporary folder" : "Λείπει ο προσωρινός φάκελος", "Failed to write to disk" : "Αποτυχία εγγραφής στο δίσκο", - "Not enough storage available" : "Μη επαρκής διαθέσιμος αποθηκευτικός χώρος", + "Not enough storage available" : "Ο διαθέσιμος αποθηκευτικός χώρος δεν επαρκεί", "Upload failed. Could not find uploaded file" : "Η φόρτωση απέτυχε. Αδυναμία εύρεσης αρχείου προς φόρτωση.", "Upload failed. Could not get file info." : "Η φόρτωση απέτυχε. Αδυναμία λήψης πληροφοριών αρχείων.", "Invalid directory." : "Μη έγκυρος φάκελος.", "Files" : "Αρχεία", "All files" : "Όλα τα αρχεία", - "Favorites" : "Αγαπημένες", + "Favorites" : "Αγαπημένα", "Home" : "Σπίτι", "Close" : "Κλείσιμο", + "Upload cancelled." : "Η αποστολή ακυρώθηκε.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Αδυναμία φόρτωσης {filename} καθώς είναι κατάλογος αρχείων ή έχει 0 bytes", "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" : "Ενέργειες", @@ -44,70 +44,70 @@ OC.L10N.register( "Select" : "Επιλογή", "Pending" : "Εκκρεμεί", "Unable to determine date" : "Αδυναμία προσδιορισμού ημερομηνίας ", - "This operation is forbidden" : "Αυτή η ενέργεια απαγορεύεται", + "This operation is forbidden" : "Αυτή η ενέργεια δεν επιτρέπεται", "This directory is unavailable, please check the logs or contact the administrator" : "Ο κατάλογος δεν είναι διαθέσιμος, παρακαλώ ελέγξτε τα αρχεία καταγραφής ή επικοινωνήστε με το διαχειριστή", "Error moving file." : "Σφάλμα κατά τη μετακίνηση του αρχείου.", "Error moving file" : "Σφάλμα κατά τη μετακίνηση του αρχείου", "Error" : "Σφάλμα", - "{new_name} already exists" : "{new_name} υπάρχει ήδη", + "{new_name} already exists" : "το {new_name} υπάρχει ήδη", "Could not rename file" : "Αδυναμία μετονομασίας αρχείου", "Could not create file" : "Αδυναμία δημιουργίας αρχείου", "Could not create folder" : "Αδυναμία δημιουργίας φακέλου", - "Error deleting file." : "Σφάλμα διαγραφής αρχείου.", + "Error deleting file." : "Σφάλμα κατά τη διαγραφή του αρχείου.", "No entries in this folder match '{filter}'" : "Δεν ταιριάζουν καταχωρήσεις σε αυτόν το φάκελο '{filter}'", "Name" : "Όνομα", "Size" : "Μέγεθος", "Modified" : "Τροποποιήθηκε", "_%n folder_::_%n folders_" : ["%n φάκελος","%n φάκελοι"], "_%n file_::_%n files_" : ["%n αρχείο","%n αρχεία"], - "{dirs} and {files}" : "{Κατάλογοι αρχείων} και {αρχεία}", + "{dirs} and {files}" : "{dirs} και {files}", "You don’t have permission to upload or create files here" : "Δεν έχετε δικαιώματα φόρτωσης ή δημιουργίας αρχείων εδώ", "_Uploading %n file_::_Uploading %n files_" : ["Ανέβασμα %n αρχείου","Ανέβασμα %n αρχείων"], "New" : "Νέο", - "\"{name}\" is an invalid file name." : "Το \"{name}\" είναι μη έγκυρο όνομα αρχείου.", + "\"{name}\" is an invalid file name." : "Το \"{name}\" δεν είναι έγκυρο όνομα αρχείου.", "File name cannot be empty." : "Το όνομα αρχείου δεν μπορεί να είναι κενό.", - "Storage of {owner} is full, files can not be updated or synced anymore!" : "Ο αποθηκευτικός χώρος του {owner} είναι πλήρης, τα αρχεία δεν δύναται να ενημερωθούν ή να συγχρονίσουν!", - "Your storage is full, files can not be updated or synced anymore!" : "Ο αποθηκευτικός σας χώρος είναι γεμάτος, τα αρχεία δεν μπορούν να ενημερωθούν ή να συγχρονιστούν πια!", - "Storage of {owner} is almost full ({usedSpacePercent}%)" : "Ο αποθηκευτικός χώρος του {owner} είναι σχεδόν πλήρης ({usedSpacePercent}%)", + "Storage of {owner} is full, files can not be updated or synced anymore!" : "Ο αποθηκευτικός χώρος του {owner} είναι γεμάτος, τα αρχεία δεν μπορούν να ενημερωθούν ή να συγχρονιστούν!", + "Your storage is full, files can not be updated or synced anymore!" : "Ο αποθηκευτικός σας χώρος είναι γεμάτος, τα αρχεία δεν μπορούν να ενημερωθούν ή να συγχρονιστούν!", + "Storage of {owner} is almost full ({usedSpacePercent}%)" : "Ο αποθηκευτικός χώρος του {owner} είναι σχεδόν γεμάτος ({usedSpacePercent}%)", "Your storage is almost full ({usedSpacePercent}%)" : "Ο αποθηκευτικός χώρος είναι σχεδόν γεμάτος ({usedSpacePercent}%)", "_matches '{filter}'_::_match '{filter}'_" : ["ταιριάζουν '{filter}' ","ταιριάζουν '{filter}'"], "Path" : "Διαδρομή", "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"], "Favorited" : "Προτιμώμενα", "Favorite" : "Αγαπημένο", - "{newname} already exists" : "το {newname} υπάρχει ήδη", - "Upload" : "Μεταφόρτωση", "Text file" : "Αρχείο κειμένου", "New text file.txt" : "Νέο αρχείο κειμένου.txt", "Folder" : "Φάκελος", - "New folder" : "Νέος κατάλογος", + "New folder" : "Νέος φάκελος", + "{newname} already exists" : "το {newname} υπάρχει ήδη", + "Upload" : "Μεταφόρτωση", "An error occurred while trying to update the tags" : "Ένα σφάλμα προέκυψε κατά τη διάρκεια ενημέρωσης των ετικετών", "A new file or folder has been <strong>created</strong>" : "Ένα νέο αρχείο ή κατάλογος έχουν <strong>δημιουργηθεί</strong>", "A file or folder has been <strong>changed</strong>" : "Ένα αρχείο ή κατάλογος έχουν <strong>αλλάξει</strong>", "Limit notifications about creation and changes to your <strong>favorite files</strong> <em>(Stream only)</em>" : "Βάλτε όριο στις ειδοποιήσεις για τη δημιουργία και αλλαγές στα <strong>αγαπημένα σας αρχεία</strong> <em>(Μόνο Stream)</em>", "A file or folder has been <strong>deleted</strong>" : "Ένα αρχείο ή κατάλογος έχουν <strong>διαγραφεί</strong>", "A file or folder has been <strong>restored</strong>" : "Ένα αρχείο ή φάκελος <strong>επαναφέρθηκε</ strong>", - "You created %1$s" : "Δημιουργήσατε %1$s", - "%2$s created %1$s" : "Ο %2$s δημιούργησε %1$s", + "You created %1$s" : "Δημιουργήσατε το %1$s", + "%2$s created %1$s" : "Ο χρήστης %2$s δημιούργησε το %1$s", "%1$s was created in a public folder" : "Το %1$s δημιουργήθηκε σε έναν δημόσιο φάκελο", - "You changed %1$s" : "Αλλάξατε %1$s", - "%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", - "Changed by %2$s" : "Άλλαξε από %2$s", - "Deleted by %2$s" : "Διαγράφηκε από %2$s", - "Restored by %2$s" : "Επαναφορά απο %2$s", - "%s could not be renamed as it has been deleted" : "%s δεν μπορούσε να μετονομαστεί εφόσον είχε διαγραφεί", + "You changed %1$s" : "Αλλάξατε το %1$s", + "%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", + "Changed by %2$s" : "Άλλαξε από το χρήστη %2$s", + "Deleted 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)" : "Διαμοιρασμός (max. %s)", "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." : "Δεν υπάρχει εδώ η δυνατότητα επεξεργασίας λόγω μη επαρκών δικαιωμάτων", + "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Χρησιμοποιήστε αυτήν την διεύθυνση για να αποκτήσετε <a href=\"%s\" target=\"_blank\">πρόσβαση στα αρχεία σας μέσω WebDAV</a>", diff --git a/apps/files/l10n/el.json b/apps/files/l10n/el.json index b374964c8b6..ee9e4ebde54 100644 --- a/apps/files/l10n/el.json +++ b/apps/files/l10n/el.json @@ -8,7 +8,7 @@ "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" : "Σφάλμα δημιουργίας φακέλου", + "Error when creating the folder" : "Σφάλμα κατά τη δημιουργία του φακέλου", "Unable to set upload directory." : "Αδυναμία ορισμού καταλόγου αποστολής.", "Invalid Token" : "Μη έγκυρο Token", "No file was uploaded. Unknown error" : "Δεν ανέβηκε κάποιο αρχείο. Άγνωστο σφάλμα", @@ -19,19 +19,19 @@ "No file was uploaded" : "Κανένα αρχείο δεν στάλθηκε", "Missing a temporary folder" : "Λείπει ο προσωρινός φάκελος", "Failed to write to disk" : "Αποτυχία εγγραφής στο δίσκο", - "Not enough storage available" : "Μη επαρκής διαθέσιμος αποθηκευτικός χώρος", + "Not enough storage available" : "Ο διαθέσιμος αποθηκευτικός χώρος δεν επαρκεί", "Upload failed. Could not find uploaded file" : "Η φόρτωση απέτυχε. Αδυναμία εύρεσης αρχείου προς φόρτωση.", "Upload failed. Could not get file info." : "Η φόρτωση απέτυχε. Αδυναμία λήψης πληροφοριών αρχείων.", "Invalid directory." : "Μη έγκυρος φάκελος.", "Files" : "Αρχεία", "All files" : "Όλα τα αρχεία", - "Favorites" : "Αγαπημένες", + "Favorites" : "Αγαπημένα", "Home" : "Σπίτι", "Close" : "Κλείσιμο", + "Upload cancelled." : "Η αποστολή ακυρώθηκε.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Αδυναμία φόρτωσης {filename} καθώς είναι κατάλογος αρχείων ή έχει 0 bytes", "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" : "Ενέργειες", @@ -42,70 +42,70 @@ "Select" : "Επιλογή", "Pending" : "Εκκρεμεί", "Unable to determine date" : "Αδυναμία προσδιορισμού ημερομηνίας ", - "This operation is forbidden" : "Αυτή η ενέργεια απαγορεύεται", + "This operation is forbidden" : "Αυτή η ενέργεια δεν επιτρέπεται", "This directory is unavailable, please check the logs or contact the administrator" : "Ο κατάλογος δεν είναι διαθέσιμος, παρακαλώ ελέγξτε τα αρχεία καταγραφής ή επικοινωνήστε με το διαχειριστή", "Error moving file." : "Σφάλμα κατά τη μετακίνηση του αρχείου.", "Error moving file" : "Σφάλμα κατά τη μετακίνηση του αρχείου", "Error" : "Σφάλμα", - "{new_name} already exists" : "{new_name} υπάρχει ήδη", + "{new_name} already exists" : "το {new_name} υπάρχει ήδη", "Could not rename file" : "Αδυναμία μετονομασίας αρχείου", "Could not create file" : "Αδυναμία δημιουργίας αρχείου", "Could not create folder" : "Αδυναμία δημιουργίας φακέλου", - "Error deleting file." : "Σφάλμα διαγραφής αρχείου.", + "Error deleting file." : "Σφάλμα κατά τη διαγραφή του αρχείου.", "No entries in this folder match '{filter}'" : "Δεν ταιριάζουν καταχωρήσεις σε αυτόν το φάκελο '{filter}'", "Name" : "Όνομα", "Size" : "Μέγεθος", "Modified" : "Τροποποιήθηκε", "_%n folder_::_%n folders_" : ["%n φάκελος","%n φάκελοι"], "_%n file_::_%n files_" : ["%n αρχείο","%n αρχεία"], - "{dirs} and {files}" : "{Κατάλογοι αρχείων} και {αρχεία}", + "{dirs} and {files}" : "{dirs} και {files}", "You don’t have permission to upload or create files here" : "Δεν έχετε δικαιώματα φόρτωσης ή δημιουργίας αρχείων εδώ", "_Uploading %n file_::_Uploading %n files_" : ["Ανέβασμα %n αρχείου","Ανέβασμα %n αρχείων"], "New" : "Νέο", - "\"{name}\" is an invalid file name." : "Το \"{name}\" είναι μη έγκυρο όνομα αρχείου.", + "\"{name}\" is an invalid file name." : "Το \"{name}\" δεν είναι έγκυρο όνομα αρχείου.", "File name cannot be empty." : "Το όνομα αρχείου δεν μπορεί να είναι κενό.", - "Storage of {owner} is full, files can not be updated or synced anymore!" : "Ο αποθηκευτικός χώρος του {owner} είναι πλήρης, τα αρχεία δεν δύναται να ενημερωθούν ή να συγχρονίσουν!", - "Your storage is full, files can not be updated or synced anymore!" : "Ο αποθηκευτικός σας χώρος είναι γεμάτος, τα αρχεία δεν μπορούν να ενημερωθούν ή να συγχρονιστούν πια!", - "Storage of {owner} is almost full ({usedSpacePercent}%)" : "Ο αποθηκευτικός χώρος του {owner} είναι σχεδόν πλήρης ({usedSpacePercent}%)", + "Storage of {owner} is full, files can not be updated or synced anymore!" : "Ο αποθηκευτικός χώρος του {owner} είναι γεμάτος, τα αρχεία δεν μπορούν να ενημερωθούν ή να συγχρονιστούν!", + "Your storage is full, files can not be updated or synced anymore!" : "Ο αποθηκευτικός σας χώρος είναι γεμάτος, τα αρχεία δεν μπορούν να ενημερωθούν ή να συγχρονιστούν!", + "Storage of {owner} is almost full ({usedSpacePercent}%)" : "Ο αποθηκευτικός χώρος του {owner} είναι σχεδόν γεμάτος ({usedSpacePercent}%)", "Your storage is almost full ({usedSpacePercent}%)" : "Ο αποθηκευτικός χώρος είναι σχεδόν γεμάτος ({usedSpacePercent}%)", "_matches '{filter}'_::_match '{filter}'_" : ["ταιριάζουν '{filter}' ","ταιριάζουν '{filter}'"], "Path" : "Διαδρομή", "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"], "Favorited" : "Προτιμώμενα", "Favorite" : "Αγαπημένο", - "{newname} already exists" : "το {newname} υπάρχει ήδη", - "Upload" : "Μεταφόρτωση", "Text file" : "Αρχείο κειμένου", "New text file.txt" : "Νέο αρχείο κειμένου.txt", "Folder" : "Φάκελος", - "New folder" : "Νέος κατάλογος", + "New folder" : "Νέος φάκελος", + "{newname} already exists" : "το {newname} υπάρχει ήδη", + "Upload" : "Μεταφόρτωση", "An error occurred while trying to update the tags" : "Ένα σφάλμα προέκυψε κατά τη διάρκεια ενημέρωσης των ετικετών", "A new file or folder has been <strong>created</strong>" : "Ένα νέο αρχείο ή κατάλογος έχουν <strong>δημιουργηθεί</strong>", "A file or folder has been <strong>changed</strong>" : "Ένα αρχείο ή κατάλογος έχουν <strong>αλλάξει</strong>", "Limit notifications about creation and changes to your <strong>favorite files</strong> <em>(Stream only)</em>" : "Βάλτε όριο στις ειδοποιήσεις για τη δημιουργία και αλλαγές στα <strong>αγαπημένα σας αρχεία</strong> <em>(Μόνο Stream)</em>", "A file or folder has been <strong>deleted</strong>" : "Ένα αρχείο ή κατάλογος έχουν <strong>διαγραφεί</strong>", "A file or folder has been <strong>restored</strong>" : "Ένα αρχείο ή φάκελος <strong>επαναφέρθηκε</ strong>", - "You created %1$s" : "Δημιουργήσατε %1$s", - "%2$s created %1$s" : "Ο %2$s δημιούργησε %1$s", + "You created %1$s" : "Δημιουργήσατε το %1$s", + "%2$s created %1$s" : "Ο χρήστης %2$s δημιούργησε το %1$s", "%1$s was created in a public folder" : "Το %1$s δημιουργήθηκε σε έναν δημόσιο φάκελο", - "You changed %1$s" : "Αλλάξατε %1$s", - "%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", - "Changed by %2$s" : "Άλλαξε από %2$s", - "Deleted by %2$s" : "Διαγράφηκε από %2$s", - "Restored by %2$s" : "Επαναφορά απο %2$s", - "%s could not be renamed as it has been deleted" : "%s δεν μπορούσε να μετονομαστεί εφόσον είχε διαγραφεί", + "You changed %1$s" : "Αλλάξατε το %1$s", + "%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", + "Changed by %2$s" : "Άλλαξε από το χρήστη %2$s", + "Deleted 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)" : "Διαμοιρασμός (max. %s)", "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." : "Δεν υπάρχει εδώ η δυνατότητα επεξεργασίας λόγω μη επαρκών δικαιωμάτων", + "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Χρησιμοποιήστε αυτήν την διεύθυνση για να αποκτήσετε <a href=\"%s\" target=\"_blank\">πρόσβαση στα αρχεία σας μέσω WebDAV</a>", 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 <strong>created</strong>" : "A new file or folder has been <strong>created</strong>", "A file or folder has been <strong>changed</strong>" : "A file or folder has been <strong>changed</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Use this address to <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>", 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 <strong>created</strong>" : "A new file or folder has been <strong>created</strong>", "A file or folder has been <strong>changed</strong>" : "A file or folder has been <strong>changed</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Use this address to <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>", 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 <strong>created</strong>" : "Se ha <strong>creado</strong> un nuevo archivo o carpeta", "A file or folder has been <strong>changed</strong>" : "Se ha <strong>modificado</strong> 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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Use esta URL <a href=\"%s\" target=\"_blank\">para acceder via WebDAV</a>", 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 <strong>created</strong>" : "Se ha <strong>creado</strong> un nuevo archivo o carpeta", "A file or folder has been <strong>changed</strong>" : "Se ha <strong>modificado</strong> 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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Use esta URL <a href=\"%s\" target=\"_blank\">para acceder via WebDAV</a>", 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 <strong>created</strong>" : "Un archivo o carpeta ha sido <strong>creado</strong>", "A file or folder has been <strong>changed</strong>" : "Un archivo o carpeta ha sido <strong>modificado</strong>", "A file or folder has been <strong>deleted</strong>" : "Un archivo o carpeta ha sido <strong>eliminado</strong>", 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 <strong>created</strong>" : "Un archivo o carpeta ha sido <strong>creado</strong>", "A file or folder has been <strong>changed</strong>" : "Un archivo o carpeta ha sido <strong>modificado</strong>", "A file or folder has been <strong>deleted</strong>" : "Un archivo o carpeta ha sido <strong>eliminado</strong>", 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 <strong>created</strong>" : "Un nuevo archivo o carpeta ha sido <strong>creado</strong>", "A file or folder has been <strong>changed</strong>" : "Un archivo o carpeta ha sido <strong>cambiado</strong>", "A file or folder has been <strong>deleted</strong>" : "Un archivo o carpeta ha sido <strong>eliminado</strong>", 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 <strong>created</strong>" : "Un nuevo archivo o carpeta ha sido <strong>creado</strong>", "A file or folder has been <strong>changed</strong>" : "Un archivo o carpeta ha sido <strong>cambiado</strong>", "A file or folder has been <strong>deleted</strong>" : "Un archivo o carpeta ha sido <strong>eliminado</strong>", 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 <strong>created</strong>" : "Uus fail või kataloog on <strong>loodud</strong>", "A file or folder has been <strong>changed</strong>" : "Fail või kataloog on <strong>muudetud</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Kasuta seda aadressi <a href=\"%s\" target=\"_blank\">oma failidele ligipääsuks WebDAV kaudu</a>", 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 <strong>created</strong>" : "Uus fail või kataloog on <strong>loodud</strong>", "A file or folder has been <strong>changed</strong>" : "Fail või kataloog on <strong>muudetud</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Kasuta seda aadressi <a href=\"%s\" target=\"_blank\">oma failidele ligipääsuks WebDAV kaudu</a>", 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 <strong>created</strong>" : "Fitxategi edo karpeta berri bat <strong>sortu da</strong>", "A file or folder has been <strong>changed</strong>" : "Fitxategi edo karpeta bat <strong>aldatu da</strong>", "A file or folder has been <strong>deleted</strong>" : "Fitxategi edo karpeta bat <strong>ezabatu da</strong>", 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 <strong>created</strong>" : "Fitxategi edo karpeta berri bat <strong>sortu da</strong>", "A file or folder has been <strong>changed</strong>" : "Fitxategi edo karpeta bat <strong>aldatu da</strong>", "A file or folder has been <strong>deleted</strong>" : "Fitxategi edo karpeta bat <strong>ezabatu da</strong>", 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 <strong>created</strong>" : "فایل یا پوشه ای <strong>ایجاد</strong> شد", "A file or folder has been <strong>changed</strong>" : "فایل یا پوشه ای به <strong>تغییر</strong> یافت", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "از این آدرس استفاده کنید تا <a href=\"%s\" target=\"_blank\">بتوانید به فایلهای خود توسط WebDAV دسترسی پیدا کنید</a>", 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 <strong>created</strong>" : "فایل یا پوشه ای <strong>ایجاد</strong> شد", "A file or folder has been <strong>changed</strong>" : "فایل یا پوشه ای به <strong>تغییر</strong> یافت", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "از این آدرس استفاده کنید تا <a href=\"%s\" target=\"_blank\">بتوانید به فایلهای خود توسط WebDAV دسترسی پیدا کنید</a>", diff --git a/apps/files/l10n/fi_FI.js b/apps/files/l10n/fi_FI.js index cf4bb0f5792..79f3321577f 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 <strong>created</strong>" : "Uusi tiedosto tai kansio on <strong>luotu</strong>", "A file or folder has been <strong>changed</strong>" : "Tiedostoa tai kansiota on <strong>muutettu</strong>", @@ -105,9 +105,8 @@ 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.", + "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Käytä tätä osoitetta <a href=\"%s\" target=\"_blank\">käyttääksesi tiedostojasi WebDAVin kautta</a>", diff --git a/apps/files/l10n/fi_FI.json b/apps/files/l10n/fi_FI.json index 56417b3c74d..e46327c83fa 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 <strong>created</strong>" : "Uusi tiedosto tai kansio on <strong>luotu</strong>", "A file or folder has been <strong>changed</strong>" : "Tiedostoa tai kansiota on <strong>muutettu</strong>", @@ -103,9 +103,8 @@ "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.", + "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Käytä tätä osoitetta <a href=\"%s\" target=\"_blank\">käyttääksesi tiedostojasi WebDAVin kautta</a>", diff --git a/apps/files/l10n/fr.js b/apps/files/l10n/fr.js index 0b290eb160a..e068b3c45ba 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 <strong>created</strong>" : "Un nouveau fichier ou répertoire a été <strong>créé</strong>", "A file or folder has been <strong>changed</strong>" : "Un fichier ou un répertoire a été <strong>modifié</strong>", @@ -105,9 +105,9 @@ 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.", + "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Utilisez cette adresse pour <a href=\"%s\" target=\"_blank\">accéder à vos fichiers par WebDAV</a>", diff --git a/apps/files/l10n/fr.json b/apps/files/l10n/fr.json index 5f51bdee302..a297b3525d1 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 <strong>created</strong>" : "Un nouveau fichier ou répertoire a été <strong>créé</strong>", "A file or folder has been <strong>changed</strong>" : "Un fichier ou un répertoire a été <strong>modifié</strong>", @@ -103,9 +103,9 @@ "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.", + "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Utilisez cette adresse pour <a href=\"%s\" target=\"_blank\">accéder à vos fichiers par WebDAV</a>", 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 <strong>created</strong>" : "<strong>Creouse</strong> un novo ficheiro ou cartafol", "A file or folder has been <strong>changed</strong>" : "<strong>Cambiouse</strong> 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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Empregue esta ligazón para <a href=\"%s\" target=\"_blank\">acceder aos seus ficheiros mediante WebDAV</a>", 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 <strong>created</strong>" : "<strong>Creouse</strong> un novo ficheiro ou cartafol", "A file or folder has been <strong>changed</strong>" : "<strong>Cambiouse</strong> 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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Empregue esta ligazón para <a href=\"%s\" target=\"_blank\">acceder aos seus ficheiros mediante WebDAV</a>", 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 <strong>created</strong>" : "קובץ או תיקייה חדשים <strong>נוצרו<strong/>", "A file or folder has been <strong>changed</strong>" : "קובץ או תיקייה <strong>שונו<strong/>", "A file or folder has been <strong>deleted</strong>" : "קובץ או תיקייה <strong>נמחקו<strong/>", 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 <strong>created</strong>" : "קובץ או תיקייה חדשים <strong>נוצרו<strong/>", "A file or folder has been <strong>changed</strong>" : "קובץ או תיקייה <strong>שונו<strong/>", "A file or folder has been <strong>deleted</strong>" : "קובץ או תיקייה <strong>נמחקו<strong/>", 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 <strong>created</strong>" : "Nova datoteka ili nova mapa su <strong>kreirani</strong>", "A file or folder has been <strong>changed</strong>" : "Datoteka ili mapa su <strong>promijenjeni</strong>", "A file or folder has been <strong>deleted</strong>" : "Datoteka ili mapa su <strong>izbrisani</strong>", 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 <strong>created</strong>" : "Nova datoteka ili nova mapa su <strong>kreirani</strong>", "A file or folder has been <strong>changed</strong>" : "Datoteka ili mapa su <strong>promijenjeni</strong>", "A file or folder has been <strong>deleted</strong>" : "Datoteka ili mapa su <strong>izbrisani</strong>", diff --git a/apps/files/l10n/hu_HU.js b/apps/files/l10n/hu_HU.js index 5eff7a8f842..3c12e4bd486 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 <strong>created</strong>" : "Új fájl vagy könyvtár <strong>létrehozása</strong>", "A file or folder has been <strong>changed</strong>" : "Fájl vagy könyvtár <strong>módosítása</strong>", @@ -105,9 +105,9 @@ 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 ", + "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Ezt a címet használja, ha <a href=\"%s\" target=\"_blank\">WebDAV-on keresztül szeretné elérni a fájljait</a>", diff --git a/apps/files/l10n/hu_HU.json b/apps/files/l10n/hu_HU.json index da5eed09733..b1bde8b7d51 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 <strong>created</strong>" : "Új fájl vagy könyvtár <strong>létrehozása</strong>", "A file or folder has been <strong>changed</strong>" : "Fájl vagy könyvtár <strong>módosítása</strong>", @@ -103,9 +103,9 @@ "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 ", + "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Ezt a címet használja, ha <a href=\"%s\" target=\"_blank\">WebDAV-on keresztül szeretné elérni a fájljait</a>", 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 <strong>created</strong>" : "Un nove file o dossier ha essite <strong>create</strong>", "A file or folder has been <strong>changed</strong>" : "Un nove file o dossier ha essite <strong>modificate</strong>", "A file or folder has been <strong>deleted</strong>" : "Un nove file o dossier ha essite <strong>delite</strong>", 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 <strong>created</strong>" : "Un nove file o dossier ha essite <strong>create</strong>", "A file or folder has been <strong>changed</strong>" : "Un nove file o dossier ha essite <strong>modificate</strong>", "A file or folder has been <strong>deleted</strong>" : "Un nove file o dossier ha essite <strong>delite</strong>", 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 <strong>created</strong>" : "Sebuah berkas atau folder baru telah <strong>dibuat</strong>", "A file or folder has been <strong>changed</strong>" : "Sebuah berkas atau folder telah <strong>diubah</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Gunakan alamat ini untuk <a href=\"%s\" target=\"_blank\">mengakses Berkas via WebDAV</a>", 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 <strong>created</strong>" : "Sebuah berkas atau folder baru telah <strong>dibuat</strong>", "A file or folder has been <strong>changed</strong>" : "Sebuah berkas atau folder telah <strong>diubah</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Gunakan alamat ini untuk <a href=\"%s\" target=\"_blank\">mengakses Berkas via WebDAV</a>", 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..4c6033e6caf 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 <strong>created</strong>" : "Un nuovo file o cartella è stato <strong>creato</strong>", "A file or folder has been <strong>changed</strong>" : "Un file o una cartella è stato <strong>modificato</strong>", @@ -105,9 +105,9 @@ 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.", + "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Utilizza questo indirizzo per <a href=\"%s\" target=\"_blank\">accedere ai tuoi file con WebDAV</a>", diff --git a/apps/files/l10n/it.json b/apps/files/l10n/it.json index 6f6092c5c15..239b8dc399c 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 <strong>created</strong>" : "Un nuovo file o cartella è stato <strong>creato</strong>", "A file or folder has been <strong>changed</strong>" : "Un file o una cartella è stato <strong>modificato</strong>", @@ -103,9 +103,9 @@ "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.", + "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Utilizza questo indirizzo per <a href=\"%s\" target=\"_blank\">accedere ai tuoi file con WebDAV</a>", diff --git a/apps/files/l10n/ja.js b/apps/files/l10n/ja.js index 28e0b124a0a..be441c15ca1 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 <strong>created</strong>" : "新しいファイルまたはフォルダーを<strong>作成</strong>したとき", "A file or folder has been <strong>changed</strong>" : "ファイルまたはフォルダーを<strong>変更</strong>したとき", @@ -96,15 +96,18 @@ OC.L10N.register( "%2$s deleted %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 により復元", "%s could not be renamed as it has been deleted" : "%s は削除されたため、ファイル名を変更できません", "%s could not be renamed" : "%sの名前を変更できませんでした", "Upload (max. %s)" : "アップロード ( 最大 %s )", "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." : "権限不足のため直接編集することはできません。", + "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "<a href=\"%s\" target=\"_blank\">WebDAV経由でのファイルアクセス</a>にはこのアドレスを利用してください", diff --git a/apps/files/l10n/ja.json b/apps/files/l10n/ja.json index 46265c531b9..58b4870369c 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 <strong>created</strong>" : "新しいファイルまたはフォルダーを<strong>作成</strong>したとき", "A file or folder has been <strong>changed</strong>" : "ファイルまたはフォルダーを<strong>変更</strong>したとき", @@ -94,15 +94,18 @@ "%2$s deleted %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 により復元", "%s could not be renamed as it has been deleted" : "%s は削除されたため、ファイル名を変更できません", "%s could not be renamed" : "%sの名前を変更できませんでした", "Upload (max. %s)" : "アップロード ( 最大 %s )", "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." : "権限不足のため直接編集することはできません。", + "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "<a href=\"%s\" target=\"_blank\">WebDAV経由でのファイルアクセス</a>にはこのアドレスを利用してください", 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 <strong>created</strong>" : "새 파일이나 폴더가 <strong>생성됨</strong>", "A file or folder has been <strong>changed</strong>" : "파일이나 폴더가 <strong>변경됨</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "WebDAV로 파일에 접근하려면 <a href=\"%s\" target=\"_blank\">이 주소를 사용하십시오</a>", 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 <strong>created</strong>" : "새 파일이나 폴더가 <strong>생성됨</strong>", "A file or folder has been <strong>changed</strong>" : "파일이나 폴더가 <strong>변경됨</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "WebDAV로 파일에 접근하려면 <a href=\"%s\" target=\"_blank\">이 주소를 사용하십시오</a>", 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 063789aae5b..ac7084cfc2d 100644 --- a/apps/files/l10n/lt_LT.js +++ b/apps/files/l10n/lt_LT.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Mėgstamiausi", "Home" : "Namų", "Close" : "Užverti", + "Upload cancelled." : "Įkėlimas atšauktas.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Nepavyksta įkelti {filename}, nes tai katalogas arba yra 0 baitų dydžio", "Total file size {size1} exceeds upload limit {size2}" : "Visas failo dydis {size1} viršyja įkėlimo limitą {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Nepakanka laisvos vietos. Keliate {size1}, bet tik {size2} yra likę", - "Upload cancelled." : "Įkėlimas atšauktas.", "Could not get result from server." : "Nepavyko gauti rezultato iš serverio.", "File upload is in progress. Leaving the page now will cancel the upload." : "Failo įkėlimas pradėtas. Jei paliksite šį puslapį, įkėlimas nutrūks.", "Actions" : "Veiksmai", @@ -71,12 +71,16 @@ OC.L10N.register( "Storage of {owner} is almost full ({usedSpacePercent}%)" : "{owner} saugykla yra beveik pilna ({usedSpacePercent}%)", "Your storage is almost full ({usedSpacePercent}%)" : "Jūsų vieta serveryje beveik visa užimta ({usedSpacePercent}%)", "_matches '{filter}'_::_match '{filter}'_" : ["atitikmuo „{filter}“","atitikmenys „{filter}“","atitikmenų „{filter}“"], + "Path" : "Kelias", + "_%n byte_::_%n bytes_" : ["%n baitas","%n baitai","%n baitų"], "Favorited" : "Pažymėta mėgstamu", "Favorite" : "Mėgiamas", - "Upload" : "Įkelti", "Text file" : "Teksto failas", + "New text file.txt" : "Naujas tekstas file.txt", "Folder" : "Katalogas", "New folder" : "Naujas aplankas", + "{newname} already exists" : "{newname} jau egzistuoja", + "Upload" : "Įkelti", "An error occurred while trying to update the tags" : "Bandant atnaujinti žymes įvyko klaida", "A new file or folder has been <strong>created</strong>" : "Naujas failas ar aplankas buvo <strong>sukurtas</strong>", "A file or folder has been <strong>changed</strong>" : "Failas ar aplankas buvo <strong>pakeistas</strong>", @@ -92,6 +96,9 @@ OC.L10N.register( "%2$s deleted %1$s" : "%2$s ištrynė %1$s", "You restored %1$s" : "Jūs atkūrėte %1$s", "%2$s restored %1$s" : "%2$s atkurta %1$s", + "Changed by %2$s" : "Pakeitė %2$s", + "Deleted by %2$s" : "Ištrynė %2$s", + "Restored by %2$s" : "Atkūrė %2$s", "%s could not be renamed as it has been deleted" : "%s negalėjo būti pervadintas, nes buvo ištrintas", "%s could not be renamed" : "%s negali būti pervadintas", "Upload (max. %s)" : "Įkelti (maks. %s)", @@ -99,7 +106,6 @@ OC.L10N.register( "Maximum upload size" : "Maksimalus įkeliamo failo dydis", "max. possible: " : "maks. galima:", "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Naudokite šį adresą, kad <a href=\"%s\" target=\"_blank\">pasiektumėte savo failus per WebDAV</a>", diff --git a/apps/files/l10n/lt_LT.json b/apps/files/l10n/lt_LT.json index d7aa2cc9c35..aef54469542 100644 --- a/apps/files/l10n/lt_LT.json +++ b/apps/files/l10n/lt_LT.json @@ -28,10 +28,10 @@ "Favorites" : "Mėgstamiausi", "Home" : "Namų", "Close" : "Užverti", + "Upload cancelled." : "Įkėlimas atšauktas.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Nepavyksta įkelti {filename}, nes tai katalogas arba yra 0 baitų dydžio", "Total file size {size1} exceeds upload limit {size2}" : "Visas failo dydis {size1} viršyja įkėlimo limitą {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Nepakanka laisvos vietos. Keliate {size1}, bet tik {size2} yra likę", - "Upload cancelled." : "Įkėlimas atšauktas.", "Could not get result from server." : "Nepavyko gauti rezultato iš serverio.", "File upload is in progress. Leaving the page now will cancel the upload." : "Failo įkėlimas pradėtas. Jei paliksite šį puslapį, įkėlimas nutrūks.", "Actions" : "Veiksmai", @@ -69,12 +69,16 @@ "Storage of {owner} is almost full ({usedSpacePercent}%)" : "{owner} saugykla yra beveik pilna ({usedSpacePercent}%)", "Your storage is almost full ({usedSpacePercent}%)" : "Jūsų vieta serveryje beveik visa užimta ({usedSpacePercent}%)", "_matches '{filter}'_::_match '{filter}'_" : ["atitikmuo „{filter}“","atitikmenys „{filter}“","atitikmenų „{filter}“"], + "Path" : "Kelias", + "_%n byte_::_%n bytes_" : ["%n baitas","%n baitai","%n baitų"], "Favorited" : "Pažymėta mėgstamu", "Favorite" : "Mėgiamas", - "Upload" : "Įkelti", "Text file" : "Teksto failas", + "New text file.txt" : "Naujas tekstas file.txt", "Folder" : "Katalogas", "New folder" : "Naujas aplankas", + "{newname} already exists" : "{newname} jau egzistuoja", + "Upload" : "Įkelti", "An error occurred while trying to update the tags" : "Bandant atnaujinti žymes įvyko klaida", "A new file or folder has been <strong>created</strong>" : "Naujas failas ar aplankas buvo <strong>sukurtas</strong>", "A file or folder has been <strong>changed</strong>" : "Failas ar aplankas buvo <strong>pakeistas</strong>", @@ -90,6 +94,9 @@ "%2$s deleted %1$s" : "%2$s ištrynė %1$s", "You restored %1$s" : "Jūs atkūrėte %1$s", "%2$s restored %1$s" : "%2$s atkurta %1$s", + "Changed by %2$s" : "Pakeitė %2$s", + "Deleted by %2$s" : "Ištrynė %2$s", + "Restored by %2$s" : "Atkūrė %2$s", "%s could not be renamed as it has been deleted" : "%s negalėjo būti pervadintas, nes buvo ištrintas", "%s could not be renamed" : "%s negali būti pervadintas", "Upload (max. %s)" : "Įkelti (maks. %s)", @@ -97,7 +104,6 @@ "Maximum upload size" : "Maksimalus įkeliamo failo dydis", "max. possible: " : "maks. galima:", "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Naudokite šį adresą, kad <a href=\"%s\" target=\"_blank\">pasiektumėte savo failus per WebDAV</a>", diff --git a/apps/files/l10n/lv.js b/apps/files/l10n/lv.js index fa5ddf4f402..ad18fe93244 100644 --- a/apps/files/l10n/lv.js +++ b/apps/files/l10n/lv.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Iecienītie", "Home" : "Mājas", "Close" : "Aizvērt", + "Upload cancelled." : "Augšupielāde ir atcelta.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Neizdodas augšupielādēt {filename}, jo tā ir vai nu mape vai 0 baitu saturošs fails.", "Total file size {size1} exceeds upload limit {size2}" : "Kopējais faila izmērs {size1} pārsniedz augšupielādes ierobežojumu {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Nav pietiekami daudz brīvas vietas. Tiek augšupielādēti {size1}, bet pieejami tikai {size2}", - "Upload cancelled." : "Augšupielāde ir atcelta.", "Could not get result from server." : "Nevar saņemt rezultātus no servera", "File upload is in progress. Leaving the page now will cancel the upload." : "Notiek augšupielāde. Pametot lapu tagad, tiks atcelta augšupielāde.", "Actions" : "Darbības", @@ -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 <strong>created</strong>" : "<strong>Izveidots</strong> jauns fails vai mape", "A file or folder has been <strong>changed</strong>" : "<strong>Izmainīts</strong> fails vai mape", diff --git a/apps/files/l10n/lv.json b/apps/files/l10n/lv.json index b164c88e381..16ac9adf08d 100644 --- a/apps/files/l10n/lv.json +++ b/apps/files/l10n/lv.json @@ -28,10 +28,10 @@ "Favorites" : "Iecienītie", "Home" : "Mājas", "Close" : "Aizvērt", + "Upload cancelled." : "Augšupielāde ir atcelta.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Neizdodas augšupielādēt {filename}, jo tā ir vai nu mape vai 0 baitu saturošs fails.", "Total file size {size1} exceeds upload limit {size2}" : "Kopējais faila izmērs {size1} pārsniedz augšupielādes ierobežojumu {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Nav pietiekami daudz brīvas vietas. Tiek augšupielādēti {size1}, bet pieejami tikai {size2}", - "Upload cancelled." : "Augšupielāde ir atcelta.", "Could not get result from server." : "Nevar saņemt rezultātus no servera", "File upload is in progress. Leaving the page now will cancel the upload." : "Notiek augšupielāde. Pametot lapu tagad, tiks atcelta augšupielāde.", "Actions" : "Darbības", @@ -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 <strong>created</strong>" : "<strong>Izveidots</strong> jauns fails vai mape", "A file or folder has been <strong>changed</strong>" : "<strong>Izmainīts</strong> 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 3d27173708d..a1f8def347e 100644 --- a/apps/files/l10n/nb_NO.js +++ b/apps/files/l10n/nb_NO.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Favoritter", "Home" : "Hjem", "Close" : "Lukk", + "Upload cancelled." : "Opplasting avbrutt.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Kan ikke laste opp {filename} fordi det er en mappe eller har 0 bytes", "Total file size {size1} exceeds upload limit {size2}" : "Total filstørrelse {size1} overstiger grense for opplasting {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Ikke nok ledig plass. Du laster opp size1} men bare {size2} er ledig", - "Upload cancelled." : "Opplasting avbrutt.", "Could not get result from server." : "Fikk ikke resultat fra serveren.", "File upload is in progress. Leaving the page now will cancel the upload." : "Filopplasting pågår. Forlater du siden nå avbrytes opplastingen.", "Actions" : "Handlinger", @@ -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 <strong>created</strong>" : "En ny fil eller mappe ble <strong>opprettet</strong>", "A file or folder has been <strong>changed</strong>" : "En fil eller mappe ble <strong>endret</strong>", @@ -96,15 +96,16 @@ OC.L10N.register( "%2$s deleted %1$s" : "%2$s slettet %1$s", "You restored %1$s" : "Du gjenopprettet %1$s", "%2$s restored %1$s" : "%2$s gjenopprettet %1$s", + "Changed by %2$s" : "Endret av %2$s", + "Deleted by %2$s" : "Slettet av %2$s", + "Restored by %2$s" : "Gjenopprettet av %2$s", "%s could not be renamed as it has been deleted" : "%s kunne ikke gis nytt navn da den er blitt slettet", "%s could not be renamed" : "Kunne ikke gi nytt navn til %s", "Upload (max. %s)" : "Opplasting (maks. %s)", "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Bruk denne adressen for å <a href=\"%s\" target=\"_blank\">få tilgang til filene dine via WebDAV</a>", diff --git a/apps/files/l10n/nb_NO.json b/apps/files/l10n/nb_NO.json index a7e0cf33b83..6d7ee493008 100644 --- a/apps/files/l10n/nb_NO.json +++ b/apps/files/l10n/nb_NO.json @@ -28,10 +28,10 @@ "Favorites" : "Favoritter", "Home" : "Hjem", "Close" : "Lukk", + "Upload cancelled." : "Opplasting avbrutt.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Kan ikke laste opp {filename} fordi det er en mappe eller har 0 bytes", "Total file size {size1} exceeds upload limit {size2}" : "Total filstørrelse {size1} overstiger grense for opplasting {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Ikke nok ledig plass. Du laster opp size1} men bare {size2} er ledig", - "Upload cancelled." : "Opplasting avbrutt.", "Could not get result from server." : "Fikk ikke resultat fra serveren.", "File upload is in progress. Leaving the page now will cancel the upload." : "Filopplasting pågår. Forlater du siden nå avbrytes opplastingen.", "Actions" : "Handlinger", @@ -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 <strong>created</strong>" : "En ny fil eller mappe ble <strong>opprettet</strong>", "A file or folder has been <strong>changed</strong>" : "En fil eller mappe ble <strong>endret</strong>", @@ -94,15 +94,16 @@ "%2$s deleted %1$s" : "%2$s slettet %1$s", "You restored %1$s" : "Du gjenopprettet %1$s", "%2$s restored %1$s" : "%2$s gjenopprettet %1$s", + "Changed by %2$s" : "Endret av %2$s", + "Deleted by %2$s" : "Slettet av %2$s", + "Restored by %2$s" : "Gjenopprettet av %2$s", "%s could not be renamed as it has been deleted" : "%s kunne ikke gis nytt navn da den er blitt slettet", "%s could not be renamed" : "Kunne ikke gi nytt navn til %s", "Upload (max. %s)" : "Opplasting (maks. %s)", "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Bruk denne adressen for å <a href=\"%s\" target=\"_blank\">få tilgang til filene dine via WebDAV</a>", diff --git a/apps/files/l10n/nl.js b/apps/files/l10n/nl.js index 53ec6c1d804..88eb77c02a5 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 <strong>created</strong>" : "Een nieuw bestand of map is <strong>aangemaakt</strong>", "A file or folder has been <strong>changed</strong>" : "Een bestand of map is <strong>gewijzigd</strong>", @@ -104,9 +104,9 @@ 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.", + "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Gebruik deze link <a href=\"%s\" target=\"_blank\">om uw bestanden via WebDAV te benaderen</a>", diff --git a/apps/files/l10n/nl.json b/apps/files/l10n/nl.json index 6a077b1cc1a..0eca44aaa0d 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 <strong>created</strong>" : "Een nieuw bestand of map is <strong>aangemaakt</strong>", "A file or folder has been <strong>changed</strong>" : "Een bestand of map is <strong>gewijzigd</strong>", @@ -102,9 +102,9 @@ "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.", + "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Gebruik deze link <a href=\"%s\" target=\"_blank\">om uw bestanden via WebDAV te benaderen</a>", 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 <strong>created</strong>" : "Ei ny fil eller mappe er <strong>oppretta</strong>", "A file or folder has been <strong>changed</strong>" : "Ei fil eller mappe er <strong>endra</strong>", "A file or folder has been <strong>deleted</strong>" : "Ei fil eller mappe er <strong>sletta</strong>", 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 <strong>created</strong>" : "Ei ny fil eller mappe er <strong>oppretta</strong>", "A file or folder has been <strong>changed</strong>" : "Ei fil eller mappe er <strong>endra</strong>", "A file or folder has been <strong>deleted</strong>" : "Ei fil eller mappe er <strong>sletta</strong>", diff --git a/apps/files/l10n/oc.js b/apps/files/l10n/oc.js index 6e82e5c5dff..d702fcace3d 100644 --- a/apps/files/l10n/oc.js +++ b/apps/files/l10n/oc.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Favorits", "Home" : "Mos fichièrs", "Close" : "Tampar", + "Upload cancelled." : "Mandadís anullat.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Impossible de mandar {filename} perque s'agís d'un repertòri o d'un fichièr de talha nulla", "Total file size {size1} exceeds upload limit {size2}" : "La talha totala del fichièr {size1} excedís la talha maximala de mandadís {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Espaci liure insufisent : ensajatz de mandar {size1} mas solament {size2} son disponibles", - "Upload cancelled." : "Mandadís anullat.", "Could not get result from server." : "Pòt pas recebre los resultats del servidor.", "File upload is in progress. Leaving the page now will cancel the upload." : "Lo mandadís del fichièr es en cors. Quitar aquesta pagina ara anullarà lo mandadís del fichièr.", "Actions" : "Accions", @@ -44,6 +44,8 @@ OC.L10N.register( "Select" : "Seleccionar", "Pending" : "En espèra", "Unable to determine date" : "Impossible de determinar la data", + "This operation is forbidden" : "L'operacion es interdicha", + "This directory is unavailable, please check the logs or contact the administrator" : "Aqueste repertòri es pas disponible. Consultatz los logs o contactatz vòstre administrator", "Error moving file." : "Error al moment del desplaçament del fichièr.", "Error moving file" : "Error al moment del desplaçament del fichièr", "Error" : "Error", @@ -64,16 +66,21 @@ OC.L10N.register( "New" : "Novèl", "\"{name}\" is an invalid file name." : "\"{name}\" es pas un nom de fichièr valid.", "File name cannot be empty." : "Lo nom de fichièr pòt pas èsser void.", + "Storage of {owner} is full, files can not be updated or synced anymore!" : "L'espaci d'emmagazinatge de {owner} es plen. Los fichièrs pòdon pas mai èsser meses a jorn o sincronizats !", "Your storage is full, files can not be updated or synced anymore!" : "Vòstre espaci d'emmagazinatge es plen, los fichièrs pòdon pas mai èsser aponduts o sincronizats !", + "Storage of {owner} is almost full ({usedSpacePercent}%)" : "L'espaci d'emmagazinatge de {owner} es gaireben plen ({usedSpacePercent}%)", "Your storage is almost full ({usedSpacePercent}%)" : "Vòstre espace d'emmagazinatge es gaireben plen ({usedSpacePercent}%)", "_matches '{filter}'_::_match '{filter}'_" : ["correspond a '{filter}'","correspondon a '{filter}'"], + "Path" : "Camin", + "_%n byte_::_%n bytes_" : ["%n octet","%n octets"], "Favorited" : "Marcat coma favorit", "Favorite" : "Favorit", - "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 <strong>created</strong>" : "Un novèl fichièr o repertòri es estat <strong>creat</strong>", "A file or folder has been <strong>changed</strong>" : "Un fichièr o un repertòri es estat <strong>modificat</strong>", @@ -89,6 +96,9 @@ OC.L10N.register( "%2$s deleted %1$s" : "%2$s a suprimit %1$s", "You restored %1$s" : "Avètz restablit %1$s", "%2$s restored %1$s" : "%2$s a restablit %1$s", + "Changed by %2$s" : "Modificat per %2$s", + "Deleted by %2$s" : "Suprimit per %2$s", + "Restored by %2$s" : "Restablit per %2$s", "%s could not be renamed as it has been deleted" : "%s pòt pas èsser renomenat perque es estat suprimit ", "%s could not be renamed" : "%s pòt pas èsser renomenat", "Upload (max. %s)" : "Mandadís (max. %s)", @@ -96,7 +106,6 @@ OC.L10N.register( "Maximum upload size" : "Talha max. de mandadís", "max. possible: " : "Max. possible :", "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Utilizatz aquesta adreça per <a href=\"%s\" target=\"_blank\">accedir a vòstres fichièrs per WebDAV</a>", diff --git a/apps/files/l10n/oc.json b/apps/files/l10n/oc.json index b75d26a5ad3..ec91aa3ccba 100644 --- a/apps/files/l10n/oc.json +++ b/apps/files/l10n/oc.json @@ -28,10 +28,10 @@ "Favorites" : "Favorits", "Home" : "Mos fichièrs", "Close" : "Tampar", + "Upload cancelled." : "Mandadís anullat.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Impossible de mandar {filename} perque s'agís d'un repertòri o d'un fichièr de talha nulla", "Total file size {size1} exceeds upload limit {size2}" : "La talha totala del fichièr {size1} excedís la talha maximala de mandadís {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Espaci liure insufisent : ensajatz de mandar {size1} mas solament {size2} son disponibles", - "Upload cancelled." : "Mandadís anullat.", "Could not get result from server." : "Pòt pas recebre los resultats del servidor.", "File upload is in progress. Leaving the page now will cancel the upload." : "Lo mandadís del fichièr es en cors. Quitar aquesta pagina ara anullarà lo mandadís del fichièr.", "Actions" : "Accions", @@ -42,6 +42,8 @@ "Select" : "Seleccionar", "Pending" : "En espèra", "Unable to determine date" : "Impossible de determinar la data", + "This operation is forbidden" : "L'operacion es interdicha", + "This directory is unavailable, please check the logs or contact the administrator" : "Aqueste repertòri es pas disponible. Consultatz los logs o contactatz vòstre administrator", "Error moving file." : "Error al moment del desplaçament del fichièr.", "Error moving file" : "Error al moment del desplaçament del fichièr", "Error" : "Error", @@ -62,16 +64,21 @@ "New" : "Novèl", "\"{name}\" is an invalid file name." : "\"{name}\" es pas un nom de fichièr valid.", "File name cannot be empty." : "Lo nom de fichièr pòt pas èsser void.", + "Storage of {owner} is full, files can not be updated or synced anymore!" : "L'espaci d'emmagazinatge de {owner} es plen. Los fichièrs pòdon pas mai èsser meses a jorn o sincronizats !", "Your storage is full, files can not be updated or synced anymore!" : "Vòstre espaci d'emmagazinatge es plen, los fichièrs pòdon pas mai èsser aponduts o sincronizats !", + "Storage of {owner} is almost full ({usedSpacePercent}%)" : "L'espaci d'emmagazinatge de {owner} es gaireben plen ({usedSpacePercent}%)", "Your storage is almost full ({usedSpacePercent}%)" : "Vòstre espace d'emmagazinatge es gaireben plen ({usedSpacePercent}%)", "_matches '{filter}'_::_match '{filter}'_" : ["correspond a '{filter}'","correspondon a '{filter}'"], + "Path" : "Camin", + "_%n byte_::_%n bytes_" : ["%n octet","%n octets"], "Favorited" : "Marcat coma favorit", "Favorite" : "Favorit", - "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 <strong>created</strong>" : "Un novèl fichièr o repertòri es estat <strong>creat</strong>", "A file or folder has been <strong>changed</strong>" : "Un fichièr o un repertòri es estat <strong>modificat</strong>", @@ -87,6 +94,9 @@ "%2$s deleted %1$s" : "%2$s a suprimit %1$s", "You restored %1$s" : "Avètz restablit %1$s", "%2$s restored %1$s" : "%2$s a restablit %1$s", + "Changed by %2$s" : "Modificat per %2$s", + "Deleted by %2$s" : "Suprimit per %2$s", + "Restored by %2$s" : "Restablit per %2$s", "%s could not be renamed as it has been deleted" : "%s pòt pas èsser renomenat perque es estat suprimit ", "%s could not be renamed" : "%s pòt pas èsser renomenat", "Upload (max. %s)" : "Mandadís (max. %s)", @@ -94,7 +104,6 @@ "Maximum upload size" : "Talha max. de mandadís", "max. possible: " : "Max. possible :", "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Utilizatz aquesta adreça per <a href=\"%s\" target=\"_blank\">accedir a vòstres fichièrs per WebDAV</a>", 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 <strong>created</strong>" : "Nowy plik lub folder został <strong>utworzony</strong>", "A file or folder has been <strong>changed</strong>" : "Plik lub folder został <strong>zmieniony</strong>", "A file or folder has been <strong>deleted</strong>" : "Plik lub folder został <strong>usunięty</strong>", 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 <strong>created</strong>" : "Nowy plik lub folder został <strong>utworzony</strong>", "A file or folder has been <strong>changed</strong>" : "Plik lub folder został <strong>zmieniony</strong>", "A file or folder has been <strong>deleted</strong>" : "Plik lub folder został <strong>usunięty</strong>", diff --git a/apps/files/l10n/pt_BR.js b/apps/files/l10n/pt_BR.js index 70d38e747ba..b7a2196db63 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 <strong>created</strong>" : "Um novo arquivo ou pasta foi <strong>criado</strong>", "A file or folder has been <strong>changed</strong>" : "Um arquivo ou pasta foi <strong>modificado</strong>", @@ -105,9 +105,9 @@ 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.", + "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Use este endereço <a href=\"%s\" target=\"_blank\">para ter acesso aos seus Arquivos via WebDAV</a>", diff --git a/apps/files/l10n/pt_BR.json b/apps/files/l10n/pt_BR.json index d0023e7d5be..335b50a2d7d 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 <strong>created</strong>" : "Um novo arquivo ou pasta foi <strong>criado</strong>", "A file or folder has been <strong>changed</strong>" : "Um arquivo ou pasta foi <strong>modificado</strong>", @@ -103,9 +103,9 @@ "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.", + "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Use este endereço <a href=\"%s\" target=\"_blank\">para ter acesso aos seus Arquivos via WebDAV</a>", diff --git a/apps/files/l10n/pt_PT.js b/apps/files/l10n/pt_PT.js index b395fdd1cd9..537abb936b1 100644 --- a/apps/files/l10n/pt_PT.js +++ b/apps/files/l10n/pt_PT.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Favoritos", "Home" : "Casa", "Close" : "Fechar", + "Upload cancelled." : "Envio cancelado.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Incapaz de enviar {filename}, dado que é uma pasta, ou tem 0 bytes", "Total file size {size1} exceeds upload limit {size2}" : "O tamanho total do ficheiro {size1} excede o limite de carregamento {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Não existe espaço suficiente. Está a enviar {size1} mas apenas existe {size2} disponível", - "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 ficheiro em progresso. Se deixar a página agora, irá cancelar o envio.", "Actions" : "Ações", @@ -75,12 +75,12 @@ OC.L10N.register( "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"], "Favorited" : "Assinalado como Favorito", "Favorite" : "Favorito", - "{newname} already exists" : "{newname} já existe", - "Upload" : "Enviar", "Text file" : "Ficheiro de Texto", "New text file.txt" : "Novo texto ficheiro.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 ao tentar atualizar as tags", "A new file or folder has been <strong>created</strong>" : "Foi <strong>criado</strong> um novo ficheiro ou pasta", "A file or folder has been <strong>changed</strong>" : "Foi <strong>alterado</strong> um ficheiro ou pasta", @@ -96,15 +96,16 @@ OC.L10N.register( "%2$s deleted %1$s" : "%2$s apagou %1$s", "You restored %1$s" : "Restaurou %1$s", "%2$s restored %1$s" : "%2$s restaurou %1$s", + "Changed by %2$s" : "Alterado por %2$s", + "Deleted by %2$s" : "Eliminado por %2$s", + "Restored by %2$s" : "Restaurado por %2$s", "%s could not be renamed as it has been deleted" : "Não foi possível renomear %s devido a ter sido eliminado", "%s could not be renamed" : "%s não pode ser renomeada", "Upload (max. %s)" : "Enviar (max. %s)", "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Utilize esta ligação para <a href=\"%s\" target=\"_blank\">aceder aos seus ficheiros via WebDAV</a>", diff --git a/apps/files/l10n/pt_PT.json b/apps/files/l10n/pt_PT.json index afa8a67a5d7..20e8dd808cc 100644 --- a/apps/files/l10n/pt_PT.json +++ b/apps/files/l10n/pt_PT.json @@ -28,10 +28,10 @@ "Favorites" : "Favoritos", "Home" : "Casa", "Close" : "Fechar", + "Upload cancelled." : "Envio cancelado.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Incapaz de enviar {filename}, dado que é uma pasta, ou tem 0 bytes", "Total file size {size1} exceeds upload limit {size2}" : "O tamanho total do ficheiro {size1} excede o limite de carregamento {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Não existe espaço suficiente. Está a enviar {size1} mas apenas existe {size2} disponível", - "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 ficheiro em progresso. Se deixar a página agora, irá cancelar o envio.", "Actions" : "Ações", @@ -73,12 +73,12 @@ "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"], "Favorited" : "Assinalado como Favorito", "Favorite" : "Favorito", - "{newname} already exists" : "{newname} já existe", - "Upload" : "Enviar", "Text file" : "Ficheiro de Texto", "New text file.txt" : "Novo texto ficheiro.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 ao tentar atualizar as tags", "A new file or folder has been <strong>created</strong>" : "Foi <strong>criado</strong> um novo ficheiro ou pasta", "A file or folder has been <strong>changed</strong>" : "Foi <strong>alterado</strong> um ficheiro ou pasta", @@ -94,15 +94,16 @@ "%2$s deleted %1$s" : "%2$s apagou %1$s", "You restored %1$s" : "Restaurou %1$s", "%2$s restored %1$s" : "%2$s restaurou %1$s", + "Changed by %2$s" : "Alterado por %2$s", + "Deleted by %2$s" : "Eliminado por %2$s", + "Restored by %2$s" : "Restaurado por %2$s", "%s could not be renamed as it has been deleted" : "Não foi possível renomear %s devido a ter sido eliminado", "%s could not be renamed" : "%s não pode ser renomeada", "Upload (max. %s)" : "Enviar (max. %s)", "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Utilize esta ligação para <a href=\"%s\" target=\"_blank\">aceder aos seus ficheiros via WebDAV</a>", 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 <strong>created</strong>" : "Un nou fișier sau dosar a fost <strong>creat</strong>", "A file or folder has been <strong>changed</strong>" : "Un nou fișier sau dosar a fost <strong>modificat</strong>", "A file or folder has been <strong>deleted</strong>" : "Un nou fișier sau dosar a fost <strong>șters</strong>", 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 <strong>created</strong>" : "Un nou fișier sau dosar a fost <strong>creat</strong>", "A file or folder has been <strong>changed</strong>" : "Un nou fișier sau dosar a fost <strong>modificat</strong>", "A file or folder has been <strong>deleted</strong>" : "Un nou fișier sau dosar a fost <strong>șters</strong>", 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 <strong>created</strong>" : "<strong>Создан</strong> новый файл или каталог", "A file or folder has been <strong>changed</strong>" : "<strong>Изменён</strong> файл или каталог", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Используйте этот адрес для <a href=\"%s\" target=\"_blank\">доступа файлам через WebDAV</a>", 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 <strong>created</strong>" : "<strong>Создан</strong> новый файл или каталог", "A file or folder has been <strong>changed</strong>" : "<strong>Изменён</strong> файл или каталог", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Используйте этот адрес для <a href=\"%s\" target=\"_blank\">доступа файлам через WebDAV</a>", 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 <strong>created</strong>" : "නව ගොනුවක් හෝ බහාලුමක් <strong> නිර්මාණය කර ඇත</ strong> ", "A file or folder has been <strong>changed</strong>" : "ගොනුවක් හෝ ෆෝල්ඩරයක් <strong>වෙනස්</strong> වී ඇත", "A file or folder has been <strong>deleted</strong>" : "ගොනුවක් හෝ ෆෝල්ඩරයක් <strong>මකා දමා</strong> ඇත", 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 <strong>created</strong>" : "නව ගොනුවක් හෝ බහාලුමක් <strong> නිර්මාණය කර ඇත</ strong> ", "A file or folder has been <strong>changed</strong>" : "ගොනුවක් හෝ ෆෝල්ඩරයක් <strong>වෙනස්</strong> වී ඇත", "A file or folder has been <strong>deleted</strong>" : "ගොනුවක් හෝ ෆෝල්ඩරයක් <strong>මකා දමා</strong> ඇත", 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 <strong>created</strong>" : "Nový súbor alebo priečinok bol <strong>vytvorený</strong>", "A file or folder has been <strong>changed</strong>" : "Súbor alebo priečinok bol <strong>zmenený</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Použite túto linku <a href=\"%s\" target=\"_blank\">pre prístup k vašim súborom cez WebDAV</a>", 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 <strong>created</strong>" : "Nový súbor alebo priečinok bol <strong>vytvorený</strong>", "A file or folder has been <strong>changed</strong>" : "Súbor alebo priečinok bol <strong>zmenený</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Použite túto linku <a href=\"%s\" target=\"_blank\">pre prístup k vašim súborom cez WebDAV</a>", 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 <strong>created</strong>" : "Nova datoteka ali mapa je <strong>ustvarjena</strong>", "A file or folder has been <strong>changed</strong>" : "Datoteka ali mapa je <strong>spremenjena</strong>.", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Uporabite naslov <a href=\"%s\" target=\"_blank\"> za dostop do datotek peko sistema WebDAV</a>.", 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 <strong>created</strong>" : "Nova datoteka ali mapa je <strong>ustvarjena</strong>", "A file or folder has been <strong>changed</strong>" : "Datoteka ali mapa je <strong>spremenjena</strong>.", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Uporabite naslov <a href=\"%s\" target=\"_blank\"> za dostop do datotek peko sistema WebDAV</a>.", diff --git a/apps/files/l10n/sq.js b/apps/files/l10n/sq.js index 4ed7b72558d..5f0b3a8c936 100644 --- a/apps/files/l10n/sq.js +++ b/apps/files/l10n/sq.js @@ -27,7 +27,7 @@ OC.L10N.register( "Invalid directory." : "Drejtori e pavlefshme.", "Files" : "Kartela", "All files" : "Krejt kartelat", - "Favorites" : "Të parapëlqyer", + "Favorites" : "Të parapëlqyera", "Home" : "Kreu", "Close" : "Mbylle", "Upload cancelled." : "Ngarkimi u anulua.", @@ -41,7 +41,7 @@ OC.L10N.register( "Rename" : "Riemërtojeni", "Delete" : "Fshije", "Details" : "Hollësi", - "Select" : "Përzgjidhni", + "Select" : "Përzgjidhe", "Pending" : "Në pritje", "Unable to determine date" : "S’arrihet të përcaktohet data", "This operation is forbidden" : "Ky veprim është i ndaluar", @@ -70,16 +70,17 @@ 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", "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 <strong>created</strong>" : "<strong>U krijua</strong> një kartelë ose dosje e re", "A file or folder has been <strong>changed</strong>" : "<strong>U ndryshua</strong> një kartelë ose dosje", @@ -104,9 +105,9 @@ 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.", + "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Përdorni këtë adresë për <a href=\"%s\" target=\"_blank\">të hyrë te Kartelat tuaja përmes WebDAV-it</a>", @@ -119,7 +120,7 @@ OC.L10N.register( "The files you are trying to upload exceed the maximum size for file uploads on this server." : "Kartelat që po rrekeni të ngarkoni e tejkalojnë madhësinë maksimale për ngarkime kartelash në këtë shërbyes.", "Files are being scanned, please wait." : "Kartelat po kontrollohen, ju lutemi, pritni.", "Currently scanning" : "Po kontrollohet", - "No favorites" : "Pa të parapëlqyer", + "No favorites" : "Pa të parapëlqyera", "Files and folders you mark as favorite will show up here" : "Këtu do të duken kartelat dhe dosjet që i shënoni si të parapëlqyera" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files/l10n/sq.json b/apps/files/l10n/sq.json index e3168339a2b..fceac2c5376 100644 --- a/apps/files/l10n/sq.json +++ b/apps/files/l10n/sq.json @@ -25,7 +25,7 @@ "Invalid directory." : "Drejtori e pavlefshme.", "Files" : "Kartela", "All files" : "Krejt kartelat", - "Favorites" : "Të parapëlqyer", + "Favorites" : "Të parapëlqyera", "Home" : "Kreu", "Close" : "Mbylle", "Upload cancelled." : "Ngarkimi u anulua.", @@ -39,7 +39,7 @@ "Rename" : "Riemërtojeni", "Delete" : "Fshije", "Details" : "Hollësi", - "Select" : "Përzgjidhni", + "Select" : "Përzgjidhe", "Pending" : "Në pritje", "Unable to determine date" : "S’arrihet të përcaktohet data", "This operation is forbidden" : "Ky veprim është i ndaluar", @@ -68,16 +68,17 @@ "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", "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 <strong>created</strong>" : "<strong>U krijua</strong> një kartelë ose dosje e re", "A file or folder has been <strong>changed</strong>" : "<strong>U ndryshua</strong> një kartelë ose dosje", @@ -102,9 +103,9 @@ "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.", + "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Përdorni këtë adresë për <a href=\"%s\" target=\"_blank\">të hyrë te Kartelat tuaja përmes WebDAV-it</a>", @@ -117,7 +118,7 @@ "The files you are trying to upload exceed the maximum size for file uploads on this server." : "Kartelat që po rrekeni të ngarkoni e tejkalojnë madhësinë maksimale për ngarkime kartelash në këtë shërbyes.", "Files are being scanned, please wait." : "Kartelat po kontrollohen, ju lutemi, pritni.", "Currently scanning" : "Po kontrollohet", - "No favorites" : "Pa të parapëlqyer", + "No favorites" : "Pa të parapëlqyera", "Files and folders you mark as favorite will show up here" : "Këtu do të duken kartelat dhe dosjet që i shënoni si të parapëlqyera" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file 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 <strong>created</strong>" : "Нови фајл или фасцикла су <strong>направљени</strong>", "A file or folder has been <strong>changed</strong>" : "Фајл или фасцикла су <strong>измењени</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Користите ову адресу да <a href=\"%s\" target=\"_blank\"> приступите фајловима преко ВебДАВ-а</a>", 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 <strong>created</strong>" : "Нови фајл или фасцикла су <strong>направљени</strong>", "A file or folder has been <strong>changed</strong>" : "Фајл или фасцикла су <strong>измењени</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Користите ову адресу да <a href=\"%s\" target=\"_blank\"> приступите фајловима преко ВебДАВ-а</a>", 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 <strong>created</strong>" : "Novi fajl ili fascikla su <strong>napravljeni</strong>", "A file or folder has been <strong>changed</strong>" : "Fajl ili fascikla su <strong>izmenjeni</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Koristite ovu adresu da <a href=\"%s\" target=\"_blank\"> pristupite fajlovima preko WebDAV-a</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 <strong>created</strong>" : "Novi fajl ili fascikla su <strong>napravljeni</strong>", "A file or folder has been <strong>changed</strong>" : "Fajl ili fascikla su <strong>izmenjeni</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Koristite ovu adresu da <a href=\"%s\" target=\"_blank\"> pristupite fajlovima preko WebDAV-a</a>", diff --git a/apps/files/l10n/sv.js b/apps/files/l10n/sv.js index a5dc7478f80..58f6d76c29e 100644 --- a/apps/files/l10n/sv.js +++ b/apps/files/l10n/sv.js @@ -30,10 +30,10 @@ OC.L10N.register( "Favorites" : "Favoriter", "Home" : "Hem", "Close" : "Stäng", + "Upload cancelled." : "Uppladdning avbruten.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Kan inte ladda upp {filename} eftersom den antingen är en mapp eller har 0 bytes.", "Total file size {size1} exceeds upload limit {size2}" : "Totala filstorleken {size1} överskrider uppladdningsgränsen {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Inte tillräckligt med ledigt utrymme, du laddar upp {size1} men endast {size2} finns kvar.", - "Upload cancelled." : "Uppladdning avbruten.", "Could not get result from server." : "Gick inte att hämta resultat från server.", "File upload is in progress. Leaving the page now will cancel the upload." : "Filuppladdning pågår. Lämnar du sidan så avbryts uppladdningen.", "Actions" : "Åtgärder", @@ -44,6 +44,8 @@ OC.L10N.register( "Select" : "Välj", "Pending" : "Väntar", "Unable to determine date" : "Misslyckades avgöra datum", + "This operation is forbidden" : "Denna operation är förbjuden", + "This directory is unavailable, please check the logs or contact the administrator" : "Denna katalog är inte tillgänglig, kontrollera loggarna eller kontakta administratören", "Error moving file." : "Fel vid flytt av fil.", "Error moving file" : "Fel uppstod vid flyttning av fil", "Error" : "Fel", @@ -52,6 +54,7 @@ OC.L10N.register( "Could not create file" : "Kunde ej skapa fil", "Could not create folder" : "Kunde ej skapa katalog", "Error deleting file." : "Kunde inte ta bort filen.", + "No entries in this folder match '{filter}'" : "Inga poster i denna mapp match \"{filter}\"", "Name" : "Namn", "Size" : "Storlek", "Modified" : "Ändrad", @@ -63,14 +66,20 @@ OC.L10N.register( "New" : "Ny", "\"{name}\" is an invalid file name." : "\"{name}\" är ett ogiltligt filnamn.", "File name cannot be empty." : "Filnamn kan inte vara tomt.", + "Storage of {owner} is full, files can not be updated or synced anymore!" : "Lagring av {owner} är full, filer kan inte uppdateras eller synkroniseras längre!", "Your storage is full, files can not be updated or synced anymore!" : "Ditt lagringsutrymme är fullt, filer kan inte längre uppdateras eller synkroniseras!", + "Storage of {owner} is almost full ({usedSpacePercent}%)" : "Lagring av {owner} är nästan full ({usedSpacePercent}%)", "Your storage is almost full ({usedSpacePercent}%)" : "Ditt lagringsutrymme är nästan fullt ({usedSpacePercent}%)", + "Path" : "sökväg", "Favorited" : "Favoritiserad", "Favorite" : "Favorit", - "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 <strong>created</strong>" : "En ny fil eller mapp har blivit <strong>skapad</strong>", "A file or folder has been <strong>changed</strong>" : "En ny fil eller mapp har blivit <strong>ändrad</strong>", "A file or folder has been <strong>deleted</strong>" : "En ny fil eller mapp har blivit <strong>raderad</strong>", @@ -84,6 +93,9 @@ OC.L10N.register( "%2$s deleted %1$s" : "%2$s raderade %1$s", "You restored %1$s" : "Du återkapade %1$s", "%2$s restored %1$s" : "%2$s återskapade %1$s", + "Changed by %2$s" : "Ändrad av %2$s", + "Deleted by %2$s" : "Bortagen av %2$s", + "Restored by %2$s" : "Återställd av %2$s", "%s could not be renamed as it has been deleted" : "%s kan inte döpas om eftersom den har raderats", "%s could not be renamed" : "%s kunde inte namnändras", "Upload (max. %s)" : "Ladda upp (max. %s)", @@ -95,7 +107,9 @@ OC.L10N.register( "WebDAV" : "WebDAV", "Use this address to <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Använd denna adress till <a href=\"%s\" target=\"_blank\">nå dina Filer via WebDAV</a>", "Cancel upload" : "Avbryt uppladdning", + "No files in here" : "Inga filer kunde hittas", "Upload some content or sync with your devices!" : "Ladda upp innehåll eller synkronisera med dina enheter!", + "No entries found in this folder" : "nga Filer hittades i denna mapp", "Select all" : "Välj allt", "Upload too large" : "För stor uppladdning", "The files you are trying to upload exceed the maximum size for file uploads on this server." : "Filerna du försöker ladda upp överstiger den maximala storleken för filöverföringar på servern.", diff --git a/apps/files/l10n/sv.json b/apps/files/l10n/sv.json index afcbb6100db..35faa25d1a0 100644 --- a/apps/files/l10n/sv.json +++ b/apps/files/l10n/sv.json @@ -28,10 +28,10 @@ "Favorites" : "Favoriter", "Home" : "Hem", "Close" : "Stäng", + "Upload cancelled." : "Uppladdning avbruten.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Kan inte ladda upp {filename} eftersom den antingen är en mapp eller har 0 bytes.", "Total file size {size1} exceeds upload limit {size2}" : "Totala filstorleken {size1} överskrider uppladdningsgränsen {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Inte tillräckligt med ledigt utrymme, du laddar upp {size1} men endast {size2} finns kvar.", - "Upload cancelled." : "Uppladdning avbruten.", "Could not get result from server." : "Gick inte att hämta resultat från server.", "File upload is in progress. Leaving the page now will cancel the upload." : "Filuppladdning pågår. Lämnar du sidan så avbryts uppladdningen.", "Actions" : "Åtgärder", @@ -42,6 +42,8 @@ "Select" : "Välj", "Pending" : "Väntar", "Unable to determine date" : "Misslyckades avgöra datum", + "This operation is forbidden" : "Denna operation är förbjuden", + "This directory is unavailable, please check the logs or contact the administrator" : "Denna katalog är inte tillgänglig, kontrollera loggarna eller kontakta administratören", "Error moving file." : "Fel vid flytt av fil.", "Error moving file" : "Fel uppstod vid flyttning av fil", "Error" : "Fel", @@ -50,6 +52,7 @@ "Could not create file" : "Kunde ej skapa fil", "Could not create folder" : "Kunde ej skapa katalog", "Error deleting file." : "Kunde inte ta bort filen.", + "No entries in this folder match '{filter}'" : "Inga poster i denna mapp match \"{filter}\"", "Name" : "Namn", "Size" : "Storlek", "Modified" : "Ändrad", @@ -61,14 +64,20 @@ "New" : "Ny", "\"{name}\" is an invalid file name." : "\"{name}\" är ett ogiltligt filnamn.", "File name cannot be empty." : "Filnamn kan inte vara tomt.", + "Storage of {owner} is full, files can not be updated or synced anymore!" : "Lagring av {owner} är full, filer kan inte uppdateras eller synkroniseras längre!", "Your storage is full, files can not be updated or synced anymore!" : "Ditt lagringsutrymme är fullt, filer kan inte längre uppdateras eller synkroniseras!", + "Storage of {owner} is almost full ({usedSpacePercent}%)" : "Lagring av {owner} är nästan full ({usedSpacePercent}%)", "Your storage is almost full ({usedSpacePercent}%)" : "Ditt lagringsutrymme är nästan fullt ({usedSpacePercent}%)", + "Path" : "sökväg", "Favorited" : "Favoritiserad", "Favorite" : "Favorit", - "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 <strong>created</strong>" : "En ny fil eller mapp har blivit <strong>skapad</strong>", "A file or folder has been <strong>changed</strong>" : "En ny fil eller mapp har blivit <strong>ändrad</strong>", "A file or folder has been <strong>deleted</strong>" : "En ny fil eller mapp har blivit <strong>raderad</strong>", @@ -82,6 +91,9 @@ "%2$s deleted %1$s" : "%2$s raderade %1$s", "You restored %1$s" : "Du återkapade %1$s", "%2$s restored %1$s" : "%2$s återskapade %1$s", + "Changed by %2$s" : "Ändrad av %2$s", + "Deleted by %2$s" : "Bortagen av %2$s", + "Restored by %2$s" : "Återställd av %2$s", "%s could not be renamed as it has been deleted" : "%s kan inte döpas om eftersom den har raderats", "%s could not be renamed" : "%s kunde inte namnändras", "Upload (max. %s)" : "Ladda upp (max. %s)", @@ -93,7 +105,9 @@ "WebDAV" : "WebDAV", "Use this address to <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Använd denna adress till <a href=\"%s\" target=\"_blank\">nå dina Filer via WebDAV</a>", "Cancel upload" : "Avbryt uppladdning", + "No files in here" : "Inga filer kunde hittas", "Upload some content or sync with your devices!" : "Ladda upp innehåll eller synkronisera med dina enheter!", + "No entries found in this folder" : "nga Filer hittades i denna mapp", "Select all" : "Välj allt", "Upload too large" : "För stor uppladdning", "The files you are trying to upload exceed the maximum size for file uploads on this server." : "Filerna du försöker ladda upp överstiger den maximala storleken för filöverföringar på servern.", 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 <strong>created</strong>" : "ஒரு புதிய கோப்புறை அல்லது ஆவணம் <strong> உருவாக்கப்பட்டுள்ளது.</strong>", "A file or folder has been <strong>changed</strong>" : "ஒரு கோப்புறை அல்லது ஆவணம் <strong>மாற்றம் செய்யப்பட்டுள்ளது.</strong>", "A file or folder has been <strong>deleted</strong>" : "ஒரு கோப்புறை அல்லது ஆவணம் <strong> நீக்கப்பட்டுள்ளது. </strong>", 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 <strong>created</strong>" : "ஒரு புதிய கோப்புறை அல்லது ஆவணம் <strong> உருவாக்கப்பட்டுள்ளது.</strong>", "A file or folder has been <strong>changed</strong>" : "ஒரு கோப்புறை அல்லது ஆவணம் <strong>மாற்றம் செய்யப்பட்டுள்ளது.</strong>", "A file or folder has been <strong>deleted</strong>" : "ஒரு கோப்புறை அல்லது ஆவணம் <strong> நீக்கப்பட்டுள்ளது. </strong>", 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..79747b68ee9 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,10 @@ 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 <strong>created</strong>" : "มีไฟล์ใหม่หรือโฟลเดอร์ได้ถูก <strong>สร้างขึ้น!</strong>", "A file or folder has been <strong>changed</strong>" : "มีไฟล์หรือโฟลเดอร์ได้ถูก <strong>เปลี่ยน!</strong>", @@ -105,9 +103,9 @@ 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." : "ไม่สามารถแก้ไขได้จากที่นี่เนื่องจากสิทธิ์ไม่เพียงพอ", + "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "ใช้ที่อยู่นี้เพื่อ <a href=\"%s\" target=\"_blank\">เข้าถึงไฟล์ของคุณผ่าน WebDAV</a>", @@ -121,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 e15e4e5803b..327e2d9eb82 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,10 @@ "_%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 <strong>created</strong>" : "มีไฟล์ใหม่หรือโฟลเดอร์ได้ถูก <strong>สร้างขึ้น!</strong>", "A file or folder has been <strong>changed</strong>" : "มีไฟล์หรือโฟลเดอร์ได้ถูก <strong>เปลี่ยน!</strong>", @@ -103,9 +101,9 @@ "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." : "ไม่สามารถแก้ไขได้จากที่นี่เนื่องจากสิทธิ์ไม่เพียงพอ", + "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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "ใช้ที่อยู่นี้เพื่อ <a href=\"%s\" target=\"_blank\">เข้าถึงไฟล์ของคุณผ่าน WebDAV</a>", @@ -119,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/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 <strong>created</strong>" : "Yeni bir dosya veya klasör <strong>oluşturuldu</strong>", "A file or folder has been <strong>changed</strong>" : "Bir dosya veya klasör <strong>değiştirildi</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "<a href=\"%s\" target=\"_blank\">Dosyalarınıza WebDAV aracılığıyla erişmek için</a> 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 <strong>created</strong>" : "Yeni bir dosya veya klasör <strong>oluşturuldu</strong>", "A file or folder has been <strong>changed</strong>" : "Bir dosya veya klasör <strong>değiştirildi</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "<a href=\"%s\" target=\"_blank\">Dosyalarınıza WebDAV aracılığıyla erişmek için</a> 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 <strong>created</strong>" : "Новий файл або теку було <strong>створено</strong>", "A file or folder has been <strong>changed</strong>" : "Файл або теку було <strong> змінено </strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Для доступу до файлів через WebDAV використовуйте <a href=\"%s\" target=\"_blank\">це посилання</a>", 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 <strong>created</strong>" : "Новий файл або теку було <strong>створено</strong>", "A file or folder has been <strong>changed</strong>" : "Файл або теку було <strong> змінено </strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "Для доступу до файлів через WebDAV використовуйте <a href=\"%s\" target=\"_blank\">це посилання</a>", 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 <strong>created</strong>" : "一个新的文件或文件夹已被<strong>创建</strong>", "A file or folder has been <strong>changed</strong>" : "一个文件或文件夹已被<strong>修改</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "使用这个地址 <a href=\"%s\" target=\"_blank\">通过 WebDAV 访问您的文件</a>", 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 <strong>created</strong>" : "一个新的文件或文件夹已被<strong>创建</strong>", "A file or folder has been <strong>changed</strong>" : "一个文件或文件夹已被<strong>修改</strong>", @@ -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 <a href=\"%s\" target=\"_blank\">access your Files via WebDAV</a>" : "使用这个地址 <a href=\"%s\" target=\"_blank\">通过 WebDAV 访问您的文件</a>", 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 <strong>created</strong>" : "新檔案或資料夾已被 <strong> 新增 </strong>", "A file or folder has been <strong>changed</strong>" : "檔案或資料夾已被 <strong> 變成 </strong>", "A file or folder has been <strong>deleted</strong>" : "新檔案或資料夾已被 <strong> 刪除 </strong>", 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 <strong>created</strong>" : "新檔案或資料夾已被 <strong> 新增 </strong>", "A file or folder has been <strong>changed</strong>" : "檔案或資料夾已被 <strong> 變成 </strong>", "A file or folder has been <strong>deleted</strong>" : "新檔案或資料夾已被 <strong> 刪除 </strong>", diff --git a/apps/files/l10n/zh_TW.js b/apps/files/l10n/zh_TW.js index 772cf083307..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" : "建立資料夾失敗", @@ -28,12 +28,12 @@ OC.L10N.register( "Files" : "檔案", "All files" : "所有檔案", "Favorites" : "最愛", - "Home" : "住宅", + "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" : "動作", @@ -45,6 +45,7 @@ OC.L10N.register( "Pending" : "等候中", "Unable to determine date" : "無法確定日期", "This operation is forbidden" : "此動作被禁止", + "This directory is unavailable, please check the logs or contact the administrator" : "這個目錄無法存取,請檢查伺服器記錄檔或聯絡管理員", "Error moving file." : "移動檔案發生錯誤", "Error moving file" : "移動檔案失敗", "Error" : "錯誤", @@ -61,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." : "檔名不能為空", @@ -69,17 +70,21 @@ OC.L10N.register( "Your storage is full, files can not be updated or synced anymore!" : "您的儲存空間已滿,沒有辦法再更新或是同步檔案!", "Storage of {owner} is almost full ({usedSpacePercent}%)" : "{owner} 的儲存空間快要滿了 ({usedSpacePercent}%)", "Your storage is almost full ({usedSpacePercent}%)" : "您的儲存空間快要滿了 ({usedSpacePercent}%)", + "_matches '{filter}'_::_match '{filter}'_" : ["符合「{filter}」"], "Path" : "路徑", "_%n byte_::_%n bytes_" : ["%n 位元組"], "Favorited" : "已加入最愛", "Favorite" : "我的最愛", - "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 <strong>created</strong>" : "新的檔案或目錄已被 <strong>建立</strong>", "A file or folder has been <strong>changed</strong>" : "檔案或目錄已被 <strong>變更</strong>", + "Limit notifications about creation and changes to your <strong>favorite files</strong> <em>(Stream only)</em>" : "僅顯示<strong>已加星號的檔案</strong>的動態通知<em>(僅限訊息串)</em>", "A file or folder has been <strong>deleted</strong>" : "檔案或目錄已被 <strong>刪除</strong>", "A file or folder has been <strong>restored</strong>" : "檔案或目錄已被 <strong>恢復</strong>", "You created %1$s" : "您建立了 %1$s", @@ -89,8 +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 還原", "%s could not be renamed as it has been deleted" : "%s 已經被刪除了所以無法重新命名", "%s could not be renamed" : "無法重新命名 %s", "Upload (max. %s)" : "上傳(至多 %s)", @@ -107,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 4e1a38eccbd..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" : "建立資料夾失敗", @@ -26,12 +26,12 @@ "Files" : "檔案", "All files" : "所有檔案", "Favorites" : "最愛", - "Home" : "住宅", + "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" : "動作", @@ -43,6 +43,7 @@ "Pending" : "等候中", "Unable to determine date" : "無法確定日期", "This operation is forbidden" : "此動作被禁止", + "This directory is unavailable, please check the logs or contact the administrator" : "這個目錄無法存取,請檢查伺服器記錄檔或聯絡管理員", "Error moving file." : "移動檔案發生錯誤", "Error moving file" : "移動檔案失敗", "Error" : "錯誤", @@ -59,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." : "檔名不能為空", @@ -67,17 +68,21 @@ "Your storage is full, files can not be updated or synced anymore!" : "您的儲存空間已滿,沒有辦法再更新或是同步檔案!", "Storage of {owner} is almost full ({usedSpacePercent}%)" : "{owner} 的儲存空間快要滿了 ({usedSpacePercent}%)", "Your storage is almost full ({usedSpacePercent}%)" : "您的儲存空間快要滿了 ({usedSpacePercent}%)", + "_matches '{filter}'_::_match '{filter}'_" : ["符合「{filter}」"], "Path" : "路徑", "_%n byte_::_%n bytes_" : ["%n 位元組"], "Favorited" : "已加入最愛", "Favorite" : "我的最愛", - "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 <strong>created</strong>" : "新的檔案或目錄已被 <strong>建立</strong>", "A file or folder has been <strong>changed</strong>" : "檔案或目錄已被 <strong>變更</strong>", + "Limit notifications about creation and changes to your <strong>favorite files</strong> <em>(Stream only)</em>" : "僅顯示<strong>已加星號的檔案</strong>的動態通知<em>(僅限訊息串)</em>", "A file or folder has been <strong>deleted</strong>" : "檔案或目錄已被 <strong>刪除</strong>", "A file or folder has been <strong>restored</strong>" : "檔案或目錄已被 <strong>恢復</strong>", "You created %1$s" : "您建立了 %1$s", @@ -87,8 +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 還原", "%s could not be renamed as it has been deleted" : "%s 已經被刪除了所以無法重新命名", "%s could not be renamed" : "無法重新命名 %s", "Upload (max. %s)" : "上傳(至多 %s)", @@ -105,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/files/lib/capabilities.php b/apps/files/lib/capabilities.php index 2e19283e4d6..14fb07a9d86 100644 --- a/apps/files/lib/capabilities.php +++ b/apps/files/lib/capabilities.php @@ -1,7 +1,7 @@ <?php /** * @author Christopher Schäpers <kondou@ts.unde.re> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Tom Needham <tom@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. 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 @@ <?php if($_['displayMaxPossibleUploadSize']):?> (<?php p($l->t('max. possible: ')); p($_['maxPossibleUploadSize']) ?>) <?php endif;?> - <br/> <input type="hidden" value="<?php p($_['requesttoken']); ?>" name="requesttoken" /> <?php if($_['uploadChangable']): ?> - <?php p($l->t('With PHP-FPM this value may take up to 5 minutes to take effect after saving.')); ?> - <br/> <input type="submit" name="submitFilesAdminSettings" id="submitFilesAdminSettings" value="<?php p($l->t( 'Save' )); ?>"/> + <p><em><?php p($l->t('With PHP-FPM it might take 5 minutes for changes to be applied.')); ?></em></p> <?php else: ?> - <?php p($l->t('Can not be edited from here due to insufficient permissions.')); ?> + <p><em><?php p($l->t('Missing permissions to edit from here.')); ?></em></p> <?php endif; ?> </form> 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 @@ </button> </div> <div id="app-settings-content"> - <h2> - <label for="webdavurl"><?php p($l->t('WebDAV'));?></label> - </h2> + <label for="webdavurl"><?php p($l->t('WebDAV'));?></label> <input id="webdavurl" type="text" readonly="readonly" value="<?php p(\OCP\Util::linkToRemote('webdav')); ?>" /> <em><?php print_unescaped($l->t('Use this address to <a href="%s" target="_blank">access your Files via WebDAV</a>', array(link_to_docs('user-webdav'))));?></em> </div> diff --git a/apps/files/tests/ajax_rename.php b/apps/files/tests/ajax_rename.php index 00a62fa002d..859c7042b89 100644 --- a/apps/files/tests/ajax_rename.php +++ b/apps/files/tests/ajax_rename.php @@ -5,7 +5,6 @@ * @author Joas Schilling <nickvergessen@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> * @author Robin Appelman <icewind@owncloud.com> - * @author tbartenstein <tbartenstein@users.noreply.github.com> * @author Thomas Müller <thomas.mueller@tmit.eu> * @author Vincent Petry <pvince81@owncloud.com> * diff --git a/apps/files/tests/command/deleteorphanedfilestest.php b/apps/files/tests/command/deleteorphanedfilestest.php index 3a1a541d8f1..a667dba99fc 100644 --- a/apps/files/tests/command/deleteorphanedfilestest.php +++ b/apps/files/tests/command/deleteorphanedfilestest.php @@ -1,6 +1,7 @@ <?php /** * @author Morris Jobke <hey@morrisjobke.de> + * @author Robin Appelman <icewind@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 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 @@ +<?php +/** + * @author Lukas Reschke <lukas@owncloud.com> + * + * @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 <http://www.gnu.org/licenses/> + * + */ + +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/apps/files/tests/controller/apicontrollertest.php b/apps/files/tests/controller/apicontrollertest.php index 7f34c0a5642..fb728d5eff0 100644 --- a/apps/files/tests/controller/apicontrollertest.php +++ b/apps/files/tests/controller/apicontrollertest.php @@ -1,9 +1,8 @@ <?php /** - * @author Joas Schilling <nickvergessen@owncloud.com> * @author Lukas Reschke <lukas@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 diff --git a/apps/files/tests/js/fileUploadSpec.js b/apps/files/tests/js/fileUploadSpec.js index cad8468d1c8..a49a5d4e2e0 100644 --- a/apps/files/tests/js/fileUploadSpec.js +++ b/apps/files/tests/js/fileUploadSpec.js @@ -117,4 +117,100 @@ describe('OC.Upload tests', function() { ); }); }); + describe('Upload conflicts', function() { + var oldFileList; + var conflictDialogStub; + var callbacks; + + beforeEach(function() { + oldFileList = FileList; + $('#testArea').append( + '<div id="tableContainer">' + + '<table id="filestable">' + + '<thead><tr>' + + '<th id="headerName" class="hidden column-name">' + + '<input type="checkbox" id="select_all_files" class="select-all">' + + '<a class="name columntitle" data-sort="name"><span>Name</span><span class="sort-indicator"></span></a>' + + '<span id="selectedActionsList" class="selectedActions hidden">' + + '<a href class="download"><img src="actions/download.svg">Download</a>' + + '<a href class="delete-selected">Delete</a></span>' + + '</th>' + + '<th class="hidden column-size"><a class="columntitle" data-sort="size"><span class="sort-indicator"></span></a></th>' + + '<th class="hidden column-mtime"><a class="columntitle" data-sort="mtime"><span class="sort-indicator"></span></a></th>' + + '</tr></thead>' + + '<tbody id="fileList"></tbody>' + + '<tfoot></tfoot>' + + '</table>' + + '</div>' + ); + FileList = new OCA.Files.FileList($('#tableContainer')); + + FileList.add({name: 'conflict.txt', mimetype: 'text/plain'}); + FileList.add({name: 'conflict2.txt', mimetype: 'text/plain'}); + + conflictDialogStub = sinon.stub(OC.dialogs, 'fileexists'); + callbacks = { + onNoConflicts: sinon.stub() + }; + }); + afterEach(function() { + conflictDialogStub.restore(); + + FileList.destroy(); + FileList = oldFileList; + }); + it('does not show conflict dialog when no client side conflict', function() { + var selection = { + // yes, the format of uploads is weird... + uploads: [ + {files: [{name: 'noconflict.txt'}]}, + {files: [{name: 'noconflict2.txt'}]} + ] + }; + + OC.Upload.checkExistingFiles(selection, callbacks); + + expect(conflictDialogStub.notCalled).toEqual(true); + expect(callbacks.onNoConflicts.calledOnce).toEqual(true); + expect(callbacks.onNoConflicts.calledWith(selection)).toEqual(true); + }); + it('shows conflict dialog when no client side conflict', function() { + var selection = { + // yes, the format of uploads is weird... + uploads: [ + {files: [{name: 'conflict.txt'}]}, + {files: [{name: 'conflict2.txt'}]}, + {files: [{name: 'noconflict.txt'}]} + ] + }; + + var deferred = $.Deferred(); + conflictDialogStub.returns(deferred.promise()); + deferred.resolve(); + + OC.Upload.checkExistingFiles(selection, callbacks); + + expect(conflictDialogStub.callCount).toEqual(3); + expect(conflictDialogStub.getCall(1).args[0]) + .toEqual({files: [ { name: 'conflict.txt' } ]}); + expect(conflictDialogStub.getCall(1).args[1]) + .toEqual({ name: 'conflict.txt', mimetype: 'text/plain', directory: '/' }); + expect(conflictDialogStub.getCall(1).args[2]).toEqual({ name: 'conflict.txt' }); + + // yes, the dialog must be called several times... + expect(conflictDialogStub.getCall(2).args[0]).toEqual({ + files: [ { name: 'conflict2.txt' } ] + }); + expect(conflictDialogStub.getCall(2).args[1]) + .toEqual({ name: 'conflict2.txt', mimetype: 'text/plain', directory: '/' }); + expect(conflictDialogStub.getCall(2).args[2]).toEqual({ name: 'conflict2.txt' }); + + expect(callbacks.onNoConflicts.calledOnce).toEqual(true); + expect(callbacks.onNoConflicts.calledWith({ + uploads: [ + {files: [{name: 'noconflict.txt'}]} + ] + })).toEqual(true); + }); + }); }); diff --git a/apps/files/tests/js/fileactionsSpec.js b/apps/files/tests/js/fileactionsSpec.js index 6a57c56c3af..d29164c5136 100644 --- a/apps/files/tests/js/fileactionsSpec.js +++ b/apps/files/tests/js/fileactionsSpec.js @@ -227,7 +227,7 @@ describe('OCA.Files.FileActions tests', function() { name: 'Test', type: OCA.Files.FileActions.TYPE_INLINE, mime: 'all', - icon: OC.imagePath('core', 'actions/test'), + icon: OC.imagePath('core', 'actions/test'), permissions: OC.PERMISSION_READ, actionHandler: actionStub }); @@ -556,4 +556,45 @@ describe('OCA.Files.FileActions tests', function() { expect(handler.notCalled).toEqual(true); }); }); + describe('default actions', function() { + describe('download', function() { + it('redirects to URL and sets busy state to list', function() { + var handleDownloadStub = sinon.stub(OCA.Files.Files, 'handleDownload'); + var busyStub = sinon.stub(fileList, 'showFileBusyState'); + var fileData = { + id: 18, + type: 'file', + name: 'testName.txt', + mimetype: 'text/plain', + size: '1234', + etag: 'a01234c', + mtime: '123456', + permissions: OC.PERMISSION_READ | OC.PERMISSION_UPDATE + }; + + // note: FileActions.display() is called implicitly + fileList.add(fileData); + + var model = fileList.getModelForFile('testName.txt'); + + fileActions.registerDefaultActions(); + fileActions.triggerAction('Download', model, fileList); + + expect(busyStub.calledOnce).toEqual(true); + 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' + ); + busyStub.reset(); + handleDownloadStub.yield(); + + expect(busyStub.calledOnce).toEqual(true); + expect(busyStub.calledWith('testName.txt', false)).toEqual(true); + + busyStub.restore(); + handleDownloadStub.restore(); + }); + }); + }); }); diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js index 994e1d32844..05e6fcc6122 100644 --- a/apps/files/tests/js/filelistSpec.js +++ b/apps/files/tests/js/filelistSpec.js @@ -1166,7 +1166,7 @@ describe('OCA.Files.FileList tests', function() { it('renders provided icon for file when provided', function() { var fileData = { type: 'file', - name: 'test dir', + name: 'test file', icon: OC.webroot + '/core/img/filetypes/application-pdf.svg', mimetype: 'application/pdf' }; @@ -1178,7 +1178,7 @@ describe('OCA.Files.FileList tests', function() { it('renders preview when no icon was provided and preview is available', function() { var fileData = { type: 'file', - name: 'test dir', + name: 'test file', isPreviewAvailable: true }; var $tr = fileList.add(fileData); @@ -1192,7 +1192,7 @@ describe('OCA.Files.FileList tests', function() { it('renders default file type icon when no icon was provided and no preview is available', function() { var fileData = { type: 'file', - name: 'test dir', + name: 'test file', isPreviewAvailable: false }; var $tr = fileList.add(fileData); @@ -1200,6 +1200,47 @@ describe('OCA.Files.FileList tests', function() { 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 + }; + var $tr = fileList.add(fileData); + var $td = $tr.find('td.filename'); + expect(OC.TestUtil.getImageUrl($td.find('.thumbnail'))).toEqual(OC.webroot + '/core/img/filetypes/folder.svg'); + expect(previewLoadStub.notCalled).toEqual(true); + }); + it('render external storage icon for external storage root', function() { + var fileData = { + type: 'dir', + mimetype: 'httpd/unix-directory', + name: 'test dir', + isPreviewAvailable: true, + mountType: 'external-root' + }; + var $tr = fileList.add(fileData); + var $td = $tr.find('td.filename'); + expect(OC.TestUtil.getImageUrl($td.find('.thumbnail'))).toEqual(OC.webroot + '/core/img/filetypes/folder-external.svg'); + expect(previewLoadStub.notCalled).toEqual(true); + }); + it('render external storage icon for external storage subdir', function() { + var fileData = { + type: 'dir', + mimetype: 'httpd/unix-directory', + name: 'test dir', + isPreviewAvailable: true, + mountType: 'external' + }; + var $tr = fileList.add(fileData); + var $td = $tr.find('td.filename'); + expect(OC.TestUtil.getImageUrl($td.find('.thumbnail'))).toEqual(OC.webroot + '/core/img/filetypes/folder-external.svg'); + expect(previewLoadStub.notCalled).toEqual(true); + // default icon override + expect($tr.attr('data-icon')).toEqual(OC.webroot + '/core/img/filetypes/folder-external.svg'); + }); + }); describe('viewer mode', function() { it('enabling viewer mode hides files table and action buttons', function() { diff --git a/apps/files/tests/js/filesSpec.js b/apps/files/tests/js/filesSpec.js index f20ba03e2f1..30e6675c155 100644 --- a/apps/files/tests/js/filesSpec.js +++ b/apps/files/tests/js/filesSpec.js @@ -87,4 +87,56 @@ describe('OCA.Files.Files tests', function() { expect(url).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=%5B%22test%20file.txt%22%2C%22abc.txt%22%5D'); }); }); + describe('handleDownload', function() { + var redirectStub; + var cookieStub; + var clock; + var testUrl; + + beforeEach(function() { + testUrl = 'http://example.com/owncloud/path/download.php'; + redirectStub = sinon.stub(OC, 'redirect'); + cookieStub = sinon.stub(OC.Util, 'isCookieSetToValue'); + clock = sinon.useFakeTimers(); + }); + afterEach(function() { + redirectStub.restore(); + cookieStub.restore(); + clock.restore(); + }); + + it('appends secret to url when no existing parameters', function() { + Files.handleDownload(testUrl); + expect(redirectStub.calledOnce).toEqual(true); + expect(redirectStub.getCall(0).args[0]).toContain(testUrl + '?downloadStartSecret='); + }); + it('appends secret to url with existing parameters', function() { + Files.handleDownload(testUrl + '?test=1'); + expect(redirectStub.calledOnce).toEqual(true); + expect(redirectStub.getCall(0).args[0]).toContain(testUrl + '?test=1&downloadStartSecret='); + }); + it('sets cookie and calls callback when cookie appears', function() { + var callbackStub = sinon.stub(); + var token; + Files.handleDownload(testUrl, callbackStub); + expect(redirectStub.calledOnce).toEqual(true); + token = OC.parseQueryString(redirectStub.getCall(0).args[0]).downloadStartSecret; + expect(token).toBeDefined(); + + expect(cookieStub.calledOnce).toEqual(true); + cookieStub.returns(false); + clock.tick(600); + + expect(cookieStub.calledTwice).toEqual(true); + expect(cookieStub.getCall(1).args[0]).toEqual('ocDownloadStarted'); + expect(cookieStub.getCall(1).args[1]).toEqual(token); + expect(callbackStub.notCalled).toEqual(true); + + cookieStub.returns(true); + clock.tick(2000); + + expect(cookieStub.callCount).toEqual(3); + expect(callbackStub.calledOnce).toEqual(true); + }); + }); }); diff --git a/apps/files/tests/js/mainfileinfodetailviewSpec.js b/apps/files/tests/js/mainfileinfodetailviewSpec.js index f4403196f2e..460629806c8 100644 --- a/apps/files/tests/js/mainfileinfodetailviewSpec.js +++ b/apps/files/tests/js/mainfileinfodetailviewSpec.js @@ -112,6 +112,20 @@ describe('OCA.Files.MainFileInfoDetailView tests', function() { lazyLoadPreviewStub.restore(); }); + it('uses icon from model if present in model', function() { + var lazyLoadPreviewStub = sinon.stub(fileList, 'lazyLoadPreview'); + testFileInfo.set('mimetype', 'httpd/unix-directory'); + testFileInfo.set('icon', OC.MimeType.getIconUrl('dir-external')); + view.setFileInfo(testFileInfo); + + expect(lazyLoadPreviewStub.notCalled).toEqual(true); + + expect(view.$el.find('.thumbnail').hasClass('icon-loading')).toEqual(false); + expect(view.$el.find('.thumbnail').css('background-image')) + .toContain('filetypes/folder-external.svg'); + + lazyLoadPreviewStub.restore(); + }); it('displays thumbnail', function() { var lazyLoadPreviewStub = sinon.stub(fileList, 'lazyLoadPreview'); 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); }); }); }); diff --git a/apps/files_external/3rdparty/composer.json b/apps/files_external/3rdparty/composer.json index ad007df23de..4ae2b7d0113 100644 --- a/apps/files_external/3rdparty/composer.json +++ b/apps/files_external/3rdparty/composer.json @@ -3,7 +3,9 @@ "description": "3rdparty components for files_external", "license": "MIT", "config": { - "vendor-dir": "." + "vendor-dir": ".", + "optimize-autoloader": true, + "classmap-authoritative": true }, "require": { "icewind/smb": "1.0.4", diff --git a/apps/files_external/3rdparty/composer/autoload_classmap.php b/apps/files_external/3rdparty/composer/autoload_classmap.php index 1bd6482f9ea..d5b0d51e82d 100644 --- a/apps/files_external/3rdparty/composer/autoload_classmap.php +++ b/apps/files_external/3rdparty/composer/autoload_classmap.php @@ -6,4 +6,49 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = $vendorDir; return array( + 'Icewind\\SMB\\AbstractShare' => $vendorDir . '/icewind/smb/src/AbstractShare.php', + 'Icewind\\SMB\\Connection' => $vendorDir . '/icewind/smb/src/Connection.php', + 'Icewind\\SMB\\ErrorCodes' => $vendorDir . '/icewind/smb/src/ErrorCodes.php', + 'Icewind\\SMB\\Exception\\AccessDeniedException' => $vendorDir . '/icewind/smb/src/Exception/AccessDeniedException.php', + 'Icewind\\SMB\\Exception\\AlreadyExistsException' => $vendorDir . '/icewind/smb/src/Exception/AlreadyExistsException.php', + 'Icewind\\SMB\\Exception\\AuthenticationException' => $vendorDir . '/icewind/smb/src/Exception/AuthenticationException.php', + 'Icewind\\SMB\\Exception\\ConnectException' => $vendorDir . '/icewind/smb/src/Exception/ConnectException.php', + 'Icewind\\SMB\\Exception\\ConnectionException' => $vendorDir . '/icewind/smb/src/Exception/ConnectionException.php', + 'Icewind\\SMB\\Exception\\ConnectionRefusedException' => $vendorDir . '/icewind/smb/src/Exception/ConnectionRefusedException.php', + 'Icewind\\SMB\\Exception\\Exception' => $vendorDir . '/icewind/smb/src/Exception/Exception.php', + 'Icewind\\SMB\\Exception\\FileInUseException' => $vendorDir . '/icewind/smb/src/Exception/FileInUseException.php', + 'Icewind\\SMB\\Exception\\ForbiddenException' => $vendorDir . '/icewind/smb/src/Exception/ForbiddenException.php', + 'Icewind\\SMB\\Exception\\HostDownException' => $vendorDir . '/icewind/smb/src/Exception/HostDownException.php', + 'Icewind\\SMB\\Exception\\InvalidHostException' => $vendorDir . '/icewind/smb/src/Exception/InvalidHostException.php', + 'Icewind\\SMB\\Exception\\InvalidPathException' => $vendorDir . '/icewind/smb/src/Exception/InvalidPathException.php', + 'Icewind\\SMB\\Exception\\InvalidRequestException' => $vendorDir . '/icewind/smb/src/Exception/InvalidRequestException.php', + 'Icewind\\SMB\\Exception\\InvalidTypeException' => $vendorDir . '/icewind/smb/src/Exception/InvalidTypeException.php', + 'Icewind\\SMB\\Exception\\NoLoginServerException' => $vendorDir . '/icewind/smb/src/Exception/NoLoginServerException.php', + 'Icewind\\SMB\\Exception\\NoRouteToHostException' => $vendorDir . '/icewind/smb/src/Exception/NoRouteToHostException.php', + 'Icewind\\SMB\\Exception\\NotEmptyException' => $vendorDir . '/icewind/smb/src/Exception/NotEmptyException.php', + 'Icewind\\SMB\\Exception\\NotFoundException' => $vendorDir . '/icewind/smb/src/Exception/NotFoundException.php', + 'Icewind\\SMB\\Exception\\TimedOutException' => $vendorDir . '/icewind/smb/src/Exception/TimedOutException.php', + 'Icewind\\SMB\\FileInfo' => $vendorDir . '/icewind/smb/src/FileInfo.php', + 'Icewind\\SMB\\IFileInfo' => $vendorDir . '/icewind/smb/src/IFileInfo.php', + 'Icewind\\SMB\\IShare' => $vendorDir . '/icewind/smb/src/IShare.php', + 'Icewind\\SMB\\NativeFileInfo' => $vendorDir . '/icewind/smb/src/NativeFileInfo.php', + 'Icewind\\SMB\\NativeServer' => $vendorDir . '/icewind/smb/src/NativeServer.php', + 'Icewind\\SMB\\NativeShare' => $vendorDir . '/icewind/smb/src/NativeShare.php', + 'Icewind\\SMB\\NativeState' => $vendorDir . '/icewind/smb/src/NativeState.php', + 'Icewind\\SMB\\NativeStream' => $vendorDir . '/icewind/smb/src/NativeStream.php', + 'Icewind\\SMB\\Parser' => $vendorDir . '/icewind/smb/src/Parser.php', + 'Icewind\\SMB\\RawConnection' => $vendorDir . '/icewind/smb/src/RawConnection.php', + 'Icewind\\SMB\\Server' => $vendorDir . '/icewind/smb/src/Server.php', + 'Icewind\\SMB\\Share' => $vendorDir . '/icewind/smb/src/Share.php', + 'Icewind\\SMB\\TimeZoneProvider' => $vendorDir . '/icewind/smb/src/TimeZoneProvider.php', + 'Icewind\\Streams\\CallbackWrapper' => $vendorDir . '/icewind/streams/src/CallbackWrapper.php', + 'Icewind\\Streams\\Directory' => $vendorDir . '/icewind/streams/src/Directory.php', + 'Icewind\\Streams\\File' => $vendorDir . '/icewind/streams/src/File.php', + 'Icewind\\Streams\\IteratorDirectory' => $vendorDir . '/icewind/streams/src/IteratorDirectory.php', + 'Icewind\\Streams\\NullWrapper' => $vendorDir . '/icewind/streams/src/NullWrapper.php', + 'Icewind\\Streams\\Tests\\CallbackWrapper' => $vendorDir . '/icewind/streams/tests/CallbackWrapper.php', + 'Icewind\\Streams\\Tests\\IteratorDirectory' => $vendorDir . '/icewind/streams/tests/IteratorDirectory.php', + 'Icewind\\Streams\\Tests\\NullWrapper' => $vendorDir . '/icewind/streams/tests/NullWrapper.php', + 'Icewind\\Streams\\Tests\\Wrapper' => $vendorDir . '/icewind/streams/tests/Wrapper.php', + 'Icewind\\Streams\\Wrapper' => $vendorDir . '/icewind/streams/src/Wrapper.php', ); diff --git a/apps/files_external/3rdparty/composer/autoload_real.php b/apps/files_external/3rdparty/composer/autoload_real.php index 3391b322be0..9e8b3b558e5 100644 --- a/apps/files_external/3rdparty/composer/autoload_real.php +++ b/apps/files_external/3rdparty/composer/autoload_real.php @@ -38,6 +38,7 @@ class ComposerAutoloaderInit98fe9b281934250b3a93f69a5ce843b3 $loader->addClassMap($classMap); } + $loader->setClassMapAuthoritative(true); $loader->register(true); return $loader; diff --git a/apps/files_external/ajax/oauth2.php b/apps/files_external/ajax/oauth2.php index e3e32c4b912..fbe60e16e26 100644 --- a/apps/files_external/ajax/oauth2.php +++ b/apps/files_external/ajax/oauth2.php @@ -41,6 +41,7 @@ if (isset($_POST['client_id']) && isset($_POST['client_secret']) && isset($_POST $client->setClientSecret((string)$_POST['client_secret']); $client->setRedirectUri((string)$_POST['redirect']); $client->setScopes(array('https://www.googleapis.com/auth/drive')); + $client->setApprovalPrompt('force'); $client->setAccessType('offline'); if (isset($_POST['step'])) { $step = $_POST['step']; diff --git a/apps/files_external/appinfo/app.php b/apps/files_external/appinfo/app.php index aa39d79a85e..a7d8f4f668d 100644 --- a/apps/files_external/appinfo/app.php +++ b/apps/files_external/appinfo/app.php @@ -1,8 +1,8 @@ <?php /** * @author Christian Berendt <berendt@b1-systems.de> - * @author Jan-Christoph Borchardt <hey@jancborchardt.net> * @author j-ed <juergen@eisfair.org> + * @author Jan-Christoph Borchardt <hey@jancborchardt.net> * @author Michael Gapczynski <GapczynskiM@gmail.com> * @author Robin Appelman <icewind@owncloud.com> * @author Robin McCorkell <rmccorkell@karoshi.org.uk> diff --git a/apps/files_external/appinfo/application.php b/apps/files_external/appinfo/application.php index c7deaaf270e..1d6e0d03400 100644 --- a/apps/files_external/appinfo/application.php +++ b/apps/files_external/appinfo/application.php @@ -2,7 +2,7 @@ /** * @author Morris Jobke <hey@morrisjobke.de> * @author Robin McCorkell <rmccorkell@karoshi.org.uk> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Ross Nicoll <jrn@jrn.me.uk> * @author Vincent Petry <pvince81@owncloud.com> * diff --git a/apps/files_external/appinfo/routes.php b/apps/files_external/appinfo/routes.php index a98a63c711d..39ded1dc2ec 100644 --- a/apps/files_external/appinfo/routes.php +++ b/apps/files_external/appinfo/routes.php @@ -4,7 +4,7 @@ * @author Jörn Friedrich Dreyer <jfd@butonic.de> * @author Morris Jobke <hey@morrisjobke.de> * @author Robin McCorkell <rmccorkell@karoshi.org.uk> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Ross Nicoll <jrn@jrn.me.uk> * @author Vincent Petry <pvince81@owncloud.com> * diff --git a/apps/files_external/controller/storagescontroller.php b/apps/files_external/controller/storagescontroller.php index f754565f628..048f3588ed7 100644 --- a/apps/files_external/controller/storagescontroller.php +++ b/apps/files_external/controller/storagescontroller.php @@ -237,9 +237,21 @@ abstract class StoragesController extends Controller { ) ); } catch (InsufficientDataForMeaningfulAnswerException $e) { - $storage->setStatus(\OC_Mount_Config::STATUS_INDETERMINATE); + $storage->setStatus( + \OC_Mount_Config::STATUS_INDETERMINATE, + $this->l10n->t('Insufficient data: %s', [$e->getMessage()]) + ); } catch (StorageNotAvailableException $e) { - $storage->setStatus(\OC_Mount_Config::STATUS_ERROR); + $storage->setStatus( + \OC_Mount_Config::STATUS_ERROR, + $e->getMessage() + ); + } catch (\Exception $e) { + // FIXME: convert storage exceptions to StorageNotAvailableException + $storage->setStatus( + \OC_Mount_Config::STATUS_ERROR, + get_class($e).': '.$e->getMessage() + ); } } diff --git a/apps/files_external/js/mountsfilelist.js b/apps/files_external/js/mountsfilelist.js index c45faafd9bf..35aef751fef 100644 --- a/apps/files_external/js/mountsfilelist.js +++ b/apps/files_external/js/mountsfilelist.js @@ -86,6 +86,10 @@ if (this._reloadCall) { this._reloadCall.abort(); } + + // there is only root + this._setCurrentDir('/', false); + this._reloadCall = $.ajax({ url: OC.linkToOCS('apps/files_external/api/v1') + 'mounts', data: { @@ -106,10 +110,9 @@ if (result.ocs && result.ocs.data) { this.setFiles(this._makeFiles(result.ocs.data)); + return true; } - else { - // TODO: error handling - } + return false; }, /** diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js index 5da34c52193..a839f396b9b 100644 --- a/apps/files_external/js/settings.js +++ b/apps/files_external/js/settings.js @@ -643,6 +643,10 @@ MountConfigListView.prototype = _.extend({ }); addSelect2(this.$el.find('tr:not(#addMountPoint) .applicableUsers'), this._userListLimit); + this.$el.tooltip({ + selector: '.status span', + container: 'body' + }); this._initEvents(); @@ -709,11 +713,12 @@ MountConfigListView.prototype = _.extend({ } highlightInput($target); var $tr = $target.closest('tr'); + this.updateStatus($tr, null); var timer = $tr.data('save-timer'); clearTimeout(timer); timer = setTimeout(function() { - self.saveStorageConfig($tr); + self.saveStorageConfig($tr, null, timer); }, 2000); $tr.data('save-timer', timer); }, @@ -931,8 +936,9 @@ MountConfigListView.prototype = _.extend({ * * @param $tr storage row * @param Function callback callback to call after save + * @param concurrentTimer only update if the timer matches this */ - saveStorageConfig:function($tr, callback) { + saveStorageConfig:function($tr, callback, concurrentTimer) { var self = this; var storage = this.getStorageConfig($tr); if (!storage.validate()) { @@ -942,15 +948,23 @@ MountConfigListView.prototype = _.extend({ this.updateStatus($tr, StorageConfig.Status.IN_PROGRESS); storage.save({ success: function(result) { - self.updateStatus($tr, result.status); - $tr.attr('data-id', result.id); - - if (_.isFunction(callback)) { - callback(storage); + if (concurrentTimer === undefined + || $tr.data('save-timer') === concurrentTimer + ) { + self.updateStatus($tr, result.status, result.statusMessage); + $tr.attr('data-id', result.id); + + if (_.isFunction(callback)) { + callback(storage); + } } }, error: function() { - self.updateStatus($tr, StorageConfig.Status.ERROR); + if (concurrentTimer === undefined + || $tr.data('save-timer') === concurrentTimer + ) { + self.updateStatus($tr, StorageConfig.Status.ERROR); + } } }); }, @@ -971,7 +985,7 @@ MountConfigListView.prototype = _.extend({ this.updateStatus($tr, StorageConfig.Status.IN_PROGRESS); storage.recheck({ success: function(result) { - self.updateStatus($tr, result.status); + self.updateStatus($tr, result.status, result.statusMessage); }, error: function() { self.updateStatus($tr, StorageConfig.Status.ERROR); @@ -984,11 +998,15 @@ MountConfigListView.prototype = _.extend({ * * @param {jQuery} $tr * @param {int} status + * @param {string} message */ - updateStatus: function($tr, status) { + updateStatus: function($tr, status, message) { var $statusSpan = $tr.find('.status span'); $statusSpan.removeClass('loading-small success indeterminate error'); switch (status) { + case null: + // remove status + break; case StorageConfig.Status.IN_PROGRESS: $statusSpan.addClass('loading-small'); break; @@ -1001,6 +1019,7 @@ MountConfigListView.prototype = _.extend({ default: $statusSpan.addClass('error'); } + $statusSpan.attr('data-original-title', (typeof message === 'string') ? message : ''); }, /** diff --git a/apps/files_external/l10n/ast.js b/apps/files_external/l10n/ast.js index 21eba8c59d5..b663657e029 100644 --- a/apps/files_external/l10n/ast.js +++ b/apps/files_external/l10n/ast.js @@ -55,7 +55,6 @@ OC.L10N.register( "Available for" : "Disponible pa", "Delete" : "Desaniciar", "Add storage" : "Amestar almacenamientu", - "Enable User External Storage" : "Habilitar almacenamientu esterno d'usuariu", "Allow users to mount the following external storage" : "Permitir a los usuarios montar el siguiente almacenamientu esternu" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/ast.json b/apps/files_external/l10n/ast.json index 2464f44ca63..0e98fe5a24a 100644 --- a/apps/files_external/l10n/ast.json +++ b/apps/files_external/l10n/ast.json @@ -53,7 +53,6 @@ "Available for" : "Disponible pa", "Delete" : "Desaniciar", "Add storage" : "Amestar almacenamientu", - "Enable User External Storage" : "Habilitar almacenamientu esterno d'usuariu", "Allow users to mount the following external storage" : "Permitir a los usuarios montar el siguiente almacenamientu esternu" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/az.js b/apps/files_external/l10n/az.js index f51a743d874..700e36a4aef 100644 --- a/apps/files_external/l10n/az.js +++ b/apps/files_external/l10n/az.js @@ -60,7 +60,6 @@ OC.L10N.register( "Advanced settings" : "İrəliləmiş quraşdırmalar", "Delete" : "Sil", "Add storage" : "Deponu əlavə et", - "Enable User External Storage" : "İstifadəçi kənar deponu aktivləşdir", "Allow users to mount the following external storage" : "Göstərilən kənar deponun bərkidilməsi üçün istifadəçilərə izin ver" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/az.json b/apps/files_external/l10n/az.json index 317b7948570..6cccabb2dd6 100644 --- a/apps/files_external/l10n/az.json +++ b/apps/files_external/l10n/az.json @@ -58,7 +58,6 @@ "Advanced settings" : "İrəliləmiş quraşdırmalar", "Delete" : "Sil", "Add storage" : "Deponu əlavə et", - "Enable User External Storage" : "İstifadəçi kənar deponu aktivləşdir", "Allow users to mount the following external storage" : "Göstərilən kənar deponun bərkidilməsi üçün istifadəçilərə izin ver" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/bg_BG.js b/apps/files_external/l10n/bg_BG.js index 8a416271bce..f14b13d2a0e 100644 --- a/apps/files_external/l10n/bg_BG.js +++ b/apps/files_external/l10n/bg_BG.js @@ -62,7 +62,6 @@ OC.L10N.register( "Advanced settings" : "Разширени настройки", "Delete" : "Изтрий", "Add storage" : "Добави дисково пространство", - "Enable User External Storage" : "Разреши Потребителско Външно Дисково Пространство", "Allow users to mount the following external storage" : "Разреши на потребителите да прикачват следното външно дисково пространство" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/bg_BG.json b/apps/files_external/l10n/bg_BG.json index c9191e6d402..6cce8fd5cfa 100644 --- a/apps/files_external/l10n/bg_BG.json +++ b/apps/files_external/l10n/bg_BG.json @@ -60,7 +60,6 @@ "Advanced settings" : "Разширени настройки", "Delete" : "Изтрий", "Add storage" : "Добави дисково пространство", - "Enable User External Storage" : "Разреши Потребителско Външно Дисково Пространство", "Allow users to mount the following external storage" : "Разреши на потребителите да прикачват следното външно дисково пространство" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/bn_BD.js b/apps/files_external/l10n/bn_BD.js index 3676a1a8b51..32d40f3fb8a 100644 --- a/apps/files_external/l10n/bn_BD.js +++ b/apps/files_external/l10n/bn_BD.js @@ -34,7 +34,6 @@ OC.L10N.register( "External Storage" : "বাহ্যিক সংরক্ষণাগার", "Folder name" : "ফোলডারের নাম", "Configuration" : "কনফিগারেসন", - "Delete" : "মুছে", - "Enable User External Storage" : "ব্যবহারকারীর বাহ্যিক সংরক্ষণাগার সক্রিয় কর" + "Delete" : "মুছে" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/bn_BD.json b/apps/files_external/l10n/bn_BD.json index 5b7d07da5a2..3a2d8d4f2af 100644 --- a/apps/files_external/l10n/bn_BD.json +++ b/apps/files_external/l10n/bn_BD.json @@ -32,7 +32,6 @@ "External Storage" : "বাহ্যিক সংরক্ষণাগার", "Folder name" : "ফোলডারের নাম", "Configuration" : "কনফিগারেসন", - "Delete" : "মুছে", - "Enable User External Storage" : "ব্যবহারকারীর বাহ্যিক সংরক্ষণাগার সক্রিয় কর" + "Delete" : "মুছে" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/ca.js b/apps/files_external/l10n/ca.js index 36ea0086c1f..b14057ea420 100644 --- a/apps/files_external/l10n/ca.js +++ b/apps/files_external/l10n/ca.js @@ -69,7 +69,6 @@ OC.L10N.register( "Advanced settings" : "Configuració avançada", "Delete" : "Esborra", "Add storage" : "Afegeix emmagatzemament", - "Enable User External Storage" : "Habilita l'emmagatzemament extern d'usuari", "Allow users to mount the following external storage" : "Permet als usuaris muntar els dispositius externs següents" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/ca.json b/apps/files_external/l10n/ca.json index ffbacca550f..cce51970c18 100644 --- a/apps/files_external/l10n/ca.json +++ b/apps/files_external/l10n/ca.json @@ -67,7 +67,6 @@ "Advanced settings" : "Configuració avançada", "Delete" : "Esborra", "Add storage" : "Afegeix emmagatzemament", - "Enable User External Storage" : "Habilita l'emmagatzemament extern d'usuari", "Allow users to mount the following external storage" : "Permet als usuaris muntar els dispositius externs següents" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/cs_CZ.js b/apps/files_external/l10n/cs_CZ.js index f547c7e26b5..3e9a14f9998 100644 --- a/apps/files_external/l10n/cs_CZ.js +++ b/apps/files_external/l10n/cs_CZ.js @@ -16,6 +16,7 @@ OC.L10N.register( "Not permitted to use authentication mechanism \"%s\"" : "Nebylo povoleno použití ověřovacího mechanismu \"%s\"", "Unsatisfied backend parameters" : "Neuspokojivé parametry služby", "Unsatisfied authentication mechanism parameters" : "Neuspokojivé parametry ověřovacího mechanismu", + "Insufficient data: %s" : "Nedostatečná data: %s", "Personal" : "Osobní", "System" : "Systém", "Grant access" : "Povolit přístup", @@ -46,6 +47,8 @@ OC.L10N.register( "OpenStack" : "OpenStack", "Username" : "Uživatelské jméno", "Password" : "Heslo", + "Tenant name" : "Jméno vlastníka", + "Identity endpoint URL" : "Identifikační koncový bod URL", "Rackspace" : "Rackspace", "API key" : "Klíč API", "Username and password" : "Uživatelské jméno a heslo", @@ -99,7 +102,7 @@ OC.L10N.register( "Advanced settings" : "Pokročilá nastavení", "Delete" : "Smazat", "Add storage" : "Přidat úložiště", - "Enable User External Storage" : "Zapnout externí uživatelské úložiště", + "Allow users to mount external storage" : "Povolit uživatelům připojení externího úložiště", "Allow users to mount the following external storage" : "Povolit uživatelů připojit následující externí úložiště" }, "nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;"); diff --git a/apps/files_external/l10n/cs_CZ.json b/apps/files_external/l10n/cs_CZ.json index d6255e0bc7e..4c6f940666e 100644 --- a/apps/files_external/l10n/cs_CZ.json +++ b/apps/files_external/l10n/cs_CZ.json @@ -14,6 +14,7 @@ "Not permitted to use authentication mechanism \"%s\"" : "Nebylo povoleno použití ověřovacího mechanismu \"%s\"", "Unsatisfied backend parameters" : "Neuspokojivé parametry služby", "Unsatisfied authentication mechanism parameters" : "Neuspokojivé parametry ověřovacího mechanismu", + "Insufficient data: %s" : "Nedostatečná data: %s", "Personal" : "Osobní", "System" : "Systém", "Grant access" : "Povolit přístup", @@ -44,6 +45,8 @@ "OpenStack" : "OpenStack", "Username" : "Uživatelské jméno", "Password" : "Heslo", + "Tenant name" : "Jméno vlastníka", + "Identity endpoint URL" : "Identifikační koncový bod URL", "Rackspace" : "Rackspace", "API key" : "Klíč API", "Username and password" : "Uživatelské jméno a heslo", @@ -97,7 +100,7 @@ "Advanced settings" : "Pokročilá nastavení", "Delete" : "Smazat", "Add storage" : "Přidat úložiště", - "Enable User External Storage" : "Zapnout externí uživatelské úložiště", + "Allow users to mount external storage" : "Povolit uživatelům připojení externího úložiště", "Allow users to mount the following external storage" : "Povolit uživatelů připojit následující externí úložiště" },"pluralForm" :"nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;" }
\ No newline at end of file diff --git a/apps/files_external/l10n/da.js b/apps/files_external/l10n/da.js index 3d0c15e578d..ba5d572a206 100644 --- a/apps/files_external/l10n/da.js +++ b/apps/files_external/l10n/da.js @@ -101,7 +101,6 @@ OC.L10N.register( "Advanced settings" : "Avancerede indstillinger", "Delete" : "Slet", "Add storage" : "Tilføj lager", - "Enable User External Storage" : "Aktivér ekstern opbevaring for brugere", "Allow users to mount the following external storage" : "Tillad brugere at montere følgende som eksternt lager" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/da.json b/apps/files_external/l10n/da.json index 0c70ebcf77a..c819040bc74 100644 --- a/apps/files_external/l10n/da.json +++ b/apps/files_external/l10n/da.json @@ -99,7 +99,6 @@ "Advanced settings" : "Avancerede indstillinger", "Delete" : "Slet", "Add storage" : "Tilføj lager", - "Enable User External Storage" : "Aktivér ekstern opbevaring for brugere", "Allow users to mount the following external storage" : "Tillad brugere at montere følgende som eksternt lager" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/de.js b/apps/files_external/l10n/de.js index 633b499934e..a51cc52a247 100644 --- a/apps/files_external/l10n/de.js +++ b/apps/files_external/l10n/de.js @@ -87,7 +87,6 @@ OC.L10N.register( "Advanced settings" : "Erweiterte Einstellungen", "Delete" : "Löschen", "Add storage" : "Speicher hinzufügen", - "Enable User External Storage" : "Externen Speicher für Benutzer aktivieren", - "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 94a89346c5d..41ecaad2594 100644 --- a/apps/files_external/l10n/de.json +++ b/apps/files_external/l10n/de.json @@ -85,7 +85,6 @@ "Advanced settings" : "Erweiterte Einstellungen", "Delete" : "Löschen", "Add storage" : "Speicher hinzufügen", - "Enable User External Storage" : "Externen Speicher für Benutzer aktivieren", - "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 db8c77aa35c..610f737a4a8 100644 --- a/apps/files_external/l10n/de_DE.js +++ b/apps/files_external/l10n/de_DE.js @@ -70,7 +70,6 @@ OC.L10N.register( "Advanced settings" : "Erweiterte Einstellungen", "Delete" : "Löschen", "Add storage" : "Speicher hinzufügen", - "Enable User External Storage" : "Externen Speicher für Benutzer aktivieren", - "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 c3a254be26f..fa21fea8f4a 100644 --- a/apps/files_external/l10n/de_DE.json +++ b/apps/files_external/l10n/de_DE.json @@ -68,7 +68,6 @@ "Advanced settings" : "Erweiterte Einstellungen", "Delete" : "Löschen", "Add storage" : "Speicher hinzufügen", - "Enable User External Storage" : "Externen Speicher für Benutzer aktivieren", - "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/files_external/l10n/el.js b/apps/files_external/l10n/el.js index 4e62178830b..a83c241af7a 100644 --- a/apps/files_external/l10n/el.js +++ b/apps/files_external/l10n/el.js @@ -16,6 +16,7 @@ OC.L10N.register( "Not permitted to use authentication mechanism \"%s\"" : "Μη επιτρεπόμενος μηχανισμός πιστοποίησης \"%s\"", "Unsatisfied backend parameters" : "Ελλιπείς παράμετροι συστήματος", "Unsatisfied authentication mechanism parameters" : "Ελλιπείς παράμετροι μηχανισμού πιστοποίησης", + "Insufficient data: %s" : "Μη επαρκή δεδομένα: %s", "Personal" : "Προσωπικά", "System" : "Σύστημα", "Grant access" : "Παροχή πρόσβασης", @@ -101,7 +102,7 @@ OC.L10N.register( "Advanced settings" : "Ρυθμίσεις για προχωρημένους", "Delete" : "Διαγραφή", "Add storage" : "Προσθηκη αποθηκευσης", - "Enable User External Storage" : "Ενεργοποίηση Εξωτερικού Αποθηκευτικού Χώρου Χρήστη", + "Allow users to mount external storage" : "Να επιτρέπεται στους χρήστες η σύνδεση εξωτερικού χώρου", "Allow users to mount the following external storage" : "Χορήγηση άδειας στους χρήστες να συνδέσουν τα παρακάτω εξωτερικά μέσα αποθήκευσης" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/el.json b/apps/files_external/l10n/el.json index 8aa6c987225..32f223cf8c0 100644 --- a/apps/files_external/l10n/el.json +++ b/apps/files_external/l10n/el.json @@ -14,6 +14,7 @@ "Not permitted to use authentication mechanism \"%s\"" : "Μη επιτρεπόμενος μηχανισμός πιστοποίησης \"%s\"", "Unsatisfied backend parameters" : "Ελλιπείς παράμετροι συστήματος", "Unsatisfied authentication mechanism parameters" : "Ελλιπείς παράμετροι μηχανισμού πιστοποίησης", + "Insufficient data: %s" : "Μη επαρκή δεδομένα: %s", "Personal" : "Προσωπικά", "System" : "Σύστημα", "Grant access" : "Παροχή πρόσβασης", @@ -99,7 +100,7 @@ "Advanced settings" : "Ρυθμίσεις για προχωρημένους", "Delete" : "Διαγραφή", "Add storage" : "Προσθηκη αποθηκευσης", - "Enable User External Storage" : "Ενεργοποίηση Εξωτερικού Αποθηκευτικού Χώρου Χρήστη", + "Allow users to mount external storage" : "Να επιτρέπεται στους χρήστες η σύνδεση εξωτερικού χώρου", "Allow users to mount the following external storage" : "Χορήγηση άδειας στους χρήστες να συνδέσουν τα παρακάτω εξωτερικά μέσα αποθήκευσης" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/en_GB.js b/apps/files_external/l10n/en_GB.js index 444d0db1d52..9829bd3e8c7 100644 --- a/apps/files_external/l10n/en_GB.js +++ b/apps/files_external/l10n/en_GB.js @@ -70,7 +70,6 @@ OC.L10N.register( "Advanced settings" : "Advanced settings", "Delete" : "Delete", "Add storage" : "Add storage", - "Enable User External Storage" : "Enable User External Storage", "Allow users to mount the following external storage" : "Allow users to mount the following external storage" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/en_GB.json b/apps/files_external/l10n/en_GB.json index 8af92769bdf..88467528431 100644 --- a/apps/files_external/l10n/en_GB.json +++ b/apps/files_external/l10n/en_GB.json @@ -68,7 +68,6 @@ "Advanced settings" : "Advanced settings", "Delete" : "Delete", "Add storage" : "Add storage", - "Enable User External Storage" : "Enable User External Storage", "Allow users to mount the following external storage" : "Allow users to mount the following external storage" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/eo.js b/apps/files_external/l10n/eo.js index 8a8884777e6..ce3dd21c012 100644 --- a/apps/files_external/l10n/eo.js +++ b/apps/files_external/l10n/eo.js @@ -40,7 +40,6 @@ OC.L10N.register( "Available for" : "Disponebla por", "Delete" : "Forigi", "Add storage" : "Aldoni memorilon", - "Enable User External Storage" : "Kapabligi malenan memorilon de uzanto", "Allow users to mount the following external storage" : "Permesi uzantojn munti la jenajn malenajn memorilojn" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/eo.json b/apps/files_external/l10n/eo.json index 6741a31e72a..d8c620d24c2 100644 --- a/apps/files_external/l10n/eo.json +++ b/apps/files_external/l10n/eo.json @@ -38,7 +38,6 @@ "Available for" : "Disponebla por", "Delete" : "Forigi", "Add storage" : "Aldoni memorilon", - "Enable User External Storage" : "Kapabligi malenan memorilon de uzanto", "Allow users to mount the following external storage" : "Permesi uzantojn munti la jenajn malenajn memorilojn" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/es.js b/apps/files_external/l10n/es.js index 21e9476f77a..5415e8963cd 100644 --- a/apps/files_external/l10n/es.js +++ b/apps/files_external/l10n/es.js @@ -88,7 +88,6 @@ OC.L10N.register( "Advanced settings" : "Configuración avanzada", "Delete" : "Eliminar", "Add storage" : "Añadir almacenamiento", - "Enable User External Storage" : "Habilitar almacenamiento externo de usuario", "Allow users to mount the following external storage" : "Permitir a los usuarios montar el siguiente almacenamiento externo" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/es.json b/apps/files_external/l10n/es.json index 5f89e008ed5..10cbf0c974a 100644 --- a/apps/files_external/l10n/es.json +++ b/apps/files_external/l10n/es.json @@ -86,7 +86,6 @@ "Advanced settings" : "Configuración avanzada", "Delete" : "Eliminar", "Add storage" : "Añadir almacenamiento", - "Enable User External Storage" : "Habilitar almacenamiento externo de usuario", "Allow users to mount the following external storage" : "Permitir a los usuarios montar el siguiente almacenamiento externo" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/es_AR.js b/apps/files_external/l10n/es_AR.js index 383b511a75f..fd242104c8c 100644 --- a/apps/files_external/l10n/es_AR.js +++ b/apps/files_external/l10n/es_AR.js @@ -23,7 +23,6 @@ OC.L10N.register( "Folder name" : "Nombre de la carpeta", "Configuration" : "Configuración", "Delete" : "Borrar", - "Add storage" : "Añadir almacenamiento", - "Enable User External Storage" : "Habilitar almacenamiento de usuario externo" + "Add storage" : "Añadir almacenamiento" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/es_AR.json b/apps/files_external/l10n/es_AR.json index 0389f98e647..d9e91a3af47 100644 --- a/apps/files_external/l10n/es_AR.json +++ b/apps/files_external/l10n/es_AR.json @@ -21,7 +21,6 @@ "Folder name" : "Nombre de la carpeta", "Configuration" : "Configuración", "Delete" : "Borrar", - "Add storage" : "Añadir almacenamiento", - "Enable User External Storage" : "Habilitar almacenamiento de usuario externo" + "Add storage" : "Añadir almacenamiento" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/es_MX.js b/apps/files_external/l10n/es_MX.js index 574ba7443d8..9682e360a58 100644 --- a/apps/files_external/l10n/es_MX.js +++ b/apps/files_external/l10n/es_MX.js @@ -22,7 +22,6 @@ OC.L10N.register( "Folder name" : "Nombre de la carpeta", "Configuration" : "Configuración", "Delete" : "Eliminar", - "Add storage" : "Añadir almacenamiento", - "Enable User External Storage" : "Habilitar almacenamiento externo de usuario" + "Add storage" : "Añadir almacenamiento" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/es_MX.json b/apps/files_external/l10n/es_MX.json index ab4fd8153c4..81b2f408d11 100644 --- a/apps/files_external/l10n/es_MX.json +++ b/apps/files_external/l10n/es_MX.json @@ -20,7 +20,6 @@ "Folder name" : "Nombre de la carpeta", "Configuration" : "Configuración", "Delete" : "Eliminar", - "Add storage" : "Añadir almacenamiento", - "Enable User External Storage" : "Habilitar almacenamiento externo de usuario" + "Add storage" : "Añadir almacenamiento" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/et_EE.js b/apps/files_external/l10n/et_EE.js index 69ddf1a9ab2..ae66daa37a6 100644 --- a/apps/files_external/l10n/et_EE.js +++ b/apps/files_external/l10n/et_EE.js @@ -80,7 +80,6 @@ OC.L10N.register( "Advanced settings" : "Lisavalikud", "Delete" : "Kustuta", "Add storage" : "Lisa andmehoidla", - "Enable User External Storage" : "Luba kasutajatele väline salvestamine", "Allow users to mount the following external storage" : "Võimalda kasutajatel ühendada järgmist välist andmehoidlat" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/et_EE.json b/apps/files_external/l10n/et_EE.json index 3538ef2e7ad..f2cc31e46e1 100644 --- a/apps/files_external/l10n/et_EE.json +++ b/apps/files_external/l10n/et_EE.json @@ -78,7 +78,6 @@ "Advanced settings" : "Lisavalikud", "Delete" : "Kustuta", "Add storage" : "Lisa andmehoidla", - "Enable User External Storage" : "Luba kasutajatele väline salvestamine", "Allow users to mount the following external storage" : "Võimalda kasutajatel ühendada järgmist välist andmehoidlat" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/eu.js b/apps/files_external/l10n/eu.js index fd31a4b6db3..599229a92b3 100644 --- a/apps/files_external/l10n/eu.js +++ b/apps/files_external/l10n/eu.js @@ -54,7 +54,6 @@ OC.L10N.register( "Available for" : "Hauentzat eskuragarri", "Delete" : "Ezabatu", "Add storage" : "Gehitu biltegiratzea", - "Enable User External Storage" : "Gaitu erabiltzaileentzako kanpo biltegiratzea", "Allow users to mount the following external storage" : "Baimendu erabiltzaileak hurrengo kanpo biltegiratzeak muntatzen" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/eu.json b/apps/files_external/l10n/eu.json index 2270fa96d08..5a568893060 100644 --- a/apps/files_external/l10n/eu.json +++ b/apps/files_external/l10n/eu.json @@ -52,7 +52,6 @@ "Available for" : "Hauentzat eskuragarri", "Delete" : "Ezabatu", "Add storage" : "Gehitu biltegiratzea", - "Enable User External Storage" : "Gaitu erabiltzaileentzako kanpo biltegiratzea", "Allow users to mount the following external storage" : "Baimendu erabiltzaileak hurrengo kanpo biltegiratzeak muntatzen" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/fa.js b/apps/files_external/l10n/fa.js index efcb4fea048..a18f7cdcf5c 100644 --- a/apps/files_external/l10n/fa.js +++ b/apps/files_external/l10n/fa.js @@ -59,7 +59,6 @@ OC.L10N.register( "Available for" : "در دسترس برای", "Advanced settings" : "تنظیمات پیشرفته", "Delete" : "حذف", - "Add storage" : "اضافه کردن حافظه", - "Enable User External Storage" : "فعال سازی حافظه خارجی کاربر" + "Add storage" : "اضافه کردن حافظه" }, "nplurals=1; plural=0;"); diff --git a/apps/files_external/l10n/fa.json b/apps/files_external/l10n/fa.json index 9e4e3b00365..4bc16f72f54 100644 --- a/apps/files_external/l10n/fa.json +++ b/apps/files_external/l10n/fa.json @@ -57,7 +57,6 @@ "Available for" : "در دسترس برای", "Advanced settings" : "تنظیمات پیشرفته", "Delete" : "حذف", - "Add storage" : "اضافه کردن حافظه", - "Enable User External Storage" : "فعال سازی حافظه خارجی کاربر" + "Add storage" : "اضافه کردن حافظه" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/apps/files_external/l10n/fi_FI.js b/apps/files_external/l10n/fi_FI.js index 610005fa925..f91dec93310 100644 --- a/apps/files_external/l10n/fi_FI.js +++ b/apps/files_external/l10n/fi_FI.js @@ -62,6 +62,7 @@ OC.L10N.register( "Username as share" : "Käyttäjänimi jakona", "OpenStack Object Storage" : "OpenStack Object Storage", "Service name" : "Palvelun nimi", + "Request timeout (seconds)" : "Pyynnön aikakatkaisu (sekunneissa)", "<b>Note:</b> " : "<b>Huomio:</b> ", "<b>Note:</b> The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>Huomio:</b> PHP:n cURL-tuki ei ole käytössä tai sitä ei ole asennettu. Kohteen %s liittäminen ei ole mahdollista. Pyydä järjestelmän ylläpitäjää ottamaan cURL-tuki käyttöön.", "<b>Note:</b> The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>Huomio:</b> PHP:n FTP-tuki ei ole käytössä tai sitä ei ole asennettu. Kohteen %s liittäminen ei ole mahdollista. Pyydä järjestelmän ylläpitäjää ottamaan FTP-tuki käyttöön.", @@ -78,7 +79,7 @@ OC.L10N.register( "Advanced settings" : "Lisäasetukset", "Delete" : "Poista", "Add storage" : "Lisää tallennustila", - "Enable User External Storage" : "Ota käyttöön ulkopuoliset tallennuspaikat", + "Allow users to mount external storage" : "Salli käyttäjien liittää erillisiä tallennustiloja", "Allow users to mount the following external storage" : "Salli käyttäjien liittää seuraavat erilliset tallennusvälineet" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/fi_FI.json b/apps/files_external/l10n/fi_FI.json index f8961048e2f..a2033b4c578 100644 --- a/apps/files_external/l10n/fi_FI.json +++ b/apps/files_external/l10n/fi_FI.json @@ -60,6 +60,7 @@ "Username as share" : "Käyttäjänimi jakona", "OpenStack Object Storage" : "OpenStack Object Storage", "Service name" : "Palvelun nimi", + "Request timeout (seconds)" : "Pyynnön aikakatkaisu (sekunneissa)", "<b>Note:</b> " : "<b>Huomio:</b> ", "<b>Note:</b> The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>Huomio:</b> PHP:n cURL-tuki ei ole käytössä tai sitä ei ole asennettu. Kohteen %s liittäminen ei ole mahdollista. Pyydä järjestelmän ylläpitäjää ottamaan cURL-tuki käyttöön.", "<b>Note:</b> The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>Huomio:</b> PHP:n FTP-tuki ei ole käytössä tai sitä ei ole asennettu. Kohteen %s liittäminen ei ole mahdollista. Pyydä järjestelmän ylläpitäjää ottamaan FTP-tuki käyttöön.", @@ -76,7 +77,7 @@ "Advanced settings" : "Lisäasetukset", "Delete" : "Poista", "Add storage" : "Lisää tallennustila", - "Enable User External Storage" : "Ota käyttöön ulkopuoliset tallennuspaikat", + "Allow users to mount external storage" : "Salli käyttäjien liittää erillisiä tallennustiloja", "Allow users to mount the following external storage" : "Salli käyttäjien liittää seuraavat erilliset tallennusvälineet" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/fr.js b/apps/files_external/l10n/fr.js index 03ceb4ab632..1389cd1233b 100644 --- a/apps/files_external/l10n/fr.js +++ b/apps/files_external/l10n/fr.js @@ -16,6 +16,7 @@ OC.L10N.register( "Not permitted to use authentication mechanism \"%s\"" : "Non autorisé à utiliser le mécanisme d'authentification \"%s\"", "Unsatisfied backend parameters" : "Paramètres manquants pour le service", "Unsatisfied authentication mechanism parameters" : "Paramètres manquants pour la méthode d'authentification", + "Insufficient data: %s" : "Données insuffisantes : %s", "Personal" : "Personnel", "System" : "Système", "Grant access" : "Autoriser l'accès", @@ -83,7 +84,7 @@ OC.L10N.register( "Username as share" : "Nom d'utilisateur comme nom de partage", "OpenStack Object Storage" : "OpenStack Object Storage", "Service name" : "Nom du service", - "Request timeout (seconds)" : "Timeout des requêtes (en secondes)", + "Request timeout (seconds)" : "Délai d'expiration des requêtes (en secondes)", "<b>Note:</b> " : "<b>Attention :</b>", "<b>Note:</b> The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>Attention :</b> La prise en charge de cURL par PHP n'est pas activée ou installée. Le montage de %s n'est pas possible. Contactez votre administrateur système pour l'installer.", "<b>Note:</b> The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>Attention : </b> La prise en charge du FTP par PHP n'est pas activée ou installée. Le montage de %s n'est pas possible. Contactez votre administrateur système pour l'installer.", @@ -101,7 +102,7 @@ OC.L10N.register( "Advanced settings" : "Paramètres avancés", "Delete" : "Supprimer", "Add storage" : "Ajouter un support de stockage", - "Enable User External Storage" : "Autoriser les utilisateurs à ajouter des stockages externes", + "Allow users to mount external storage" : "Autoriser les utilisateurs à monter des espaces de stockage externes", "Allow users to mount the following external storage" : "Autoriser les utilisateurs à monter les stockages externes suivants" }, "nplurals=2; plural=(n > 1);"); diff --git a/apps/files_external/l10n/fr.json b/apps/files_external/l10n/fr.json index 5fbba59b929..9d078bf13fc 100644 --- a/apps/files_external/l10n/fr.json +++ b/apps/files_external/l10n/fr.json @@ -14,6 +14,7 @@ "Not permitted to use authentication mechanism \"%s\"" : "Non autorisé à utiliser le mécanisme d'authentification \"%s\"", "Unsatisfied backend parameters" : "Paramètres manquants pour le service", "Unsatisfied authentication mechanism parameters" : "Paramètres manquants pour la méthode d'authentification", + "Insufficient data: %s" : "Données insuffisantes : %s", "Personal" : "Personnel", "System" : "Système", "Grant access" : "Autoriser l'accès", @@ -81,7 +82,7 @@ "Username as share" : "Nom d'utilisateur comme nom de partage", "OpenStack Object Storage" : "OpenStack Object Storage", "Service name" : "Nom du service", - "Request timeout (seconds)" : "Timeout des requêtes (en secondes)", + "Request timeout (seconds)" : "Délai d'expiration des requêtes (en secondes)", "<b>Note:</b> " : "<b>Attention :</b>", "<b>Note:</b> The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>Attention :</b> La prise en charge de cURL par PHP n'est pas activée ou installée. Le montage de %s n'est pas possible. Contactez votre administrateur système pour l'installer.", "<b>Note:</b> The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>Attention : </b> La prise en charge du FTP par PHP n'est pas activée ou installée. Le montage de %s n'est pas possible. Contactez votre administrateur système pour l'installer.", @@ -99,7 +100,7 @@ "Advanced settings" : "Paramètres avancés", "Delete" : "Supprimer", "Add storage" : "Ajouter un support de stockage", - "Enable User External Storage" : "Autoriser les utilisateurs à ajouter des stockages externes", + "Allow users to mount external storage" : "Autoriser les utilisateurs à monter des espaces de stockage externes", "Allow users to mount the following external storage" : "Autoriser les utilisateurs à monter les stockages externes suivants" },"pluralForm" :"nplurals=2; plural=(n > 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/gl.js b/apps/files_external/l10n/gl.js index 1fa5f41d64a..5827a6ab57f 100644 --- a/apps/files_external/l10n/gl.js +++ b/apps/files_external/l10n/gl.js @@ -70,7 +70,6 @@ OC.L10N.register( "Advanced settings" : "Axustes avanzados", "Delete" : "Eliminar", "Add storage" : "Engadir almacenamento", - "Enable User External Storage" : "Activar o almacenamento externo do usuario", "Allow users to mount the following external storage" : "Permitirlle aos usuarios montar o seguinte almacenamento externo" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/gl.json b/apps/files_external/l10n/gl.json index a4cacf44faf..29dde23c329 100644 --- a/apps/files_external/l10n/gl.json +++ b/apps/files_external/l10n/gl.json @@ -68,7 +68,6 @@ "Advanced settings" : "Axustes avanzados", "Delete" : "Eliminar", "Add storage" : "Engadir almacenamento", - "Enable User External Storage" : "Activar o almacenamento externo do usuario", "Allow users to mount the following external storage" : "Permitirlle aos usuarios montar o seguinte almacenamento externo" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/he.js b/apps/files_external/l10n/he.js index 2de5539e7d1..613f2688ee4 100644 --- a/apps/files_external/l10n/he.js +++ b/apps/files_external/l10n/he.js @@ -21,7 +21,6 @@ OC.L10N.register( "External Storage" : "אחסון חיצוני", "Folder name" : "שם התיקייה", "Configuration" : "הגדרות", - "Delete" : "מחיקה", - "Enable User External Storage" : "הפעלת אחסון חיצוני למשתמשים" + "Delete" : "מחיקה" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/he.json b/apps/files_external/l10n/he.json index 4b4e289c53e..928329f1d4e 100644 --- a/apps/files_external/l10n/he.json +++ b/apps/files_external/l10n/he.json @@ -19,7 +19,6 @@ "External Storage" : "אחסון חיצוני", "Folder name" : "שם התיקייה", "Configuration" : "הגדרות", - "Delete" : "מחיקה", - "Enable User External Storage" : "הפעלת אחסון חיצוני למשתמשים" + "Delete" : "מחיקה" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/hr.js b/apps/files_external/l10n/hr.js index 651470a58fe..4ab71f76ffb 100644 --- a/apps/files_external/l10n/hr.js +++ b/apps/files_external/l10n/hr.js @@ -52,7 +52,6 @@ OC.L10N.register( "Available for" : "Dostupno za", "Delete" : "Izbrišite", "Add storage" : "Dodajte spremište", - "Enable User External Storage" : "Omogućite korisničko vanjsko spremište", "Allow users to mount the following external storage" : "Dopustite korisnicima postavljanje sljedećeg vanjskog spremišta" }, "nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;"); diff --git a/apps/files_external/l10n/hr.json b/apps/files_external/l10n/hr.json index 80722b18ca4..e8b8dcd3f61 100644 --- a/apps/files_external/l10n/hr.json +++ b/apps/files_external/l10n/hr.json @@ -50,7 +50,6 @@ "Available for" : "Dostupno za", "Delete" : "Izbrišite", "Add storage" : "Dodajte spremište", - "Enable User External Storage" : "Omogućite korisničko vanjsko spremište", "Allow users to mount the following external storage" : "Dopustite korisnicima postavljanje sljedećeg vanjskog spremišta" },"pluralForm" :"nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;" }
\ No newline at end of file diff --git a/apps/files_external/l10n/hu_HU.js b/apps/files_external/l10n/hu_HU.js index 563267f66fd..0a307f8a609 100644 --- a/apps/files_external/l10n/hu_HU.js +++ b/apps/files_external/l10n/hu_HU.js @@ -40,7 +40,6 @@ OC.L10N.register( "Configuration" : "Beállítások", "Available for" : "Elérhető számukra", "Delete" : "Törlés", - "Add storage" : "Tároló becsatolása", - "Enable User External Storage" : "Külső tárolók engedélyezése a felhasználók részére" + "Add storage" : "Tároló becsatolása" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/hu_HU.json b/apps/files_external/l10n/hu_HU.json index a3608dba7b7..4012c0eb490 100644 --- a/apps/files_external/l10n/hu_HU.json +++ b/apps/files_external/l10n/hu_HU.json @@ -38,7 +38,6 @@ "Configuration" : "Beállítások", "Available for" : "Elérhető számukra", "Delete" : "Törlés", - "Add storage" : "Tároló becsatolása", - "Enable User External Storage" : "Külső tárolók engedélyezése a felhasználók részére" + "Add storage" : "Tároló becsatolása" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/id.js b/apps/files_external/l10n/id.js index e324a70e98e..b01e13e6085 100644 --- a/apps/files_external/l10n/id.js +++ b/apps/files_external/l10n/id.js @@ -101,7 +101,6 @@ OC.L10N.register( "Advanced settings" : "Pengaturan Lanjutan", "Delete" : "Hapus", "Add storage" : "Tambahkan penyimpanan", - "Enable User External Storage" : "Aktifkan Penyimpanan Eksternal Pengguna", "Allow users to mount the following external storage" : "Izinkan pengguna untuk mengaitkan penyimpanan eksternal berikut" }, "nplurals=1; plural=0;"); diff --git a/apps/files_external/l10n/id.json b/apps/files_external/l10n/id.json index 83f81014b1e..383850199ac 100644 --- a/apps/files_external/l10n/id.json +++ b/apps/files_external/l10n/id.json @@ -99,7 +99,6 @@ "Advanced settings" : "Pengaturan Lanjutan", "Delete" : "Hapus", "Add storage" : "Tambahkan penyimpanan", - "Enable User External Storage" : "Aktifkan Penyimpanan Eksternal Pengguna", "Allow users to mount the following external storage" : "Izinkan pengguna untuk mengaitkan penyimpanan eksternal berikut" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/apps/files_external/l10n/is.js b/apps/files_external/l10n/is.js index 8af1f2ac0cf..a1edd11fc1c 100644 --- a/apps/files_external/l10n/is.js +++ b/apps/files_external/l10n/is.js @@ -17,7 +17,6 @@ OC.L10N.register( "External Storage" : "Ytri gagnageymsla", "Folder name" : "Nafn möppu", "Configuration" : "Uppsetning", - "Delete" : "Eyða", - "Enable User External Storage" : "Virkja ytra gagnasvæði notenda" + "Delete" : "Eyða" }, "nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);"); diff --git a/apps/files_external/l10n/is.json b/apps/files_external/l10n/is.json index 8abd02bdf0a..6d52ed3a896 100644 --- a/apps/files_external/l10n/is.json +++ b/apps/files_external/l10n/is.json @@ -15,7 +15,6 @@ "External Storage" : "Ytri gagnageymsla", "Folder name" : "Nafn möppu", "Configuration" : "Uppsetning", - "Delete" : "Eyða", - "Enable User External Storage" : "Virkja ytra gagnasvæði notenda" + "Delete" : "Eyða" },"pluralForm" :"nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/it.js b/apps/files_external/l10n/it.js index c39e1764909..8e126abe93b 100644 --- a/apps/files_external/l10n/it.js +++ b/apps/files_external/l10n/it.js @@ -16,6 +16,7 @@ OC.L10N.register( "Not permitted to use authentication mechanism \"%s\"" : "Utilizzo del meccanismo di autenticazione \"%s\" non permesso", "Unsatisfied backend parameters" : "Parametri del motore non soddisfatti", "Unsatisfied authentication mechanism parameters" : "Parametri del meccanismo di autenticazione non soddisfatti", + "Insufficient data: %s" : "Dati insufficienti: %s", "Personal" : "Personale", "System" : "Sistema", "Grant access" : "Concedi l'accesso", @@ -101,7 +102,7 @@ OC.L10N.register( "Advanced settings" : "Impostazioni avanzate", "Delete" : "Elimina", "Add storage" : "Aggiungi archiviazione", - "Enable User External Storage" : "Abilita la memoria esterna dell'utente", - "Allow users to mount the following external storage" : "Consenti agli utenti di montare la seguente memoria esterna" + "Allow users to mount external storage" : "Consenti agli utenti di montare archiviazioni esterne", + "Allow users to mount the following external storage" : "Consenti agli utenti di montare la seguente archiviazione esterna" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/it.json b/apps/files_external/l10n/it.json index ca3786bd3f5..e21cf5973d2 100644 --- a/apps/files_external/l10n/it.json +++ b/apps/files_external/l10n/it.json @@ -14,6 +14,7 @@ "Not permitted to use authentication mechanism \"%s\"" : "Utilizzo del meccanismo di autenticazione \"%s\" non permesso", "Unsatisfied backend parameters" : "Parametri del motore non soddisfatti", "Unsatisfied authentication mechanism parameters" : "Parametri del meccanismo di autenticazione non soddisfatti", + "Insufficient data: %s" : "Dati insufficienti: %s", "Personal" : "Personale", "System" : "Sistema", "Grant access" : "Concedi l'accesso", @@ -99,7 +100,7 @@ "Advanced settings" : "Impostazioni avanzate", "Delete" : "Elimina", "Add storage" : "Aggiungi archiviazione", - "Enable User External Storage" : "Abilita la memoria esterna dell'utente", - "Allow users to mount the following external storage" : "Consenti agli utenti di montare la seguente memoria esterna" + "Allow users to mount external storage" : "Consenti agli utenti di montare archiviazioni esterne", + "Allow users to mount the following external storage" : "Consenti agli utenti di montare la seguente archiviazione esterna" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/ja.js b/apps/files_external/l10n/ja.js index 954fff49f47..4481c7fdd2e 100644 --- a/apps/files_external/l10n/ja.js +++ b/apps/files_external/l10n/ja.js @@ -1,16 +1,28 @@ OC.L10N.register( "files_external", { + "Fetching request tokens failed. Verify that your app key and secret are correct." : "リクエストトークンの取得に失敗しました。アプリのキーとパスワードが正しいことを確認してください。", + "Fetching access tokens failed. Verify that your app key and secret are correct." : "アクセストークンの取得に失敗しました。アプリのキーとパスワードが正しいことを確認してください。", + "Please provide a valid app key and secret." : "有効なアプリのキーとパスワードを入力してください。", "Step 1 failed. Exception: %s" : "ステップ 1 の実行に失敗しました。例外: %s", "Step 2 failed. Exception: %s" : "ステップ 2 の実行に失敗しました。例外: %s", "External storage" : "外部ストレージ", "Storage with id \"%i\" not found" : "ストレージID \"%i\" が見つかりません", + "Invalid backend or authentication mechanism class" : "バックエンドまたは認証システムクラスが無効", "Invalid mount point" : "無効なマウントポイント", + "Objectstore forbidden" : "オブジェクトストアが禁じられています", "Invalid storage backend \"%s\"" : "\"%s\" のストレージバックエンドが不正", + "Not permitted to use backend \"%s\"" : "バックエンド %s を使うための権限がありません", + "Not permitted to use authentication mechanism \"%s\"" : "認証システム %s を使う権限がありません", + "Unsatisfied backend parameters" : "バックエンドのためのパラメーターが不十分です。", + "Unsatisfied authentication mechanism parameters" : "認証のためのパラメータが不十分です", + "Insufficient data: %s" : "データが不足しています: %s", "Personal" : "個人", "System" : "システム", "Grant access" : "アクセスを許可", "Access granted" : "アクセスは許可されました", + "Error configuring OAuth1" : "OAuth1 設定エラー", + "Error configuring OAuth2" : "OAuth2 設定エラー", "Generate keys" : "キーを生成", "Error generating key pair" : "キーペアの生成エラー", "Enable encryption" : "暗号化を有効に", @@ -24,6 +36,7 @@ OC.L10N.register( "Saved" : "保存されました", "Access key" : "アクセスキー", "Secret key" : "シークレットキー", + "Builtin" : "ビルトイン", "None" : "なし", "OAuth1" : "OAuth1", "App key" : "アプリキー", @@ -34,8 +47,12 @@ OC.L10N.register( "OpenStack" : "OpenStack", "Username" : "ユーザー名", "Password" : "パスワード", + "Tenant name" : "テナント名", + "Identity endpoint URL" : "認証エンドポイントURL", "Rackspace" : "Rackspace", "API key" : "APIキー", + "Username and password" : "ユーザー名とパスワード", + "Session credentials" : "セッション資格情報", "RSA public key" : "RSA公開鍵", "Public key" : "公開鍵", "Amazon S3" : "Amazon S3", @@ -66,6 +83,8 @@ OC.L10N.register( "SMB / CIFS using OC login" : "ownCloudログインを利用したSMB / CIFS", "Username as share" : "共有名", "OpenStack Object Storage" : "OpenStack ObjectStorage", + "Service name" : "サービス名", + "Request timeout (seconds)" : "リクエストがタイムアウトするまでの秒数", "<b>Note:</b> " : "<b>注意:</b> ", "<b>Note:</b> The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>注意:</b> PHPにcURLのエクステンションが入っていないか、有効ではありません。%s をマウントすることができません。このシステムの管理者にインストールをお願いしてください。", "<b>Note:</b> The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>注意:</b> PHPにFTPのエクステンションが入っていないか、有効ではありません。%s をマウントすることができません。このシステムの管理者にインストールをお願いしてください。", @@ -77,12 +96,13 @@ OC.L10N.register( "Scope" : "スコープ", "External Storage" : "外部ストレージ", "Folder name" : "フォルダー名", + "Authentication" : "認証", "Configuration" : "設定", "Available for" : "利用可能", "Advanced settings" : "詳細設定", "Delete" : "削除", "Add storage" : "ストレージを追加", - "Enable User External Storage" : "ユーザーの外部ストレージを有効にする", + "Allow users to mount external storage" : "ユーザーに外部ストレージの接続を許可する", "Allow users to mount the following external storage" : "ユーザーに以下の外部ストレージのマウントを許可する" }, "nplurals=1; plural=0;"); diff --git a/apps/files_external/l10n/ja.json b/apps/files_external/l10n/ja.json index 257f0d85251..5573c11fe84 100644 --- a/apps/files_external/l10n/ja.json +++ b/apps/files_external/l10n/ja.json @@ -1,14 +1,26 @@ { "translations": { + "Fetching request tokens failed. Verify that your app key and secret are correct." : "リクエストトークンの取得に失敗しました。アプリのキーとパスワードが正しいことを確認してください。", + "Fetching access tokens failed. Verify that your app key and secret are correct." : "アクセストークンの取得に失敗しました。アプリのキーとパスワードが正しいことを確認してください。", + "Please provide a valid app key and secret." : "有効なアプリのキーとパスワードを入力してください。", "Step 1 failed. Exception: %s" : "ステップ 1 の実行に失敗しました。例外: %s", "Step 2 failed. Exception: %s" : "ステップ 2 の実行に失敗しました。例外: %s", "External storage" : "外部ストレージ", "Storage with id \"%i\" not found" : "ストレージID \"%i\" が見つかりません", + "Invalid backend or authentication mechanism class" : "バックエンドまたは認証システムクラスが無効", "Invalid mount point" : "無効なマウントポイント", + "Objectstore forbidden" : "オブジェクトストアが禁じられています", "Invalid storage backend \"%s\"" : "\"%s\" のストレージバックエンドが不正", + "Not permitted to use backend \"%s\"" : "バックエンド %s を使うための権限がありません", + "Not permitted to use authentication mechanism \"%s\"" : "認証システム %s を使う権限がありません", + "Unsatisfied backend parameters" : "バックエンドのためのパラメーターが不十分です。", + "Unsatisfied authentication mechanism parameters" : "認証のためのパラメータが不十分です", + "Insufficient data: %s" : "データが不足しています: %s", "Personal" : "個人", "System" : "システム", "Grant access" : "アクセスを許可", "Access granted" : "アクセスは許可されました", + "Error configuring OAuth1" : "OAuth1 設定エラー", + "Error configuring OAuth2" : "OAuth2 設定エラー", "Generate keys" : "キーを生成", "Error generating key pair" : "キーペアの生成エラー", "Enable encryption" : "暗号化を有効に", @@ -22,6 +34,7 @@ "Saved" : "保存されました", "Access key" : "アクセスキー", "Secret key" : "シークレットキー", + "Builtin" : "ビルトイン", "None" : "なし", "OAuth1" : "OAuth1", "App key" : "アプリキー", @@ -32,8 +45,12 @@ "OpenStack" : "OpenStack", "Username" : "ユーザー名", "Password" : "パスワード", + "Tenant name" : "テナント名", + "Identity endpoint URL" : "認証エンドポイントURL", "Rackspace" : "Rackspace", "API key" : "APIキー", + "Username and password" : "ユーザー名とパスワード", + "Session credentials" : "セッション資格情報", "RSA public key" : "RSA公開鍵", "Public key" : "公開鍵", "Amazon S3" : "Amazon S3", @@ -64,6 +81,8 @@ "SMB / CIFS using OC login" : "ownCloudログインを利用したSMB / CIFS", "Username as share" : "共有名", "OpenStack Object Storage" : "OpenStack ObjectStorage", + "Service name" : "サービス名", + "Request timeout (seconds)" : "リクエストがタイムアウトするまでの秒数", "<b>Note:</b> " : "<b>注意:</b> ", "<b>Note:</b> The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>注意:</b> PHPにcURLのエクステンションが入っていないか、有効ではありません。%s をマウントすることができません。このシステムの管理者にインストールをお願いしてください。", "<b>Note:</b> The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>注意:</b> PHPにFTPのエクステンションが入っていないか、有効ではありません。%s をマウントすることができません。このシステムの管理者にインストールをお願いしてください。", @@ -75,12 +94,13 @@ "Scope" : "スコープ", "External Storage" : "外部ストレージ", "Folder name" : "フォルダー名", + "Authentication" : "認証", "Configuration" : "設定", "Available for" : "利用可能", "Advanced settings" : "詳細設定", "Delete" : "削除", "Add storage" : "ストレージを追加", - "Enable User External Storage" : "ユーザーの外部ストレージを有効にする", + "Allow users to mount external storage" : "ユーザーに外部ストレージの接続を許可する", "Allow users to mount the following external storage" : "ユーザーに以下の外部ストレージのマウントを許可する" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/apps/files_external/l10n/ka_GE.js b/apps/files_external/l10n/ka_GE.js index 6f38743a215..824295cb93d 100644 --- a/apps/files_external/l10n/ka_GE.js +++ b/apps/files_external/l10n/ka_GE.js @@ -22,7 +22,6 @@ OC.L10N.register( "Folder name" : "ფოლდერის სახელი", "Configuration" : "კონფიგურაცია", "Delete" : "წაშლა", - "Add storage" : "საცავის დამატება", - "Enable User External Storage" : "მომხმარებლის ექსტერნალ საცავის აქტივირება" + "Add storage" : "საცავის დამატება" }, "nplurals=1; plural=0;"); diff --git a/apps/files_external/l10n/ka_GE.json b/apps/files_external/l10n/ka_GE.json index 7ca96f6db5d..73ad2cfd0c5 100644 --- a/apps/files_external/l10n/ka_GE.json +++ b/apps/files_external/l10n/ka_GE.json @@ -20,7 +20,6 @@ "Folder name" : "ფოლდერის სახელი", "Configuration" : "კონფიგურაცია", "Delete" : "წაშლა", - "Add storage" : "საცავის დამატება", - "Enable User External Storage" : "მომხმარებლის ექსტერნალ საცავის აქტივირება" + "Add storage" : "საცავის დამატება" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/apps/files_external/l10n/ko.js b/apps/files_external/l10n/ko.js index 3faf53bf1e5..9028a3e2986 100644 --- a/apps/files_external/l10n/ko.js +++ b/apps/files_external/l10n/ko.js @@ -16,6 +16,7 @@ OC.L10N.register( "Not permitted to use authentication mechanism \"%s\"" : "인증 방식 \"%s\" 사용이 허가되지 않았음", "Unsatisfied backend parameters" : "백엔드 인자가 부족함", "Unsatisfied authentication mechanism parameters" : "인증 방식 인자가 부족함", + "Insufficient data: %s" : "충분하지 않은 데이터: %s", "Personal" : "개인", "System" : "시스템", "Grant access" : "접근 권한 부여", @@ -101,7 +102,7 @@ OC.L10N.register( "Advanced settings" : "고급 설정", "Delete" : "삭제", "Add storage" : "저장소 추가", - "Enable User External Storage" : "사용자 외부 저장소 사용", + "Allow users to mount external storage" : "사용자가 외부 저장소를 마운트하도록 허용", "Allow users to mount the following external storage" : "사용자가 다음 외부 저장소를 마운트할 수 있도록 허용" }, "nplurals=1; plural=0;"); diff --git a/apps/files_external/l10n/ko.json b/apps/files_external/l10n/ko.json index 039190cf4f9..d27fdfcae30 100644 --- a/apps/files_external/l10n/ko.json +++ b/apps/files_external/l10n/ko.json @@ -14,6 +14,7 @@ "Not permitted to use authentication mechanism \"%s\"" : "인증 방식 \"%s\" 사용이 허가되지 않았음", "Unsatisfied backend parameters" : "백엔드 인자가 부족함", "Unsatisfied authentication mechanism parameters" : "인증 방식 인자가 부족함", + "Insufficient data: %s" : "충분하지 않은 데이터: %s", "Personal" : "개인", "System" : "시스템", "Grant access" : "접근 권한 부여", @@ -99,7 +100,7 @@ "Advanced settings" : "고급 설정", "Delete" : "삭제", "Add storage" : "저장소 추가", - "Enable User External Storage" : "사용자 외부 저장소 사용", + "Allow users to mount external storage" : "사용자가 외부 저장소를 마운트하도록 허용", "Allow users to mount the following external storage" : "사용자가 다음 외부 저장소를 마운트할 수 있도록 허용" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/apps/files_external/l10n/lt_LT.js b/apps/files_external/l10n/lt_LT.js index 741d507db42..b6d334d792d 100644 --- a/apps/files_external/l10n/lt_LT.js +++ b/apps/files_external/l10n/lt_LT.js @@ -23,7 +23,6 @@ OC.L10N.register( "Folder name" : "Katalogo pavadinimas", "Configuration" : "Konfigūracija", "Delete" : "Ištrinti", - "Add storage" : "Pridėti saugyklą", - "Enable User External Storage" : "Įjungti vartotojų išorines saugyklas" + "Add storage" : "Pridėti saugyklą" }, "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_external/l10n/lt_LT.json b/apps/files_external/l10n/lt_LT.json index 152c48a1035..f1c46b145ee 100644 --- a/apps/files_external/l10n/lt_LT.json +++ b/apps/files_external/l10n/lt_LT.json @@ -21,7 +21,6 @@ "Folder name" : "Katalogo pavadinimas", "Configuration" : "Konfigūracija", "Delete" : "Ištrinti", - "Add storage" : "Pridėti saugyklą", - "Enable User External Storage" : "Įjungti vartotojų išorines saugyklas" + "Add storage" : "Pridėti saugyklą" },"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_external/l10n/lv.js b/apps/files_external/l10n/lv.js index 2f694de2249..6590706fa2a 100644 --- a/apps/files_external/l10n/lv.js +++ b/apps/files_external/l10n/lv.js @@ -5,6 +5,7 @@ OC.L10N.register( "Personal" : "Personīgi", "Grant access" : "Piešķirt pieeju", "Access granted" : "Piešķirta pieeja", + "Enable encryption" : "Ieslēgt šifrēšanu", "Saved" : "Saglabāts", "None" : "Nav", "Username" : "Lietotājvārds", @@ -21,7 +22,6 @@ OC.L10N.register( "Folder name" : "Mapes nosaukums", "Configuration" : "Konfigurācija", "Delete" : "Dzēst", - "Add storage" : "Pievienot krātuvi", - "Enable User External Storage" : "Aktivēt lietotāja ārējo krātuvi" + "Add storage" : "Pievienot krātuvi" }, "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);"); diff --git a/apps/files_external/l10n/lv.json b/apps/files_external/l10n/lv.json index 5b281307ec3..4e27db77737 100644 --- a/apps/files_external/l10n/lv.json +++ b/apps/files_external/l10n/lv.json @@ -3,6 +3,7 @@ "Personal" : "Personīgi", "Grant access" : "Piešķirt pieeju", "Access granted" : "Piešķirta pieeja", + "Enable encryption" : "Ieslēgt šifrēšanu", "Saved" : "Saglabāts", "None" : "Nav", "Username" : "Lietotājvārds", @@ -19,7 +20,6 @@ "Folder name" : "Mapes nosaukums", "Configuration" : "Konfigurācija", "Delete" : "Dzēst", - "Add storage" : "Pievienot krātuvi", - "Enable User External Storage" : "Aktivēt lietotāja ārējo krātuvi" + "Add storage" : "Pievienot krātuvi" },"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/mk.js b/apps/files_external/l10n/mk.js index 3a62a2b580b..e75f1afa620 100644 --- a/apps/files_external/l10n/mk.js +++ b/apps/files_external/l10n/mk.js @@ -22,7 +22,6 @@ OC.L10N.register( "External Storage" : "Надворешно складиште", "Folder name" : "Име на папка", "Configuration" : "Конфигурација", - "Delete" : "Избриши", - "Enable User External Storage" : "Овозможи надворешни за корисници" + "Delete" : "Избриши" }, "nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;"); diff --git a/apps/files_external/l10n/mk.json b/apps/files_external/l10n/mk.json index 9fb0994a604..ae095b46310 100644 --- a/apps/files_external/l10n/mk.json +++ b/apps/files_external/l10n/mk.json @@ -20,7 +20,6 @@ "External Storage" : "Надворешно складиште", "Folder name" : "Име на папка", "Configuration" : "Конфигурација", - "Delete" : "Избриши", - "Enable User External Storage" : "Овозможи надворешни за корисници" + "Delete" : "Избриши" },"pluralForm" :"nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;" }
\ No newline at end of file diff --git a/apps/files_external/l10n/nb_NO.js b/apps/files_external/l10n/nb_NO.js index 2057f257adc..ecafac048c0 100644 --- a/apps/files_external/l10n/nb_NO.js +++ b/apps/files_external/l10n/nb_NO.js @@ -101,7 +101,6 @@ OC.L10N.register( "Advanced settings" : "Avanserte innstillinger", "Delete" : "Slett", "Add storage" : "Legg til lagringsplass", - "Enable User External Storage" : "Aktiver ekstern lagring for bruker", "Allow users to mount the following external storage" : "Tillat brukere å koble opp følgende eksterne lagring" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/nb_NO.json b/apps/files_external/l10n/nb_NO.json index 36556fd9912..9a7a2ae6287 100644 --- a/apps/files_external/l10n/nb_NO.json +++ b/apps/files_external/l10n/nb_NO.json @@ -99,7 +99,6 @@ "Advanced settings" : "Avanserte innstillinger", "Delete" : "Slett", "Add storage" : "Legg til lagringsplass", - "Enable User External Storage" : "Aktiver ekstern lagring for bruker", "Allow users to mount the following external storage" : "Tillat brukere å koble opp følgende eksterne lagring" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/nds.js b/apps/files_external/l10n/nds.js index 717417fdc2b..f7f1da30c60 100644 --- a/apps/files_external/l10n/nds.js +++ b/apps/files_external/l10n/nds.js @@ -96,7 +96,6 @@ OC.L10N.register( "Advanced settings" : "Erweiterte Einstellungen", "Delete" : "Löschen", "Add storage" : "Speicher hinzufügen", - "Enable User External Storage" : "Externen Speicher für Nutzer aktivieren", "Allow users to mount the following external storage" : "Erlaube Benutzern folgenden externen Speicher einzuhängen" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/nds.json b/apps/files_external/l10n/nds.json index b7c196ef64c..bfadfc0c123 100644 --- a/apps/files_external/l10n/nds.json +++ b/apps/files_external/l10n/nds.json @@ -94,7 +94,6 @@ "Advanced settings" : "Erweiterte Einstellungen", "Delete" : "Löschen", "Add storage" : "Speicher hinzufügen", - "Enable User External Storage" : "Externen Speicher für Nutzer aktivieren", "Allow users to mount the following external storage" : "Erlaube Benutzern folgenden externen Speicher einzuhängen" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/nl.js b/apps/files_external/l10n/nl.js index 02661996d5e..57481ce4176 100644 --- a/apps/files_external/l10n/nl.js +++ b/apps/files_external/l10n/nl.js @@ -16,6 +16,7 @@ OC.L10N.register( "Not permitted to use authentication mechanism \"%s\"" : "Niet toegestaan om authenticatiemechanisme \"%s\" te gebruiken", "Unsatisfied backend parameters" : "Onvoldoende backend parameters", "Unsatisfied authentication mechanism parameters" : "Onvoldoende authenticatiemechanisme parameters", + "Insufficient data: %s" : "Onvoldoende gegevens: %s", "Personal" : "Persoonlijk", "System" : "Systeem", "Grant access" : "Sta toegang toe", @@ -101,7 +102,7 @@ OC.L10N.register( "Advanced settings" : "Geavanceerde instellingen", "Delete" : "Verwijder", "Add storage" : "Toevoegen opslag", - "Enable User External Storage" : "Externe opslag voor gebruikers activeren", + "Allow users to mount external storage" : "Sta gebruikers toe om een externe opslag aan te koppelen", "Allow users to mount the following external storage" : "Sta gebruikers toe de volgende externe opslag aan te koppelen" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/nl.json b/apps/files_external/l10n/nl.json index ef7f42b1f38..fc80c3bbb2c 100644 --- a/apps/files_external/l10n/nl.json +++ b/apps/files_external/l10n/nl.json @@ -14,6 +14,7 @@ "Not permitted to use authentication mechanism \"%s\"" : "Niet toegestaan om authenticatiemechanisme \"%s\" te gebruiken", "Unsatisfied backend parameters" : "Onvoldoende backend parameters", "Unsatisfied authentication mechanism parameters" : "Onvoldoende authenticatiemechanisme parameters", + "Insufficient data: %s" : "Onvoldoende gegevens: %s", "Personal" : "Persoonlijk", "System" : "Systeem", "Grant access" : "Sta toegang toe", @@ -99,7 +100,7 @@ "Advanced settings" : "Geavanceerde instellingen", "Delete" : "Verwijder", "Add storage" : "Toevoegen opslag", - "Enable User External Storage" : "Externe opslag voor gebruikers activeren", + "Allow users to mount external storage" : "Sta gebruikers toe om een externe opslag aan te koppelen", "Allow users to mount the following external storage" : "Sta gebruikers toe de volgende externe opslag aan te koppelen" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/oc.js b/apps/files_external/l10n/oc.js index b7bc419fdd7..a45aebf81ba 100644 --- a/apps/files_external/l10n/oc.js +++ b/apps/files_external/l10n/oc.js @@ -1,25 +1,42 @@ OC.L10N.register( "files_external", { + "Fetching request tokens failed. Verify that your app key and secret are correct." : "L'obtencion dels getons de requèsta a fracassat. Verificatz que vòstra clau d'aplicacion e vòstre senhal son corrèctes.", + "Fetching access tokens failed. Verify that your app key and secret are correct." : "L'obtencion dels getons d'aacès a fracassat. Verificatz que vòstra clau d'aplicacion e vòstre senhal son corrèctes.", + "Please provide a valid app key and secret." : "Provesissètz una clau d'aplicacion e un senhal valids.", "Step 1 failed. Exception: %s" : "L’etapa 1 a fracassat. Error : %s", "Step 2 failed. Exception: %s" : "L’etapa 2 a fracassat. Error : %s", "External storage" : "Emmagazinatge extèrne", "Storage with id \"%i\" not found" : "Emmagazinatge amb l'id \"%i\" pas trobat", + "Invalid backend or authentication mechanism class" : "Servici o metòde d'autentificacion pas valable", "Invalid mount point" : "Punt de montatge invalid", + "Objectstore forbidden" : "\"Objectstore\" interdich", "Invalid storage backend \"%s\"" : "Servici d'emmagazinatge invalid : \"%s\"", + "Not permitted to use backend \"%s\"" : "Pas autorizat a utilizar lo servici \"%s\"", + "Not permitted to use authentication mechanism \"%s\"" : "Pas autorizat a utilizar lo mecanisme d'autentificacion \"%s\"", + "Unsatisfied backend parameters" : "Paramètres mancants pel servici", + "Unsatisfied authentication mechanism parameters" : "Paramètres mancants pel metòde d'autentificacion", + "Insufficient data: %s" : "Donadas insufisentas : %s", "Personal" : "Personal", "System" : "Sistèma", "Grant access" : "Autorizar l'accès", "Access granted" : "Accès autorizat", + "Error configuring OAuth1" : "Error al moment de la configuracion d'OAuth1", + "Error configuring OAuth2" : "Error al moment de la configuracion d'OAuth2", "Generate keys" : "Generar de claus", "Error generating key pair" : "Error al moment de la generacion de las claus", "Enable encryption" : "Activar lo chiframent", "Enable previews" : "Activar las previsualizacions", + "Check for changes" : "Recercar las modificacions", "Never" : "Pas jamai", + "Once every direct access" : "Un còp a cada accès dirècte", + "Every time the filesystem is used" : "A cada còp que lo sistèma de fichièrs es utilizat", + "All users. Type to select user or group." : "Totes los utilizaires. Clicatz aicí per restrénher.", "(group)" : "(grop)", - "Saved" : "Salvat", + "Saved" : "Enregistrat", "Access key" : "Clau d'accès", "Secret key" : "Clau secreta", + "Builtin" : "Integrat", "None" : "Pas cap", "OAuth1" : "OAuth1", "App key" : "App key", @@ -27,9 +44,15 @@ OC.L10N.register( "OAuth2" : "OAuth2", "Client ID" : "ID Client", "Client secret" : "Secret client", + "OpenStack" : "OpenStack", "Username" : "Nom d'utilizaire", "Password" : "Senhal", + "Tenant name" : "Tenant name", + "Identity endpoint URL" : "Identity endpoint URL", + "Rackspace" : "Rackspace", "API key" : "Clau API", + "Username and password" : "Nom d'utilizaire e senhal", + "Session credentials" : "Informacions d'identificacion de session", "RSA public key" : "Clau publica RSA", "Public key" : "Clau publica", "Amazon S3" : "Amazon S3", @@ -52,6 +75,7 @@ OC.L10N.register( "Location" : "Emplaçament", "ownCloud" : "ownCloud", "SFTP" : "SFTP", + "Root" : "Raiç", "SFTP with secret key login" : "SFTP amb un identificant secret", "SMB / CIFS" : "SMB / CIFS", "Share" : "Partejar", @@ -60,6 +84,7 @@ OC.L10N.register( "Username as share" : "Nom d'utilizaire coma nom de partiment", "OpenStack Object Storage" : "OpenStack Object Storage", "Service name" : "Nom del servici", + "Request timeout (seconds)" : "Timeout de las requèstas (en segondas)", "<b>Note:</b> " : "<b>Atencion :</b>", "<b>Note:</b> The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>Atencion :</b> La presa en carga de cURL per PHP es pas activada o installada. Lo montatge de %s es pas possible. Contactatz vòstre administrator sistèma per l'installar.", "<b>Note:</b> The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>Atencion : </b> La presa en carga del FTP per PHP es pas activada o installada. Lo montatge de %s es pas possible. Contactatz vòstre administrator sistèma per l'installar.", @@ -77,7 +102,7 @@ OC.L10N.register( "Advanced settings" : "Paramètres avançats", "Delete" : "Suprimir", "Add storage" : "Apondre un supòrt d'emmagazinatge", - "Enable User External Storage" : "Autorizar los utilizaires a apondre d'emmagazinatges extèrnes", + "Allow users to mount external storage" : "Autorizar los utilizaires a montar l'espaci d'emmagazinatge extèrne", "Allow users to mount the following external storage" : "Autorizar los utilizaires a montar los emmagazinatges extèrnes seguents" }, "nplurals=2; plural=(n > 1);"); diff --git a/apps/files_external/l10n/oc.json b/apps/files_external/l10n/oc.json index 05670245634..c49326a955f 100644 --- a/apps/files_external/l10n/oc.json +++ b/apps/files_external/l10n/oc.json @@ -1,23 +1,40 @@ { "translations": { + "Fetching request tokens failed. Verify that your app key and secret are correct." : "L'obtencion dels getons de requèsta a fracassat. Verificatz que vòstra clau d'aplicacion e vòstre senhal son corrèctes.", + "Fetching access tokens failed. Verify that your app key and secret are correct." : "L'obtencion dels getons d'aacès a fracassat. Verificatz que vòstra clau d'aplicacion e vòstre senhal son corrèctes.", + "Please provide a valid app key and secret." : "Provesissètz una clau d'aplicacion e un senhal valids.", "Step 1 failed. Exception: %s" : "L’etapa 1 a fracassat. Error : %s", "Step 2 failed. Exception: %s" : "L’etapa 2 a fracassat. Error : %s", "External storage" : "Emmagazinatge extèrne", "Storage with id \"%i\" not found" : "Emmagazinatge amb l'id \"%i\" pas trobat", + "Invalid backend or authentication mechanism class" : "Servici o metòde d'autentificacion pas valable", "Invalid mount point" : "Punt de montatge invalid", + "Objectstore forbidden" : "\"Objectstore\" interdich", "Invalid storage backend \"%s\"" : "Servici d'emmagazinatge invalid : \"%s\"", + "Not permitted to use backend \"%s\"" : "Pas autorizat a utilizar lo servici \"%s\"", + "Not permitted to use authentication mechanism \"%s\"" : "Pas autorizat a utilizar lo mecanisme d'autentificacion \"%s\"", + "Unsatisfied backend parameters" : "Paramètres mancants pel servici", + "Unsatisfied authentication mechanism parameters" : "Paramètres mancants pel metòde d'autentificacion", + "Insufficient data: %s" : "Donadas insufisentas : %s", "Personal" : "Personal", "System" : "Sistèma", "Grant access" : "Autorizar l'accès", "Access granted" : "Accès autorizat", + "Error configuring OAuth1" : "Error al moment de la configuracion d'OAuth1", + "Error configuring OAuth2" : "Error al moment de la configuracion d'OAuth2", "Generate keys" : "Generar de claus", "Error generating key pair" : "Error al moment de la generacion de las claus", "Enable encryption" : "Activar lo chiframent", "Enable previews" : "Activar las previsualizacions", + "Check for changes" : "Recercar las modificacions", "Never" : "Pas jamai", + "Once every direct access" : "Un còp a cada accès dirècte", + "Every time the filesystem is used" : "A cada còp que lo sistèma de fichièrs es utilizat", + "All users. Type to select user or group." : "Totes los utilizaires. Clicatz aicí per restrénher.", "(group)" : "(grop)", - "Saved" : "Salvat", + "Saved" : "Enregistrat", "Access key" : "Clau d'accès", "Secret key" : "Clau secreta", + "Builtin" : "Integrat", "None" : "Pas cap", "OAuth1" : "OAuth1", "App key" : "App key", @@ -25,9 +42,15 @@ "OAuth2" : "OAuth2", "Client ID" : "ID Client", "Client secret" : "Secret client", + "OpenStack" : "OpenStack", "Username" : "Nom d'utilizaire", "Password" : "Senhal", + "Tenant name" : "Tenant name", + "Identity endpoint URL" : "Identity endpoint URL", + "Rackspace" : "Rackspace", "API key" : "Clau API", + "Username and password" : "Nom d'utilizaire e senhal", + "Session credentials" : "Informacions d'identificacion de session", "RSA public key" : "Clau publica RSA", "Public key" : "Clau publica", "Amazon S3" : "Amazon S3", @@ -50,6 +73,7 @@ "Location" : "Emplaçament", "ownCloud" : "ownCloud", "SFTP" : "SFTP", + "Root" : "Raiç", "SFTP with secret key login" : "SFTP amb un identificant secret", "SMB / CIFS" : "SMB / CIFS", "Share" : "Partejar", @@ -58,6 +82,7 @@ "Username as share" : "Nom d'utilizaire coma nom de partiment", "OpenStack Object Storage" : "OpenStack Object Storage", "Service name" : "Nom del servici", + "Request timeout (seconds)" : "Timeout de las requèstas (en segondas)", "<b>Note:</b> " : "<b>Atencion :</b>", "<b>Note:</b> The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>Atencion :</b> La presa en carga de cURL per PHP es pas activada o installada. Lo montatge de %s es pas possible. Contactatz vòstre administrator sistèma per l'installar.", "<b>Note:</b> The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>Atencion : </b> La presa en carga del FTP per PHP es pas activada o installada. Lo montatge de %s es pas possible. Contactatz vòstre administrator sistèma per l'installar.", @@ -75,7 +100,7 @@ "Advanced settings" : "Paramètres avançats", "Delete" : "Suprimir", "Add storage" : "Apondre un supòrt d'emmagazinatge", - "Enable User External Storage" : "Autorizar los utilizaires a apondre d'emmagazinatges extèrnes", + "Allow users to mount external storage" : "Autorizar los utilizaires a montar l'espaci d'emmagazinatge extèrne", "Allow users to mount the following external storage" : "Autorizar los utilizaires a montar los emmagazinatges extèrnes seguents" },"pluralForm" :"nplurals=2; plural=(n > 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/pl.js b/apps/files_external/l10n/pl.js index ac24a2b9006..1f7cc6b1979 100644 --- a/apps/files_external/l10n/pl.js +++ b/apps/files_external/l10n/pl.js @@ -70,7 +70,6 @@ OC.L10N.register( "Advanced settings" : "Ustawienia zaawansowane", "Delete" : "Usuń", "Add storage" : "Dodaj zasoby dyskowe", - "Enable User External Storage" : "Włącz zewnętrzne zasoby dyskowe użytkownika", "Allow users to mount the following external storage" : "Pozwól użytkownikom montować następujące zewnętrzne zasoby dyskowe" }, "nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"); diff --git a/apps/files_external/l10n/pl.json b/apps/files_external/l10n/pl.json index 750e7384d68..5b5059a5d18 100644 --- a/apps/files_external/l10n/pl.json +++ b/apps/files_external/l10n/pl.json @@ -68,7 +68,6 @@ "Advanced settings" : "Ustawienia zaawansowane", "Delete" : "Usuń", "Add storage" : "Dodaj zasoby dyskowe", - "Enable User External Storage" : "Włącz zewnętrzne zasoby dyskowe użytkownika", "Allow users to mount the following external storage" : "Pozwól użytkownikom montować następujące zewnętrzne zasoby dyskowe" },"pluralForm" :"nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/pt_BR.js b/apps/files_external/l10n/pt_BR.js index 3d392a688ee..92bc16355d3 100644 --- a/apps/files_external/l10n/pt_BR.js +++ b/apps/files_external/l10n/pt_BR.js @@ -16,6 +16,7 @@ OC.L10N.register( "Not permitted to use authentication mechanism \"%s\"" : "Não é permitido usar o mecanismo de autenticação \"%s\"", "Unsatisfied backend parameters" : "Parâmetros de back-end não-atendidos", "Unsatisfied authentication mechanism parameters" : "Parâmetros de mecanismos de autenticação não satisfeitos", + "Insufficient data: %s" : "Dados insuficientes: %s", "Personal" : "Pessoal", "System" : "Sistema", "Grant access" : "Permitir acesso", @@ -101,7 +102,7 @@ OC.L10N.register( "Advanced settings" : "Configurações avançadas", "Delete" : "Excluir", "Add storage" : "Adicionar Armazenamento", - "Enable User External Storage" : "Habilitar Armazenamento Externo do Usuário", + "Allow users to mount external storage" : "Permitir que usuários montem armazenamento externo", "Allow users to mount the following external storage" : "Permitir que usuários montem o seguinte armazenamento externo" }, "nplurals=2; plural=(n > 1);"); diff --git a/apps/files_external/l10n/pt_BR.json b/apps/files_external/l10n/pt_BR.json index 9289ac7f388..bb6e0a96cff 100644 --- a/apps/files_external/l10n/pt_BR.json +++ b/apps/files_external/l10n/pt_BR.json @@ -14,6 +14,7 @@ "Not permitted to use authentication mechanism \"%s\"" : "Não é permitido usar o mecanismo de autenticação \"%s\"", "Unsatisfied backend parameters" : "Parâmetros de back-end não-atendidos", "Unsatisfied authentication mechanism parameters" : "Parâmetros de mecanismos de autenticação não satisfeitos", + "Insufficient data: %s" : "Dados insuficientes: %s", "Personal" : "Pessoal", "System" : "Sistema", "Grant access" : "Permitir acesso", @@ -99,7 +100,7 @@ "Advanced settings" : "Configurações avançadas", "Delete" : "Excluir", "Add storage" : "Adicionar Armazenamento", - "Enable User External Storage" : "Habilitar Armazenamento Externo do Usuário", + "Allow users to mount external storage" : "Permitir que usuários montem armazenamento externo", "Allow users to mount the following external storage" : "Permitir que usuários montem o seguinte armazenamento externo" },"pluralForm" :"nplurals=2; plural=(n > 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/pt_PT.js b/apps/files_external/l10n/pt_PT.js index 6ea55871262..4e8b3245e66 100644 --- a/apps/files_external/l10n/pt_PT.js +++ b/apps/files_external/l10n/pt_PT.js @@ -8,9 +8,13 @@ OC.L10N.register( "Step 2 failed. Exception: %s" : "Passo 2 falhou. Exceção: %s", "External storage" : "Armazenamento Externo", "Storage with id \"%i\" not found" : "Não foi encontrado o armazenamento com a id. \"%i\"", + "Invalid backend or authentication mechanism class" : "Parâmetros do mecanismo de autenticação inválidos", "Invalid mount point" : "Ponto de montagem inválido", "Invalid storage backend \"%s\"" : "Backend de armazenamento inválido \"%s\"", + "Not permitted to use backend \"%s\"" : "Não é permitido utilizar a interface \"%s\"", + "Not permitted to use authentication mechanism \"%s\"" : "Não é permitido utilizar o mecanismo de autenticação \"%s\"", "Unsatisfied authentication mechanism parameters" : "Parâmetros do mecanismo de autenticação inválidos", + "Insufficient data: %s" : "Dados insuficientes: %s", "Personal" : "Pessoal", "System" : "Sistema", "Grant access" : "Conceder acesso", @@ -43,6 +47,7 @@ OC.L10N.register( "API key" : "Chave API", "Username and password" : "Nome de utilizador e palavra-passe", "Session credentials" : "Credenciais da sessão", + "RSA public key" : "Chave pública RSA", "Public key" : "Chave pública", "Amazon S3" : "Amazon S3", "Bucket" : "Bucket", @@ -72,6 +77,7 @@ OC.L10N.register( "Username as share" : "Nome de utilizador como partilha", "OpenStack Object Storage" : "Armazenamento de Objetos OpenStack", "Service name" : "Nome do serviço", + "Request timeout (seconds)" : "Pedido expira (segundos)", "<b>Note:</b> " : "<b>Nota:</b> ", "<b>Note:</b> The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>Aviso:</b> O suporte cURL no PHP não está activo ou instalado. Não é possível montar %s. Peça ao seu administrador para instalar.", "<b>Note:</b> The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>Aviso:</b> O suporte FTP no PHP não está activo ou instalado. Não é possível montar %s. Peça ao seu administrador para instalar.", @@ -89,7 +95,6 @@ OC.L10N.register( "Advanced settings" : "Definições avançadas", "Delete" : "Apagar", "Add storage" : "Adicionar armazenamento", - "Enable User External Storage" : "Ativar Armazenamento Externo para o Utilizador", "Allow users to mount the following external storage" : "Permitir que os utilizadores montem o seguinte armazenamento externo" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/pt_PT.json b/apps/files_external/l10n/pt_PT.json index 8711356815f..51333429106 100644 --- a/apps/files_external/l10n/pt_PT.json +++ b/apps/files_external/l10n/pt_PT.json @@ -6,9 +6,13 @@ "Step 2 failed. Exception: %s" : "Passo 2 falhou. Exceção: %s", "External storage" : "Armazenamento Externo", "Storage with id \"%i\" not found" : "Não foi encontrado o armazenamento com a id. \"%i\"", + "Invalid backend or authentication mechanism class" : "Parâmetros do mecanismo de autenticação inválidos", "Invalid mount point" : "Ponto de montagem inválido", "Invalid storage backend \"%s\"" : "Backend de armazenamento inválido \"%s\"", + "Not permitted to use backend \"%s\"" : "Não é permitido utilizar a interface \"%s\"", + "Not permitted to use authentication mechanism \"%s\"" : "Não é permitido utilizar o mecanismo de autenticação \"%s\"", "Unsatisfied authentication mechanism parameters" : "Parâmetros do mecanismo de autenticação inválidos", + "Insufficient data: %s" : "Dados insuficientes: %s", "Personal" : "Pessoal", "System" : "Sistema", "Grant access" : "Conceder acesso", @@ -41,6 +45,7 @@ "API key" : "Chave API", "Username and password" : "Nome de utilizador e palavra-passe", "Session credentials" : "Credenciais da sessão", + "RSA public key" : "Chave pública RSA", "Public key" : "Chave pública", "Amazon S3" : "Amazon S3", "Bucket" : "Bucket", @@ -70,6 +75,7 @@ "Username as share" : "Nome de utilizador como partilha", "OpenStack Object Storage" : "Armazenamento de Objetos OpenStack", "Service name" : "Nome do serviço", + "Request timeout (seconds)" : "Pedido expira (segundos)", "<b>Note:</b> " : "<b>Nota:</b> ", "<b>Note:</b> The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>Aviso:</b> O suporte cURL no PHP não está activo ou instalado. Não é possível montar %s. Peça ao seu administrador para instalar.", "<b>Note:</b> The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>Aviso:</b> O suporte FTP no PHP não está activo ou instalado. Não é possível montar %s. Peça ao seu administrador para instalar.", @@ -87,7 +93,6 @@ "Advanced settings" : "Definições avançadas", "Delete" : "Apagar", "Add storage" : "Adicionar armazenamento", - "Enable User External Storage" : "Ativar Armazenamento Externo para o Utilizador", "Allow users to mount the following external storage" : "Permitir que os utilizadores montem o seguinte armazenamento externo" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/ro.js b/apps/files_external/l10n/ro.js index 89f07797d96..d8ba040824c 100644 --- a/apps/files_external/l10n/ro.js +++ b/apps/files_external/l10n/ro.js @@ -31,7 +31,6 @@ OC.L10N.register( "Configuration" : "Configurație", "Delete" : "Șterge", "Add storage" : "Adauga stocare", - "Enable User External Storage" : "Permite stocare externă pentru utilizatori", "Allow users to mount the following external storage" : "Permite utilizatorilor să monteze următoarea unitate de stocare" }, "nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));"); diff --git a/apps/files_external/l10n/ro.json b/apps/files_external/l10n/ro.json index 912e6d99b9e..cbe2826def4 100644 --- a/apps/files_external/l10n/ro.json +++ b/apps/files_external/l10n/ro.json @@ -29,7 +29,6 @@ "Configuration" : "Configurație", "Delete" : "Șterge", "Add storage" : "Adauga stocare", - "Enable User External Storage" : "Permite stocare externă pentru utilizatori", "Allow users to mount the following external storage" : "Permite utilizatorilor să monteze următoarea unitate de stocare" },"pluralForm" :"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));" }
\ No newline at end of file diff --git a/apps/files_external/l10n/ru.js b/apps/files_external/l10n/ru.js index 7e4bfc18730..5550ea780ab 100644 --- a/apps/files_external/l10n/ru.js +++ b/apps/files_external/l10n/ru.js @@ -101,7 +101,6 @@ OC.L10N.register( "Advanced settings" : "Расширенные настройки", "Delete" : "Удалить", "Add storage" : "Добавить хранилище", - "Enable User External Storage" : "Включить пользовательские внешние хранилища", "Allow users to mount the following external storage" : "Разрешить пользователям монтировать следующие сервисы хранения данных" }, "nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);"); diff --git a/apps/files_external/l10n/ru.json b/apps/files_external/l10n/ru.json index 50754b309ec..52792a3f09a 100644 --- a/apps/files_external/l10n/ru.json +++ b/apps/files_external/l10n/ru.json @@ -99,7 +99,6 @@ "Advanced settings" : "Расширенные настройки", "Delete" : "Удалить", "Add storage" : "Добавить хранилище", - "Enable User External Storage" : "Включить пользовательские внешние хранилища", "Allow users to mount the following external storage" : "Разрешить пользователям монтировать следующие сервисы хранения данных" },"pluralForm" :"nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/si_LK.js b/apps/files_external/l10n/si_LK.js index 80a6026ad75..82b68af82eb 100644 --- a/apps/files_external/l10n/si_LK.js +++ b/apps/files_external/l10n/si_LK.js @@ -18,7 +18,6 @@ OC.L10N.register( "External Storage" : "භාහිර ගබඩාව", "Folder name" : "ෆොල්ඩරයේ නම", "Configuration" : "වින්යාසය", - "Delete" : "මකා දමන්න", - "Enable User External Storage" : "පරිශීලක භාහිර ගබඩාවන් සක්රිය කරන්න" + "Delete" : "මකා දමන්න" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/si_LK.json b/apps/files_external/l10n/si_LK.json index bc3a9ee11db..2150ac0f9b2 100644 --- a/apps/files_external/l10n/si_LK.json +++ b/apps/files_external/l10n/si_LK.json @@ -16,7 +16,6 @@ "External Storage" : "භාහිර ගබඩාව", "Folder name" : "ෆොල්ඩරයේ නම", "Configuration" : "වින්යාසය", - "Delete" : "මකා දමන්න", - "Enable User External Storage" : "පරිශීලක භාහිර ගබඩාවන් සක්රිය කරන්න" + "Delete" : "මකා දමන්න" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/sk_SK.js b/apps/files_external/l10n/sk_SK.js index 2f9732961fb..41f9c866196 100644 --- a/apps/files_external/l10n/sk_SK.js +++ b/apps/files_external/l10n/sk_SK.js @@ -100,7 +100,6 @@ OC.L10N.register( "Advanced settings" : "Rozšírené nastavenia", "Delete" : "Zmazať", "Add storage" : "Pridať úložisko", - "Enable User External Storage" : "Povoliť externé úložisko", "Allow users to mount the following external storage" : "Povoliť používateľom pripojiť tieto externé úložiská" }, "nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;"); diff --git a/apps/files_external/l10n/sk_SK.json b/apps/files_external/l10n/sk_SK.json index b2b21ffe1bb..4072136fa53 100644 --- a/apps/files_external/l10n/sk_SK.json +++ b/apps/files_external/l10n/sk_SK.json @@ -98,7 +98,6 @@ "Advanced settings" : "Rozšírené nastavenia", "Delete" : "Zmazať", "Add storage" : "Pridať úložisko", - "Enable User External Storage" : "Povoliť externé úložisko", "Allow users to mount the following external storage" : "Povoliť používateľom pripojiť tieto externé úložiská" },"pluralForm" :"nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;" }
\ No newline at end of file diff --git a/apps/files_external/l10n/sl.js b/apps/files_external/l10n/sl.js index c971920298a..f9513a5f11c 100644 --- a/apps/files_external/l10n/sl.js +++ b/apps/files_external/l10n/sl.js @@ -70,7 +70,6 @@ OC.L10N.register( "Advanced settings" : "Napredne nastavitve", "Delete" : "Izbriši", "Add storage" : "Dodaj shrambo", - "Enable User External Storage" : "Omogoči zunanjo uporabniško podatkovno shrambo", "Allow users to mount the following external storage" : "Dovoli uporabnikom priklapljanje navedenih zunanjih shramb." }, "nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);"); diff --git a/apps/files_external/l10n/sl.json b/apps/files_external/l10n/sl.json index 1a8df6097d8..ca97f27b234 100644 --- a/apps/files_external/l10n/sl.json +++ b/apps/files_external/l10n/sl.json @@ -68,7 +68,6 @@ "Advanced settings" : "Napredne nastavitve", "Delete" : "Izbriši", "Add storage" : "Dodaj shrambo", - "Enable User External Storage" : "Omogoči zunanjo uporabniško podatkovno shrambo", "Allow users to mount the following external storage" : "Dovoli uporabnikom priklapljanje navedenih zunanjih shramb." },"pluralForm" :"nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/sq.js b/apps/files_external/l10n/sq.js index e61b50257ce..f8e5c5a27dc 100644 --- a/apps/files_external/l10n/sq.js +++ b/apps/files_external/l10n/sq.js @@ -16,6 +16,7 @@ OC.L10N.register( "Not permitted to use authentication mechanism \"%s\"" : "S’i lejohet të përdorë mekanizmin e mirëfilltësimit \"%s\"", "Unsatisfied backend parameters" : "Parametra mekanizmi shërbimi të paplotësuar", "Unsatisfied authentication mechanism parameters" : "Parametra mekanizmi mirëfilltësimi të papërmbushur", + "Insufficient data: %s" : "Të dhëna të pamjaftueshme: %s", "Personal" : "Personale", "System" : "Sistem", "Grant access" : "Akordoji hyrje", @@ -58,10 +59,10 @@ OC.L10N.register( "Port" : "Portë", "Region" : "Rajon", "Enable SSL" : "Aktivizo SSL-në", - "Enable Path Style" : "Aktivizon Stile Shtegu", + "Enable Path Style" : "Aktivizo Stile Shtegu", "WebDAV" : "WebDAV", "URL" : "URL", - "Remote subfolder" : "Nëndosje e largët", + "Remote subfolder" : "Nëndosje e largët", "Secure https://" : "https:// e sigurt", "Dropbox" : "Dropbox", "FTP" : "FTP", @@ -69,7 +70,7 @@ OC.L10N.register( "Secure ftps://" : "ftps:// e sigurt", "Google Drive" : "Google Drive", "Local" : "Vendore", - "Location" : "Vendndodhja", + "Location" : "Vendndodhje", "ownCloud" : "ownCloud", "SFTP" : "SFTP", "Root" : "Rrënjë", @@ -87,7 +88,7 @@ OC.L10N.register( "<b>Note:</b> The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>Shënim:</b> S’është aktivizuar ose instaluar mbulimi i FTP-së në PHP. Montimi i %s s’është i mundur. Ju lutemi, kërkojini përgjegjësit të sistemit tuaj ta instalojë.", "<b>Note:</b> \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>Shënim:</b> S’është instaluar \"%s\". Montimi i %s s’është i mundur. Ju lutemi, kërkojini përgjegjësit të sistemit tuaj ta instalojë.", "No external storage configured" : "Pa depozita të jashtme të formësuara", - "You can add external storages in the personal settings" : "Depozita të jashmte mund të shtoni që prej rregullimeve personale", + "You can add external storages in the personal settings" : "Depozita të jashtme mund të shtoni që prej rregullimeve personale", "Name" : "Emër", "Storage type" : "Lloj depozite", "Scope" : "Shtrirje", @@ -95,11 +96,11 @@ OC.L10N.register( "Folder name" : "Emër dosjeje", "Authentication" : "Mirëfilltësim", "Configuration" : "Formësim", - "Available for" : "I gatshëm për", + "Available for" : "E gatshme për", "Advanced settings" : "Rregullime të mëtejshme", "Delete" : "Fshije", "Add storage" : "Shtoni depozitë", - "Enable User External Storage" : "Aktivizo Depozita të Jashtme Përdoruesi", + "Allow users to mount external storage" : "Lejoju përdoruesve të montojnë depozita të jashtme", "Allow users to mount the following external storage" : "Lejoju përdoruesve të montojnë depozitën e jashtme vijuese" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/sq.json b/apps/files_external/l10n/sq.json index 6c2d60c87a1..0da8e9406bb 100644 --- a/apps/files_external/l10n/sq.json +++ b/apps/files_external/l10n/sq.json @@ -14,6 +14,7 @@ "Not permitted to use authentication mechanism \"%s\"" : "S’i lejohet të përdorë mekanizmin e mirëfilltësimit \"%s\"", "Unsatisfied backend parameters" : "Parametra mekanizmi shërbimi të paplotësuar", "Unsatisfied authentication mechanism parameters" : "Parametra mekanizmi mirëfilltësimi të papërmbushur", + "Insufficient data: %s" : "Të dhëna të pamjaftueshme: %s", "Personal" : "Personale", "System" : "Sistem", "Grant access" : "Akordoji hyrje", @@ -56,10 +57,10 @@ "Port" : "Portë", "Region" : "Rajon", "Enable SSL" : "Aktivizo SSL-në", - "Enable Path Style" : "Aktivizon Stile Shtegu", + "Enable Path Style" : "Aktivizo Stile Shtegu", "WebDAV" : "WebDAV", "URL" : "URL", - "Remote subfolder" : "Nëndosje e largët", + "Remote subfolder" : "Nëndosje e largët", "Secure https://" : "https:// e sigurt", "Dropbox" : "Dropbox", "FTP" : "FTP", @@ -67,7 +68,7 @@ "Secure ftps://" : "ftps:// e sigurt", "Google Drive" : "Google Drive", "Local" : "Vendore", - "Location" : "Vendndodhja", + "Location" : "Vendndodhje", "ownCloud" : "ownCloud", "SFTP" : "SFTP", "Root" : "Rrënjë", @@ -85,7 +86,7 @@ "<b>Note:</b> The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>Shënim:</b> S’është aktivizuar ose instaluar mbulimi i FTP-së në PHP. Montimi i %s s’është i mundur. Ju lutemi, kërkojini përgjegjësit të sistemit tuaj ta instalojë.", "<b>Note:</b> \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>Shënim:</b> S’është instaluar \"%s\". Montimi i %s s’është i mundur. Ju lutemi, kërkojini përgjegjësit të sistemit tuaj ta instalojë.", "No external storage configured" : "Pa depozita të jashtme të formësuara", - "You can add external storages in the personal settings" : "Depozita të jashmte mund të shtoni që prej rregullimeve personale", + "You can add external storages in the personal settings" : "Depozita të jashtme mund të shtoni që prej rregullimeve personale", "Name" : "Emër", "Storage type" : "Lloj depozite", "Scope" : "Shtrirje", @@ -93,11 +94,11 @@ "Folder name" : "Emër dosjeje", "Authentication" : "Mirëfilltësim", "Configuration" : "Formësim", - "Available for" : "I gatshëm për", + "Available for" : "E gatshme për", "Advanced settings" : "Rregullime të mëtejshme", "Delete" : "Fshije", "Add storage" : "Shtoni depozitë", - "Enable User External Storage" : "Aktivizo Depozita të Jashtme Përdoruesi", + "Allow users to mount external storage" : "Lejoju përdoruesve të montojnë depozita të jashtme", "Allow users to mount the following external storage" : "Lejoju përdoruesve të montojnë depozitën e jashtme vijuese" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/sr.js b/apps/files_external/l10n/sr.js index 633bfbcb423..02596d8ab22 100644 --- a/apps/files_external/l10n/sr.js +++ b/apps/files_external/l10n/sr.js @@ -69,7 +69,6 @@ OC.L10N.register( "Advanced settings" : "Напредне поставке", "Delete" : "Обриши", "Add storage" : "Додај складиште", - "Enable User External Storage" : "Укључи корисничко спољашње складиште", "Allow users to mount the following external storage" : "Дозволи корисницима да монтирају следећа спољашња складишта" }, "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"); diff --git a/apps/files_external/l10n/sr.json b/apps/files_external/l10n/sr.json index 820bec758df..f1c12eeb0f7 100644 --- a/apps/files_external/l10n/sr.json +++ b/apps/files_external/l10n/sr.json @@ -67,7 +67,6 @@ "Advanced settings" : "Напредне поставке", "Delete" : "Обриши", "Add storage" : "Додај складиште", - "Enable User External Storage" : "Укључи корисничко спољашње складиште", "Allow users to mount the following external storage" : "Дозволи корисницима да монтирају следећа спољашња складишта" },"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/sr@latin.js b/apps/files_external/l10n/sr@latin.js index 0d1c69f4b75..880a33c1614 100644 --- a/apps/files_external/l10n/sr@latin.js +++ b/apps/files_external/l10n/sr@latin.js @@ -50,7 +50,6 @@ OC.L10N.register( "Available for" : "Dostupno za", "Delete" : "Obriši", "Add storage" : "Dodaj skladište", - "Enable User External Storage" : "Omogući korisničko spoljašnje skladište", "Allow users to mount the following external storage" : "Omogući korisnicima da namontiraju sledeće spoljašnje skladište" }, "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"); diff --git a/apps/files_external/l10n/sr@latin.json b/apps/files_external/l10n/sr@latin.json index 747a9f1082d..760100867eb 100644 --- a/apps/files_external/l10n/sr@latin.json +++ b/apps/files_external/l10n/sr@latin.json @@ -48,7 +48,6 @@ "Available for" : "Dostupno za", "Delete" : "Obriši", "Add storage" : "Dodaj skladište", - "Enable User External Storage" : "Omogući korisničko spoljašnje skladište", "Allow users to mount the following external storage" : "Omogući korisnicima da namontiraju sledeće spoljašnje skladište" },"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/sv.js b/apps/files_external/l10n/sv.js index 2defbf76c8c..09786533e87 100644 --- a/apps/files_external/l10n/sv.js +++ b/apps/files_external/l10n/sv.js @@ -55,7 +55,6 @@ OC.L10N.register( "Available for" : "Tillgänglig för", "Delete" : "Radera", "Add storage" : "Lägg till lagring", - "Enable User External Storage" : "Aktivera extern lagring för användare", "Allow users to mount the following external storage" : "Tillåt användare att montera följande extern lagring" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/sv.json b/apps/files_external/l10n/sv.json index ec8b7ef37fb..ddb7439cb8d 100644 --- a/apps/files_external/l10n/sv.json +++ b/apps/files_external/l10n/sv.json @@ -53,7 +53,6 @@ "Available for" : "Tillgänglig för", "Delete" : "Radera", "Add storage" : "Lägg till lagring", - "Enable User External Storage" : "Aktivera extern lagring för användare", "Allow users to mount the following external storage" : "Tillåt användare att montera följande extern lagring" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/ta_LK.js b/apps/files_external/l10n/ta_LK.js index 382d5e943a1..8ab0f6d513c 100644 --- a/apps/files_external/l10n/ta_LK.js +++ b/apps/files_external/l10n/ta_LK.js @@ -18,7 +18,6 @@ OC.L10N.register( "External Storage" : "வெளி சேமிப்பு", "Folder name" : "கோப்புறை பெயர்", "Configuration" : "தகவமைப்பு", - "Delete" : "நீக்குக", - "Enable User External Storage" : "பயனாளர் வெளி சேமிப்பை இயலுமைப்படுத்துக" + "Delete" : "நீக்குக" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_external/l10n/ta_LK.json b/apps/files_external/l10n/ta_LK.json index c838cbe0173..dd1c1003728 100644 --- a/apps/files_external/l10n/ta_LK.json +++ b/apps/files_external/l10n/ta_LK.json @@ -16,7 +16,6 @@ "External Storage" : "வெளி சேமிப்பு", "Folder name" : "கோப்புறை பெயர்", "Configuration" : "தகவமைப்பு", - "Delete" : "நீக்குக", - "Enable User External Storage" : "பயனாளர் வெளி சேமிப்பை இயலுமைப்படுத்துக" + "Delete" : "நீக்குக" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/th_TH.js b/apps/files_external/l10n/th_TH.js index 9879265a709..55611a5531d 100644 --- a/apps/files_external/l10n/th_TH.js +++ b/apps/files_external/l10n/th_TH.js @@ -16,6 +16,7 @@ OC.L10N.register( "Not permitted to use authentication mechanism \"%s\"" : "ไม่อนุญาตให้ตรวจสอบการรับรองความถูกต้อง \"%s\"", "Unsatisfied backend parameters" : "พารามิเตอร์แบ็กเอนด์ไม่ได้รับอนุญาต", "Unsatisfied authentication mechanism parameters" : "การรับรองความถูกต้องไม่เพียงพอ", + "Insufficient data: %s" : "ข้อมูลไม่เพียงพอ: %s", "Personal" : "ส่วนตัว", "System" : "ระบบ", "Grant access" : "อนุญาตให้เข้าถึงได้", @@ -101,7 +102,7 @@ OC.L10N.register( "Advanced settings" : "ตั้งค่าขั้นสูง", "Delete" : "ลบ", "Add storage" : "เพิ่มพื้นที่จัดเก็บข้อมูล", - "Enable User External Storage" : "เปิดให้มีการใช้พื้นที่จัดเก็บข้อมูลของผู้ใช้งานจากภายนอกได้", + "Allow users to mount external storage" : "อนุญาตให้ผู้ใช้ติดตั้งการจัดเก็บข้อมูลภายนอก", "Allow users to mount the following external storage" : "อนุญาตให้ผู้ใช้ติดตั้งจัดเก็บข้อมูลภายนอกต่อไปนี้" }, "nplurals=1; plural=0;"); diff --git a/apps/files_external/l10n/th_TH.json b/apps/files_external/l10n/th_TH.json index 8c00efd7bb2..2db63df9df2 100644 --- a/apps/files_external/l10n/th_TH.json +++ b/apps/files_external/l10n/th_TH.json @@ -14,6 +14,7 @@ "Not permitted to use authentication mechanism \"%s\"" : "ไม่อนุญาตให้ตรวจสอบการรับรองความถูกต้อง \"%s\"", "Unsatisfied backend parameters" : "พารามิเตอร์แบ็กเอนด์ไม่ได้รับอนุญาต", "Unsatisfied authentication mechanism parameters" : "การรับรองความถูกต้องไม่เพียงพอ", + "Insufficient data: %s" : "ข้อมูลไม่เพียงพอ: %s", "Personal" : "ส่วนตัว", "System" : "ระบบ", "Grant access" : "อนุญาตให้เข้าถึงได้", @@ -99,7 +100,7 @@ "Advanced settings" : "ตั้งค่าขั้นสูง", "Delete" : "ลบ", "Add storage" : "เพิ่มพื้นที่จัดเก็บข้อมูล", - "Enable User External Storage" : "เปิดให้มีการใช้พื้นที่จัดเก็บข้อมูลของผู้ใช้งานจากภายนอกได้", + "Allow users to mount external storage" : "อนุญาตให้ผู้ใช้ติดตั้งการจัดเก็บข้อมูลภายนอก", "Allow users to mount the following external storage" : "อนุญาตให้ผู้ใช้ติดตั้งจัดเก็บข้อมูลภายนอกต่อไปนี้" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/apps/files_external/l10n/tr.js b/apps/files_external/l10n/tr.js index 6eada0b32f3..619e5975ed8 100644 --- a/apps/files_external/l10n/tr.js +++ b/apps/files_external/l10n/tr.js @@ -101,7 +101,6 @@ OC.L10N.register( "Advanced settings" : "Gelişmiş ayarlar", "Delete" : "Sil", "Add storage" : "Depo ekle", - "Enable User External Storage" : "Kullanıcılar için Harici Depolamayı Etkinleştir", "Allow users to mount the following external storage" : "Kullanıcıların aşağıdaki harici depolamayı bağlamalarına izin ver" }, "nplurals=2; plural=(n > 1);"); diff --git a/apps/files_external/l10n/tr.json b/apps/files_external/l10n/tr.json index 7fd764d0165..cb315a333c2 100644 --- a/apps/files_external/l10n/tr.json +++ b/apps/files_external/l10n/tr.json @@ -99,7 +99,6 @@ "Advanced settings" : "Gelişmiş ayarlar", "Delete" : "Sil", "Add storage" : "Depo ekle", - "Enable User External Storage" : "Kullanıcılar için Harici Depolamayı Etkinleştir", "Allow users to mount the following external storage" : "Kullanıcıların aşağıdaki harici depolamayı bağlamalarına izin ver" },"pluralForm" :"nplurals=2; plural=(n > 1);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/uk.js b/apps/files_external/l10n/uk.js index 68b1787346a..f8ca8dc360c 100644 --- a/apps/files_external/l10n/uk.js +++ b/apps/files_external/l10n/uk.js @@ -64,7 +64,6 @@ OC.L10N.register( "Advanced settings" : "Розширені налаштування", "Delete" : "Видалити", "Add storage" : "Додати сховище", - "Enable User External Storage" : "Активувати користувацькі зовнішні сховища", "Allow users to mount the following external storage" : "Дозволити користувачам монтувати наступні зовнішні сховища" }, "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"); diff --git a/apps/files_external/l10n/uk.json b/apps/files_external/l10n/uk.json index 5765a30dc59..c34d0d2c82f 100644 --- a/apps/files_external/l10n/uk.json +++ b/apps/files_external/l10n/uk.json @@ -62,7 +62,6 @@ "Advanced settings" : "Розширені налаштування", "Delete" : "Видалити", "Add storage" : "Додати сховище", - "Enable User External Storage" : "Активувати користувацькі зовнішні сховища", "Allow users to mount the following external storage" : "Дозволити користувачам монтувати наступні зовнішні сховища" },"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" }
\ No newline at end of file diff --git a/apps/files_external/l10n/vi.js b/apps/files_external/l10n/vi.js index 49c746851eb..f3fdb39136c 100644 --- a/apps/files_external/l10n/vi.js +++ b/apps/files_external/l10n/vi.js @@ -22,7 +22,6 @@ OC.L10N.register( "Folder name" : "Tên thư mục", "Configuration" : "Cấu hình", "Delete" : "Xóa", - "Add storage" : "Thêm bộ nhớ", - "Enable User External Storage" : "Kích hoạt tính năng lưu trữ ngoài" + "Add storage" : "Thêm bộ nhớ" }, "nplurals=1; plural=0;"); diff --git a/apps/files_external/l10n/vi.json b/apps/files_external/l10n/vi.json index 4daddc7ae57..fdba39fc95e 100644 --- a/apps/files_external/l10n/vi.json +++ b/apps/files_external/l10n/vi.json @@ -20,7 +20,6 @@ "Folder name" : "Tên thư mục", "Configuration" : "Cấu hình", "Delete" : "Xóa", - "Add storage" : "Thêm bộ nhớ", - "Enable User External Storage" : "Kích hoạt tính năng lưu trữ ngoài" + "Add storage" : "Thêm bộ nhớ" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/apps/files_external/l10n/zh_CN.js b/apps/files_external/l10n/zh_CN.js index 3ba25300d95..4b99fc170a2 100644 --- a/apps/files_external/l10n/zh_CN.js +++ b/apps/files_external/l10n/zh_CN.js @@ -42,7 +42,6 @@ OC.L10N.register( "Available for" : "可用于", "Delete" : "删除", "Add storage" : "增加存储", - "Enable User External Storage" : "启用用户外部存储", "Allow users to mount the following external storage" : "允许用户挂载以下外部存储" }, "nplurals=1; plural=0;"); diff --git a/apps/files_external/l10n/zh_CN.json b/apps/files_external/l10n/zh_CN.json index 94301573ab9..fddc688c5c2 100644 --- a/apps/files_external/l10n/zh_CN.json +++ b/apps/files_external/l10n/zh_CN.json @@ -40,7 +40,6 @@ "Available for" : "可用于", "Delete" : "删除", "Add storage" : "增加存储", - "Enable User External Storage" : "启用用户外部存储", "Allow users to mount the following external storage" : "允许用户挂载以下外部存储" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/apps/files_external/l10n/zh_TW.js b/apps/files_external/l10n/zh_TW.js index e4e01cd2d59..61f224e4ffe 100644 --- a/apps/files_external/l10n/zh_TW.js +++ b/apps/files_external/l10n/zh_TW.js @@ -1,39 +1,102 @@ OC.L10N.register( "files_external", { + "Fetching request tokens failed. Verify that your app key and secret are correct." : "請求失敗,請驗證您的應用程式金鑰及密碼是否正確", + "Fetching access tokens failed. Verify that your app key and secret are correct." : "存取失敗,請驗證您的應用程式金鑰及密碼是否正確", + "Please provide a valid app key and secret." : "請提供有效的應用程式金鑰及密碼", + "Step 1 failed. Exception: %s" : "步驟 1 失敗,出現異常: %s", + "Step 2 failed. Exception: %s" : "步驟 2 失敗,出現異常: %s", "External storage" : "外部儲存", + "Storage with id \"%i\" not found" : "沒有找到編號 \"%i\" 的儲存空間 ", + "Invalid backend or authentication mechanism class" : "無效的後端處理或是驗證方式", + "Invalid mount point" : "無效的掛載點", + "Objectstore forbidden" : "物件儲存禁止存取", + "Invalid storage backend \"%s\"" : "無效的後端儲存 \"%s\"", + "Not permitted to use backend \"%s\"" : "不被允許使用後端儲存 \"%s\"", + "Not permitted to use authentication mechanism \"%s\"" : "不被允許使用驗證機制 \"%s\"", + "Unsatisfied backend parameters" : "無法滿足後端所需的參數條件", + "Unsatisfied authentication mechanism parameters" : "無法滿足驗證機制所需的參數條件", + "Insufficient data: %s" : "資料不足: %s", "Personal" : "個人", "System" : "系統", "Grant access" : "允許存取", "Access granted" : "允許存取", + "Error configuring OAuth1" : "設定 OAuth1 時發生錯誤", + "Error configuring OAuth2" : "設定 OAuth2 時發生錯誤", + "Generate keys" : "產生金鑰", + "Error generating key pair" : "產生金鑰對錯誤", + "Enable encryption" : "啟用加密", + "Enable previews" : "啟動預覽", + "Check for changes" : "檢查變動", + "Never" : "絕不", + "Every time the filesystem is used" : "每當檔案系統使用時", + "All users. Type to select user or group." : "所有人都可以使用,或者選擇特定使用者、群組", + "(group)" : "(群組)", "Saved" : "已儲存", + "Access key" : "存取金鑰", + "Secret key" : "私密金鑰", "None" : "無", + "App key" : "App 金鑰", + "App secret" : "App 密碼", + "Client ID" : "客戶端ID", + "Client secret" : "客戶端密碼", + "OpenStack" : "OpenStack", "Username" : "使用者名稱", "Password" : "密碼", + "Tenant name" : "租戶/專案名稱", + "Identity endpoint URL" : "身份識別終端點 URL", + "Rackspace" : "Rackspace", "API key" : "API金鑰", + "Username and password" : "使用者帳號和密碼", + "RSA public key" : "RSA 公開金鑰", + "Public key" : "公開金鑰", "Amazon S3" : "Amazon S3", + "Bucket" : "Bucket", + "Hostname" : "主機名稱", "Port" : "連接埠", "Region" : "地區", "Enable SSL" : "啟用 SSL", + "Enable Path Style" : "啟用路徑格式", "WebDAV" : "WebDAV", "URL" : "URL", + "Remote subfolder" : "遠端子資料夾", + "Secure https://" : "安全 https://", + "Dropbox" : "Dropbox", + "FTP" : "檔案傳輸協定-FTP", "Host" : "主機", + "Secure ftps://" : "安全 ftps://", + "Google Drive" : "Google 雲端硬碟", "Local" : "本地", "Location" : "地點", "ownCloud" : "ownCloud", + "SFTP" : "安全檔案傳輸協定-SFTP", + "SFTP with secret key login" : "以密碼金鑰登入SFTP", + "SMB / CIFS" : "伺服器訊息區塊-SMB/網路文件共享系統 (CIFS)", "Share" : "分享", + "Domain" : "網域名稱", + "SMB / CIFS using OC login" : "SMB / CIFS 使用 OC 登入", + "Username as share" : "以使用者名稱分享", + "OpenStack Object Storage" : "OpenStack 物件儲存", + "Service name" : "服務名稱", + "Request timeout (seconds)" : "請求超時 (秒)", "<b>Note:</b> " : "<b>警告:</b> ", "<b>Note:</b> The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>警告:</b> PHP 並未啓用 Curl 的支援,因此無法掛載 %s 。請洽您的系統管理員將其安裝並啓用。", "<b>Note:</b> The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>警告</b>:PHP 並未啓用 FTP 的支援,因此無法掛載 %s,請洽您的系統管理員將其安裝並啓用。", "<b>Note:</b> \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>警告</b>並未安裝 \"%s\",因此無法掛載 %s。請洽您的系統管理員將其安裝並啓用。", + "No external storage configured" : "目前尚未配置任何外部儲存", + "You can add external storages in the personal settings" : "在個人設定裡您可以自行加入外部儲存設定", "Name" : "名稱", + "Storage type" : "儲存類型", + "Scope" : "範圍", "External Storage" : "外部儲存", "Folder name" : "資料夾名稱", + "Authentication" : "驗證", "Configuration" : "設定", "Available for" : "可用的", + "Advanced settings" : "進階設定", "Delete" : "刪除", "Add storage" : "增加儲存區", - "Enable User External Storage" : "啓用使用者外部儲存", + "Allow users to mount external storage" : "允許使用者能自行掛載外部儲存", "Allow users to mount the following external storage" : "允許使用者自行掛載以下的外部儲存" }, "nplurals=1; plural=0;"); diff --git a/apps/files_external/l10n/zh_TW.json b/apps/files_external/l10n/zh_TW.json index 1ed049bc079..b9aa234e89e 100644 --- a/apps/files_external/l10n/zh_TW.json +++ b/apps/files_external/l10n/zh_TW.json @@ -1,37 +1,100 @@ { "translations": { + "Fetching request tokens failed. Verify that your app key and secret are correct." : "請求失敗,請驗證您的應用程式金鑰及密碼是否正確", + "Fetching access tokens failed. Verify that your app key and secret are correct." : "存取失敗,請驗證您的應用程式金鑰及密碼是否正確", + "Please provide a valid app key and secret." : "請提供有效的應用程式金鑰及密碼", + "Step 1 failed. Exception: %s" : "步驟 1 失敗,出現異常: %s", + "Step 2 failed. Exception: %s" : "步驟 2 失敗,出現異常: %s", "External storage" : "外部儲存", + "Storage with id \"%i\" not found" : "沒有找到編號 \"%i\" 的儲存空間 ", + "Invalid backend or authentication mechanism class" : "無效的後端處理或是驗證方式", + "Invalid mount point" : "無效的掛載點", + "Objectstore forbidden" : "物件儲存禁止存取", + "Invalid storage backend \"%s\"" : "無效的後端儲存 \"%s\"", + "Not permitted to use backend \"%s\"" : "不被允許使用後端儲存 \"%s\"", + "Not permitted to use authentication mechanism \"%s\"" : "不被允許使用驗證機制 \"%s\"", + "Unsatisfied backend parameters" : "無法滿足後端所需的參數條件", + "Unsatisfied authentication mechanism parameters" : "無法滿足驗證機制所需的參數條件", + "Insufficient data: %s" : "資料不足: %s", "Personal" : "個人", "System" : "系統", "Grant access" : "允許存取", "Access granted" : "允許存取", + "Error configuring OAuth1" : "設定 OAuth1 時發生錯誤", + "Error configuring OAuth2" : "設定 OAuth2 時發生錯誤", + "Generate keys" : "產生金鑰", + "Error generating key pair" : "產生金鑰對錯誤", + "Enable encryption" : "啟用加密", + "Enable previews" : "啟動預覽", + "Check for changes" : "檢查變動", + "Never" : "絕不", + "Every time the filesystem is used" : "每當檔案系統使用時", + "All users. Type to select user or group." : "所有人都可以使用,或者選擇特定使用者、群組", + "(group)" : "(群組)", "Saved" : "已儲存", + "Access key" : "存取金鑰", + "Secret key" : "私密金鑰", "None" : "無", + "App key" : "App 金鑰", + "App secret" : "App 密碼", + "Client ID" : "客戶端ID", + "Client secret" : "客戶端密碼", + "OpenStack" : "OpenStack", "Username" : "使用者名稱", "Password" : "密碼", + "Tenant name" : "租戶/專案名稱", + "Identity endpoint URL" : "身份識別終端點 URL", + "Rackspace" : "Rackspace", "API key" : "API金鑰", + "Username and password" : "使用者帳號和密碼", + "RSA public key" : "RSA 公開金鑰", + "Public key" : "公開金鑰", "Amazon S3" : "Amazon S3", + "Bucket" : "Bucket", + "Hostname" : "主機名稱", "Port" : "連接埠", "Region" : "地區", "Enable SSL" : "啟用 SSL", + "Enable Path Style" : "啟用路徑格式", "WebDAV" : "WebDAV", "URL" : "URL", + "Remote subfolder" : "遠端子資料夾", + "Secure https://" : "安全 https://", + "Dropbox" : "Dropbox", + "FTP" : "檔案傳輸協定-FTP", "Host" : "主機", + "Secure ftps://" : "安全 ftps://", + "Google Drive" : "Google 雲端硬碟", "Local" : "本地", "Location" : "地點", "ownCloud" : "ownCloud", + "SFTP" : "安全檔案傳輸協定-SFTP", + "SFTP with secret key login" : "以密碼金鑰登入SFTP", + "SMB / CIFS" : "伺服器訊息區塊-SMB/網路文件共享系統 (CIFS)", "Share" : "分享", + "Domain" : "網域名稱", + "SMB / CIFS using OC login" : "SMB / CIFS 使用 OC 登入", + "Username as share" : "以使用者名稱分享", + "OpenStack Object Storage" : "OpenStack 物件儲存", + "Service name" : "服務名稱", + "Request timeout (seconds)" : "請求超時 (秒)", "<b>Note:</b> " : "<b>警告:</b> ", "<b>Note:</b> The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>警告:</b> PHP 並未啓用 Curl 的支援,因此無法掛載 %s 。請洽您的系統管理員將其安裝並啓用。", "<b>Note:</b> The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>警告</b>:PHP 並未啓用 FTP 的支援,因此無法掛載 %s,請洽您的系統管理員將其安裝並啓用。", "<b>Note:</b> \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>警告</b>並未安裝 \"%s\",因此無法掛載 %s。請洽您的系統管理員將其安裝並啓用。", + "No external storage configured" : "目前尚未配置任何外部儲存", + "You can add external storages in the personal settings" : "在個人設定裡您可以自行加入外部儲存設定", "Name" : "名稱", + "Storage type" : "儲存類型", + "Scope" : "範圍", "External Storage" : "外部儲存", "Folder name" : "資料夾名稱", + "Authentication" : "驗證", "Configuration" : "設定", "Available for" : "可用的", + "Advanced settings" : "進階設定", "Delete" : "刪除", "Add storage" : "增加儲存區", - "Enable User External Storage" : "啓用使用者外部儲存", + "Allow users to mount external storage" : "允許使用者能自行掛載外部儲存", "Allow users to mount the following external storage" : "允許使用者自行掛載以下的外部儲存" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/apps/files_external/lib/amazons3.php b/apps/files_external/lib/amazons3.php index 00915140bab..4b867c005a7 100644 --- a/apps/files_external/lib/amazons3.php +++ b/apps/files_external/lib/amazons3.php @@ -418,27 +418,6 @@ class AmazonS3 extends \OC\Files\Storage\Common { return false; } - public function getMimeType($path) { - $path = $this->normalizePath($path); - - if ($this->is_dir($path)) { - return 'httpd/unix-directory'; - } else if ($this->file_exists($path)) { - try { - $result = $this->getConnection()->headObject(array( - 'Bucket' => $this->bucket, - 'Key' => $path - )); - } catch (S3Exception $e) { - \OCP\Util::logException('files_external', $e); - return false; - } - - return $result['ContentType']; - } - return false; - } - public function touch($path, $mtime = null) { $path = $this->normalizePath($path); diff --git a/apps/files_external/lib/config.php b/apps/files_external/lib/config.php index d9fdb748fcd..6c900f0f224 100644 --- a/apps/files_external/lib/config.php +++ b/apps/files_external/lib/config.php @@ -269,6 +269,7 @@ class OC_Mount_Config { } } catch (Exception $exception) { \OCP\Util::logException('files_external', $exception); + throw $exception; } } return self::STATUS_ERROR; diff --git a/apps/files_external/lib/dropbox.php b/apps/files_external/lib/dropbox.php index 6a822c3fc69..df8a0255134 100644 --- a/apps/files_external/lib/dropbox.php +++ b/apps/files_external/lib/dropbox.php @@ -64,7 +64,7 @@ class Dropbox extends \OC\Files\Storage\Common { * @param string $path */ private function deleteMetaData($path) { - $path = $this->root.$path; + $path = ltrim($this->root.$path, '/'); if (isset($this->metaData[$path])) { unset($this->metaData[$path]); return true; @@ -72,6 +72,10 @@ class Dropbox extends \OC\Files\Storage\Common { return false; } + private function setMetaData($path, $metaData) { + $this->metaData[ltrim($path, '/')] = $metaData; + } + /** * Returns the path's metadata * @param string $path path for which to return the metadata @@ -80,7 +84,7 @@ class Dropbox extends \OC\Files\Storage\Common { * false, null if the file doesn't exist or "false" if the operation failed */ private function getDropBoxMetaData($path, $list = false) { - $path = $this->root.$path; + $path = ltrim($this->root.$path, '/'); if ( ! $list && isset($this->metaData[$path])) { return $this->metaData[$path]; } else { @@ -96,14 +100,14 @@ class Dropbox extends \OC\Files\Storage\Common { // Cache folder's contents foreach ($response['contents'] as $file) { if (!isset($file['is_deleted']) || !$file['is_deleted']) { - $this->metaData[$path.'/'.basename($file['path'])] = $file; + $this->setMetaData($path.'/'.basename($file['path']), $file); $contents[] = $file; } } unset($response['contents']); } if (!isset($response['is_deleted']) || !$response['is_deleted']) { - $this->metaData[$path] = $response; + $this->setMetaData($path, $response); } // Return contents of folder only return $contents; @@ -116,7 +120,7 @@ class Dropbox extends \OC\Files\Storage\Common { $response = $this->dropbox->getMetaData($requestPath, 'false'); if (!isset($response['is_deleted']) || !$response['is_deleted']) { - $this->metaData[$path] = $response; + $this->setMetaData($path, $response); return $response; } return null; @@ -295,18 +299,6 @@ class Dropbox extends \OC\Files\Storage\Common { } } - public function getMimeType($path) { - if ($this->filetype($path) == 'dir') { - return 'httpd/unix-directory'; - } else { - $metaData = $this->getDropBoxMetaData($path); - if ($metaData) { - return $metaData['mime_type']; - } - } - return false; - } - public function free_space($path) { try { $info = $this->dropbox->getAccountInfo(); 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 @@ -52,27 +52,37 @@ 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} */ public function __construct($params) { // 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/lib/storageconfig.php b/apps/files_external/lib/storageconfig.php index 70aaa186783..86a7e6ffa12 100644 --- a/apps/files_external/lib/storageconfig.php +++ b/apps/files_external/lib/storageconfig.php @@ -73,6 +73,13 @@ class StorageConfig implements \JsonSerializable { private $status; /** + * Status message + * + * @var string + */ + private $statusMessage; + + /** * Priority * * @var int @@ -295,7 +302,7 @@ class StorageConfig implements \JsonSerializable { } /** - * Sets the storage status, whether the config worked last time + * Gets the storage status, whether the config worked last time * * @return int $status status */ @@ -304,12 +311,23 @@ class StorageConfig implements \JsonSerializable { } /** + * Gets the message describing the storage status + * + * @return string|null + */ + public function getStatusMessage() { + return $this->statusMessage; + } + + /** * Sets the storage status, whether the config worked last time * * @param int $status status + * @param string|null $message optional message */ - public function setStatus($status) { + public function setStatus($status, $message = null) { $this->status = $status; + $this->statusMessage = $message; } /** @@ -341,6 +359,9 @@ class StorageConfig implements \JsonSerializable { if (!is_null($this->status)) { $result['status'] = $this->status; } + if (!is_null($this->statusMessage)) { + $result['statusMessage'] = $this->statusMessage; + } return $result; } } diff --git a/apps/files_external/lib/swift.php b/apps/files_external/lib/swift.php index b9454b8d671..e946e7feb77 100644 --- a/apps/files_external/lib/swift.php +++ b/apps/files_external/lib/swift.php @@ -106,7 +106,10 @@ class Swift extends \OC\Files\Storage\Common { $this->getContainer()->getPartialObject($path); return true; } catch (ClientErrorResponseException $e) { - \OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR); + // Expected response is "404 Not Found", so only log if it isn't + if ($e->getResponse()->getStatusCode() !== 404) { + \OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR); + } return false; } } @@ -361,18 +364,6 @@ class Swift extends \OC\Files\Storage\Common { } } - public function getMimeType($path) { - $path = $this->normalizePath($path); - - if ($this->is_dir($path)) { - return 'httpd/unix-directory'; - } else if ($this->file_exists($path)) { - $object = $this->getContainer()->getPartialObject($path); - return $object->getContentType(); - } - return false; - } - public function touch($path, $mtime = null) { $path = $this->normalizePath($path); if (is_null($mtime)) { diff --git a/apps/files_external/service/backendservice.php b/apps/files_external/service/backendservice.php index 1e90247b3e4..b325517e58a 100644 --- a/apps/files_external/service/backendservice.php +++ b/apps/files_external/service/backendservice.php @@ -72,6 +72,11 @@ class BackendService { $this->userMountingBackends = explode(',', $this->config->getAppValue('files_external', 'user_mounting_backends', '') ); + + // if no backend is in the list an empty string is in the array and user mounting is disabled + if ($this->userMountingBackends === ['']) { + $this->userMountingAllowed = false; + } } /** diff --git a/apps/files_external/templates/settings.php b/apps/files_external/templates/settings.php index d00d22765e3..cebf6cc4de0 100644 --- a/apps/files_external/templates/settings.php +++ b/apps/files_external/templates/settings.php @@ -193,7 +193,7 @@ <br /> <input type="checkbox" name="allowUserMounting" id="allowUserMounting" class="checkbox" value="1" <?php if ($_['allowUserMounting'] == 'yes') print_unescaped(' checked="checked"'); ?> /> - <label for="allowUserMounting"><?php p($l->t('Enable User External Storage')); ?></label> <span id="userMountingMsg" class="msg"></span> + <label for="allowUserMounting"><?php p($l->t('Allow users to mount external storage')); ?></label> <span id="userMountingMsg" class="msg"></span> <p id="userMountingBackends"<?php if ($_['allowUserMounting'] != 'yes'): ?> class="hidden"<?php endif; ?>> <?php p($l->t('Allow users to mount the following external storage')); ?><br /> 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/', + ], ]; } } diff --git a/apps/files_external/tests/env/start-amazons3-ceph.sh b/apps/files_external/tests/env/start-amazons3-ceph.sh index f2beb0bd714..b40d28f1ec6 100755 --- a/apps/files_external/tests/env/start-amazons3-ceph.sh +++ b/apps/files_external/tests/env/start-amazons3-ceph.sh @@ -41,7 +41,7 @@ container=`docker run -d \ -e RGW_CIVETWEB_PORT=$port \ ${docker_image}` -host=`docker inspect $container | grep IPAddress | cut -d '"' -f 4` +host=`docker inspect --format="{{.NetworkSettings.IPAddress}}" $container` echo "${docker_image} container: $container" diff --git a/apps/files_external/tests/env/start-ftp-morrisjobke.sh b/apps/files_external/tests/env/start-ftp-morrisjobke.sh index 35e3eafb839..3c6cc62bce8 100755 --- a/apps/files_external/tests/env/start-ftp-morrisjobke.sh +++ b/apps/files_external/tests/env/start-ftp-morrisjobke.sh @@ -34,7 +34,7 @@ password=12345 container=`docker run -d -e USERNAME=$user -e PASSWORD=$password morrisjobke/docker-proftpd` -host=`docker inspect $container | grep IPAddress | cut -d '"' -f 4` +host=`docker inspect --format="{{.NetworkSettings.IPAddress}}" $container` cat > $thisFolder/config.ftp.php <<DELIM <?php diff --git a/apps/files_external/tests/env/start-sftp-atmoz.sh b/apps/files_external/tests/env/start-sftp-atmoz.sh index c4ef81b8357..3e0616f03d2 100755 --- a/apps/files_external/tests/env/start-sftp-atmoz.sh +++ b/apps/files_external/tests/env/start-sftp-atmoz.sh @@ -34,7 +34,7 @@ password=12345 container=`docker run -d atmoz/sftp $user:$password:1001` -host=`docker inspect $container | grep IPAddress | cut -d '"' -f 4` +host=`docker inspect --format="{{.NetworkSettings.IPAddress}}" $container` cat > $thisFolder/config.sftp.php <<DELIM <?php diff --git a/apps/files_external/tests/env/start-smb-silvershell.sh b/apps/files_external/tests/env/start-smb-silvershell.sh index e2aa025c711..31e3da44646 100755 --- a/apps/files_external/tests/env/start-smb-silvershell.sh +++ b/apps/files_external/tests/env/start-smb-silvershell.sh @@ -31,7 +31,7 @@ fi; container=`docker run -d -e SMB_USER=test -e SMB_PWD=test silvershell/samba` -host=`docker inspect $container | grep IPAddress | cut -d '"' -f 4` +host=`docker inspect --format="{{.NetworkSettings.IPAddress}}" $container` cat > $thisFolder/config.smb.php <<DELIM <?php diff --git a/apps/files_external/tests/service/userglobalstoragesservicetest.php b/apps/files_external/tests/service/userglobalstoragesservicetest.php index 1b902b6eee5..e88764d0f78 100644 --- a/apps/files_external/tests/service/userglobalstoragesservicetest.php +++ b/apps/files_external/tests/service/userglobalstoragesservicetest.php @@ -1,6 +1,7 @@ <?php /** * @author Robin McCorkell <rmccorkell@karoshi.org.uk> + * @author Vincent Petry <pvince81@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 diff --git a/apps/files_sharing/ajax/external.php b/apps/files_sharing/ajax/external.php index c80f0e0b288..0f8a3d56cf0 100644 --- a/apps/files_sharing/ajax/external.php +++ b/apps/files_sharing/ajax/external.php @@ -5,7 +5,7 @@ * @author Lukas Reschke <lukas@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> * @author Robin Appelman <icewind@owncloud.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Vincent Petry <pvince81@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. diff --git a/apps/files_sharing/ajax/list.php b/apps/files_sharing/ajax/list.php index 9819048b881..c7f0bde5d4a 100644 --- a/apps/files_sharing/ajax/list.php +++ b/apps/files_sharing/ajax/list.php @@ -3,7 +3,7 @@ * @author Joas Schilling <nickvergessen@owncloud.com> * @author Lukas Reschke <lukas@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Thomas Müller <thomas.mueller@tmit.eu> * @author Vincent Petry <pvince81@owncloud.com> * diff --git a/apps/files_sharing/ajax/publicpreview.php b/apps/files_sharing/ajax/publicpreview.php index 62157e0ac0e..2902969b21f 100644 --- a/apps/files_sharing/ajax/publicpreview.php +++ b/apps/files_sharing/ajax/publicpreview.php @@ -4,7 +4,7 @@ * @author Georg Ehrke <georg@owncloud.com> * @author Lukas Reschke <lukas@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Thomas Müller <thomas.mueller@tmit.eu> * * @copyright Copyright (c) 2015, ownCloud, Inc. diff --git a/apps/files_sharing/api/local.php b/apps/files_sharing/api/local.php index 42e77570f95..bb5136a0c99 100644 --- a/apps/files_sharing/api/local.php +++ b/apps/files_sharing/api/local.php @@ -4,7 +4,7 @@ * @author Joas Schilling <nickvergessen@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> * @author Robin Appelman <icewind@owncloud.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Thomas Müller <thomas.mueller@tmit.eu> * @author Vincent Petry <pvince81@owncloud.com> * diff --git a/apps/files_sharing/api/ocssharewrapper.php b/apps/files_sharing/api/ocssharewrapper.php new file mode 100644 index 00000000000..3ce2901dfb4 --- /dev/null +++ b/apps/files_sharing/api/ocssharewrapper.php @@ -0,0 +1,71 @@ +<?php +/** + * @author Roeland Jago Douma <rullzer@owncloud.com> + * + * @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 <http://www.gnu.org/licenses/> + * + */ +namespace OCA\Files_Sharing\API; + +class OCSShareWrapper { + + /** + * @return Share20OCS + */ + private function getShare20OCS() { + return new Share20OCS(new \OC\Share20\Manager( + \OC::$server->getUserSession()->getUser(), + \OC::$server->getUserManager(), + \OC::$server->getGroupManager(), + \OC::$server->getLogger(), + \OC::$server->getAppConfig(), + \OC::$server->getUserFolder(), + new \OC\Share20\DefaultShareProvider( + \OC::$server->getDatabaseConnection(), + \OC::$server->getUserManager(), + \OC::$server->getGroupManager(), + \OC::$server->getUserFolder() + ) + ), + \OC::$server->getGroupManager(), + \OC::$server->getUserManager(), + \OC::$server->getRequest(), + \OC::$server->getUserFolder(), + \OC::$server->getURLGenerator()); + } + + public function getAllShares($params) { + return \OCA\Files_Sharing\API\Local::getAllShares($params); + } + + public function createShare($params) { + return \OCA\Files_Sharing\API\Local::createShare($params); + } + + public function getShare($params) { + $id = $params['id']; + return $this->getShare20OCS()->getShare($id); + } + + public function updateShare($params) { + return \OCA\Files_Sharing\API\Local::updateShare($params); + } + + public function deleteShare($params) { + $id = $params['id']; + return $this->getShare20OCS()->deleteShare($id); + } +} diff --git a/apps/files_sharing/api/remote.php b/apps/files_sharing/api/remote.php index d67920c3521..fb692f8a9a6 100644 --- a/apps/files_sharing/api/remote.php +++ b/apps/files_sharing/api/remote.php @@ -1,7 +1,7 @@ <?php /** * @author Joas Schilling <nickvergessen@owncloud.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 @@ -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(); diff --git a/apps/files_sharing/api/server2server.php b/apps/files_sharing/api/server2server.php index 2e0468039b4..93998ad774e 100644 --- a/apps/files_sharing/api/server2server.php +++ b/apps/files_sharing/api/server2server.php @@ -3,6 +3,7 @@ * @author Arthur Schiwon <blizzz@owncloud.com> * @author Björn Schießle <schiessle@owncloud.com> * @author Joas Schilling <nickvergessen@owncloud.com> + * @author Lukas Reschke <lukas@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> * * @copyright Copyright (c) 2015, ownCloud, Inc. @@ -25,6 +26,7 @@ namespace OCA\Files_Sharing\API; use OCA\Files_Sharing\Activity; +use OCP\Files\NotFoundException; class Server2Server { @@ -264,7 +266,11 @@ class Server2Server { private function getFile($user, $fileSource) { \OC_Util::setupFS($user); - $file = \OC\Files\Filesystem::getPath($fileSource); + try { + $file = \OC\Files\Filesystem::getPath($fileSource); + } catch (NotFoundException $e) { + $file = null; + } $args = \OC\Files\Filesystem::is_dir($file) ? array('dir' => $file) : array('dir' => dirname($file), 'scrollto' => $file); $link = \OCP\Util::linkToAbsolute('files', 'index.php', $args); diff --git a/apps/files_sharing/api/share20ocs.php b/apps/files_sharing/api/share20ocs.php new file mode 100644 index 00000000000..aaf5a3c72b6 --- /dev/null +++ b/apps/files_sharing/api/share20ocs.php @@ -0,0 +1,167 @@ +<?php +/** + * @author Roeland Jago Douma <rullzer@owncloud.com> + * + * @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 <http://www.gnu.org/licenses/> + * + */ +namespace OCA\Files_Sharing\API; + +use OC\Share20\IShare; + +class Share20OCS { + + /** @var \OC\Share20\Manager */ + private $shareManager; + + /** @var \OCP\IGroupManager */ + private $groupManager; + + /** @var \OCP\IUserManager */ + private $userManager; + + /** @var \OCP\IRequest */ + private $request; + + /** @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\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 string $id + * @return \OC_OCS_Result + */ + public function deleteShare($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.'); + } + + /* + * FIXME + * User the old code path for remote shares until we have our remoteshareprovider + */ + if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) { + \OCA\Files_Sharing\API\Local::deleteShare(['id' => $id]); + } + + try { + $this->shareManager->deleteShare($share); + } catch (\OC\Share20\Exception\BackendError $e) { + return new \OC_OCS_Result(null, 404, 'could not delete share'); + } + + return new \OC_OCS_Result(); + } +} diff --git a/apps/files_sharing/api/sharees.php b/apps/files_sharing/api/sharees.php index b34aef72163..21f68d9b253 100644 --- a/apps/files_sharing/api/sharees.php +++ b/apps/files_sharing/api/sharees.php @@ -1,7 +1,7 @@ <?php /** * @author Joas Schilling <nickvergessen@owncloud.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 diff --git a/apps/files_sharing/appinfo/application.php b/apps/files_sharing/appinfo/application.php index 9dc0e0618b5..545a9425083 100644 --- a/apps/files_sharing/appinfo/application.php +++ b/apps/files_sharing/appinfo/application.php @@ -3,7 +3,8 @@ * @author Joas Schilling <nickvergessen@owncloud.com> * @author Lukas Reschke <lukas@owncloud.com> * @author Robin Appelman <icewind@owncloud.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> + * @author Vincent Petry <pvince81@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 diff --git a/apps/files_sharing/appinfo/install.php b/apps/files_sharing/appinfo/install.php index 607e990346a..5185ae883f3 100644 --- a/apps/files_sharing/appinfo/install.php +++ b/apps/files_sharing/appinfo/install.php @@ -1,6 +1,7 @@ <?php /** * @author Joas Schilling <nickvergessen@owncloud.com> + * @author Morris Jobke <hey@morrisjobke.de> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 diff --git a/apps/files_sharing/appinfo/routes.php b/apps/files_sharing/appinfo/routes.php index a466c4fc6cc..8755691c1e8 100644 --- a/apps/files_sharing/appinfo/routes.php +++ b/apps/files_sharing/appinfo/routes.php @@ -5,7 +5,7 @@ * @author Joas Schilling <nickvergessen@owncloud.com> * @author Lukas Reschke <lukas@owncloud.com> * @author Robin Appelman <icewind@owncloud.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Thomas Müller <thomas.mueller@tmit.eu> * * @copyright Copyright (c) 2015, ownCloud, Inc. @@ -61,29 +61,31 @@ $this->create('sharing_external_add', '/external') //TODO: SET: mail notification, waiting for PR #4689 to be accepted +$OCSShare = new \OCA\Files_Sharing\API\OCSShareWrapper(); + API::register('get', '/apps/files_sharing/api/v1/shares', - array('\OCA\Files_Sharing\API\Local', 'getAllShares'), + [$OCSShare, 'getAllShares'], 'files_sharing'); API::register('post', '/apps/files_sharing/api/v1/shares', - array('\OCA\Files_Sharing\API\Local', 'createShare'), + [$OCSShare, 'createShare'], 'files_sharing'); API::register('get', '/apps/files_sharing/api/v1/shares/{id}', - array('\OCA\Files_Sharing\API\Local', 'getShare'), + [$OCSShare, 'getShare'], 'files_sharing'); API::register('put', '/apps/files_sharing/api/v1/shares/{id}', - array('\OCA\Files_Sharing\API\Local', 'updateShare'), + [$OCSShare, 'updateShare'], 'files_sharing'); API::register('delete', '/apps/files_sharing/api/v1/shares/{id}', - array('\OCA\Files_Sharing\API\Local', 'deleteShare'), + [$OCSShare, 'deleteShare'], 'files_sharing'); API::register('get', @@ -130,3 +132,4 @@ API::register('get', '/apps/files_sharing/api/v1/sharees', [$sharees, 'search'], 'files_sharing', API::USER_AUTH); + diff --git a/apps/files_sharing/appinfo/update.php b/apps/files_sharing/appinfo/update.php index 03fb78a05af..8bff20cc442 100644 --- a/apps/files_sharing/appinfo/update.php +++ b/apps/files_sharing/appinfo/update.php @@ -2,6 +2,7 @@ /** * @author Björn Schießle <schiessle@owncloud.com> * @author Joas Schilling <nickvergessen@owncloud.com> + * @author Morris Jobke <hey@morrisjobke.de> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 diff --git a/apps/files_sharing/css/authenticate.css b/apps/files_sharing/css/authenticate.css index 43707c76100..55a40cf508d 100644 --- a/apps/files_sharing/css/authenticate.css +++ b/apps/files_sharing/css/authenticate.css @@ -18,7 +18,3 @@ input[type='submit'] { fieldset > p { position: relative; } - -#password-icon { - top: 20px; -} diff --git a/apps/files_sharing/js/public.js b/apps/files_sharing/js/public.js index 16b4f1589b1..246b639f652 100644 --- a/apps/files_sharing/js/public.js +++ b/apps/files_sharing/js/public.js @@ -54,7 +54,7 @@ OCA.Sharing.PublicApp = { $el, { id: 'files.public', - scrollContainer: $(window), + scrollContainer: $('#content-wrapper'), dragOptions: dragOptions, folderDropOptions: folderDropOptions, fileActions: fileActions, diff --git a/apps/files_sharing/js/share.js b/apps/files_sharing/js/share.js index 30a803f3207..63225a0d8ec 100644 --- a/apps/files_sharing/js/share.js +++ b/apps/files_sharing/js/share.js @@ -130,6 +130,13 @@ // remove icon, if applicable OC.Share.markFileAsShared($tr, false, false); } + var newIcon = $tr.attr('data-icon'); + // in case markFileAsShared decided to change the icon, + // we need to modify the model + // (FIXME: yes, this is hacky) + if (fileInfoModel.get('icon') !== newIcon) { + fileInfoModel.set('icon', newIcon); + } }); fileList.registerTabView(shareTab); }, diff --git a/apps/files_sharing/js/sharedfilelist.js b/apps/files_sharing/js/sharedfilelist.js index 2e798a92578..68bfd63ec89 100644 --- a/apps/files_sharing/js/sharedfilelist.js +++ b/apps/files_sharing/js/sharedfilelist.js @@ -105,11 +105,7 @@ }, getDirectoryPermissions: function() { - var perms = OC.PERMISSION_READ; - if (this._sharedWithUser) { - perms |= OC.PERMISSION_DELETE; - } - return perms; + return OC.PERMISSION_READ | OC.PERMISSION_DELETE; }, updateStorageStatistics: function() { @@ -123,6 +119,9 @@ this._reloadCall.abort(); } + // there is only root + this._setCurrentDir('/', false); + var promises = []; var shares = $.ajax({ url: OC.linkToOCS('apps/files_sharing/api/v1') + 'shares', @@ -173,17 +172,14 @@ if (shares[0].ocs && shares[0].ocs.data) { files = files.concat(this._makeFilesFromShares(shares[0].ocs.data)); - } else { - // TODO: error handling } if (remoteShares && remoteShares[0].ocs && remoteShares[0].ocs.data) { files = files.concat(this._makeFilesFromRemoteShares(remoteShares[0].ocs.data)); - } else { - // TODO: error handling } this.setFiles(files); + return true; }, _makeFilesFromRemoteShares: function(data) { @@ -271,11 +267,7 @@ } file.name = OC.basename(share.path); file.path = OC.dirname(share.path); - if (this._sharedWithUser) { - file.permissions = OC.PERMISSION_ALL; - } else { - file.permissions = OC.PERMISSION_ALL - OC.PERMISSION_DELETE; - } + file.permissions = OC.PERMISSION_ALL; if (file.path) { file.extraData = share.path; } diff --git a/apps/files_sharing/l10n/ast.js b/apps/files_sharing/l10n/ast.js index 9ba12962bdb..b504ff6d092 100644 --- a/apps/files_sharing/l10n/ast.js +++ b/apps/files_sharing/l10n/ast.js @@ -25,6 +25,7 @@ OC.L10N.register( "This share is password-protected" : "Esta compartición tien contraseña protexida", "The password is wrong. Try again." : "La contraseña ye incorreuta. Inténtalo otra vegada.", "Password" : "Contraseña", + "No entries found in this folder" : "Nenguna entrada en esta carpeta", "Name" : "Nome", "Share time" : "Compartir hora", "Sorry, this link doesn’t seem to work anymore." : "Sentímoslo, esti enllaz paez que yá nun furrula.", diff --git a/apps/files_sharing/l10n/ast.json b/apps/files_sharing/l10n/ast.json index 52cd9b9013e..89f5607993e 100644 --- a/apps/files_sharing/l10n/ast.json +++ b/apps/files_sharing/l10n/ast.json @@ -23,6 +23,7 @@ "This share is password-protected" : "Esta compartición tien contraseña protexida", "The password is wrong. Try again." : "La contraseña ye incorreuta. Inténtalo otra vegada.", "Password" : "Contraseña", + "No entries found in this folder" : "Nenguna entrada en esta carpeta", "Name" : "Nome", "Share time" : "Compartir hora", "Sorry, this link doesn’t seem to work anymore." : "Sentímoslo, esti enllaz paez que yá nun furrula.", diff --git a/apps/files_sharing/l10n/da.js b/apps/files_sharing/l10n/da.js index d31acc37760..212e281b0d2 100644 --- a/apps/files_sharing/l10n/da.js +++ b/apps/files_sharing/l10n/da.js @@ -43,6 +43,14 @@ OC.L10N.register( "%2$s shared %1$s via link" : "%2$s delt %1$s via link", "%2$s shared %1$s with you" : "%2$s delt %1$s med dig", "You shared %1$s via link" : "Du delte %1$s via link", + "Downloaded via public link" : "Downloaded via et offentligt link", + "Shared with %2$s" : "Delt med %2$s", + "Shared with group %2$s" : "Delt med gruppen %2$s", + "Shared with %3$s by %2$s" : "Delt med %3$s af %2$s", + "Shared with group %3$s by %2$s" : "Delt med gruppen %3$s af %2$s", + "Shared via link by %2$s" : "Delt via link af %2$s", + "Shared by %2$s" : "Delt af %2$s", + "Shared via public link" : "Delt via offentligt link", "Shares" : "Delt", "You received %2$s as a remote share from %1$s" : "Du modtog %2$s som en ekstern deling fra %1$s", "Accept" : "Acceptér", diff --git a/apps/files_sharing/l10n/da.json b/apps/files_sharing/l10n/da.json index fe702de52e8..e13c671a005 100644 --- a/apps/files_sharing/l10n/da.json +++ b/apps/files_sharing/l10n/da.json @@ -41,6 +41,14 @@ "%2$s shared %1$s via link" : "%2$s delt %1$s via link", "%2$s shared %1$s with you" : "%2$s delt %1$s med dig", "You shared %1$s via link" : "Du delte %1$s via link", + "Downloaded via public link" : "Downloaded via et offentligt link", + "Shared with %2$s" : "Delt med %2$s", + "Shared with group %2$s" : "Delt med gruppen %2$s", + "Shared with %3$s by %2$s" : "Delt med %3$s af %2$s", + "Shared with group %3$s by %2$s" : "Delt med gruppen %3$s af %2$s", + "Shared via link by %2$s" : "Delt via link af %2$s", + "Shared by %2$s" : "Delt af %2$s", + "Shared via public link" : "Delt via offentligt link", "Shares" : "Delt", "You received %2$s as a remote share from %1$s" : "Du modtog %2$s som en ekstern deling fra %1$s", "Accept" : "Acceptér", diff --git a/apps/files_sharing/l10n/el.js b/apps/files_sharing/l10n/el.js index e4024492b65..62150bcc942 100644 --- a/apps/files_sharing/l10n/el.js +++ b/apps/files_sharing/l10n/el.js @@ -7,9 +7,9 @@ OC.L10N.register( "Could not authenticate to remote share, password might be wrong" : "Δεν ήταν δυνατή η πιστοποίηση στο απομακρυσμένο διαμοιρασμένο στοιχείο, μπορεί να είναι λάθος ο κωδικός πρόσβασης", "Storage not valid" : "Μη έγκυρος αποθηκευτικός χώρος", "Couldn't add remote share" : "Αδυναμία προσθήκης απομακρυσμένου κοινόχρηστου φακέλου", - "Shared with you" : "Διαμοιρασμένο με εσάς", - "Shared with others" : "Διαμοιρασμένο με άλλους", - "Shared by link" : "Διαμοιρασμένο μέσω συνδέσμου", + "Shared with you" : "Διαμοιρασμένα με εσάς", + "Shared with others" : "Διαμοιρασμένα με άλλους", + "Shared by link" : "Διαμοιρασμένα μέσω συνδέσμου", "Nothing shared with you yet" : "Κανένα αρχείο δεν έχει διαμοιραστεί ακόμα με εσάς.", "Files and folders others share with you will show up here" : "Τα αρχεία και οι φάκελοι που άλλοι διαμοιράζονται με εσάς θα εμφανιστούν εδώ", "Nothing shared yet" : "Δεν έχει διαμοιραστεί τίποτα μέχρι στιγμής", diff --git a/apps/files_sharing/l10n/el.json b/apps/files_sharing/l10n/el.json index 7bf5c00841e..5b23eaeedb5 100644 --- a/apps/files_sharing/l10n/el.json +++ b/apps/files_sharing/l10n/el.json @@ -5,9 +5,9 @@ "Could not authenticate to remote share, password might be wrong" : "Δεν ήταν δυνατή η πιστοποίηση στο απομακρυσμένο διαμοιρασμένο στοιχείο, μπορεί να είναι λάθος ο κωδικός πρόσβασης", "Storage not valid" : "Μη έγκυρος αποθηκευτικός χώρος", "Couldn't add remote share" : "Αδυναμία προσθήκης απομακρυσμένου κοινόχρηστου φακέλου", - "Shared with you" : "Διαμοιρασμένο με εσάς", - "Shared with others" : "Διαμοιρασμένο με άλλους", - "Shared by link" : "Διαμοιρασμένο μέσω συνδέσμου", + "Shared with you" : "Διαμοιρασμένα με εσάς", + "Shared with others" : "Διαμοιρασμένα με άλλους", + "Shared by link" : "Διαμοιρασμένα μέσω συνδέσμου", "Nothing shared with you yet" : "Κανένα αρχείο δεν έχει διαμοιραστεί ακόμα με εσάς.", "Files and folders others share with you will show up here" : "Τα αρχεία και οι φάκελοι που άλλοι διαμοιράζονται με εσάς θα εμφανιστούν εδώ", "Nothing shared yet" : "Δεν έχει διαμοιραστεί τίποτα μέχρι στιγμής", diff --git a/apps/files_sharing/l10n/ja.js b/apps/files_sharing/l10n/ja.js index 413f4a2ac8c..b80be0c3315 100644 --- a/apps/files_sharing/l10n/ja.js +++ b/apps/files_sharing/l10n/ja.js @@ -38,10 +38,23 @@ OC.L10N.register( "Public shared file %1$s was downloaded" : "公開共有ファイル %1$s がダウンロードされました", "You shared %1$s with %2$s" : "あなたは %1$s を %2$s と共有しました", "You shared %1$s with group %2$s" : "あなたは %1$s をグループ %2$s と共有しました", + "%2$s shared %1$s with %3$s" : "%2$s は %1$s を %3$s と共有しました", + "%2$s shared %1$s with group %3$s" : "%2$s は %1$s をグループ %3$s と共有しました", + "%2$s shared %1$s via link" : "%2$s はリンク経由で %1$s を共有しました", "%2$s shared %1$s with you" : "%2$s は %1$s をあなたと共有しました", "You shared %1$s via link" : "リンク経由で %1$s を共有しています", + "Downloaded via public link" : "公開リンクからダウンロードしました", + "Shared with %2$s" : "%2$s と共有しました", + "Shared with group %2$s" : "%2$s グループと共有しました", + "Shared with %3$s by %2$s" : "%3$s と %2$s で共有しました", + "Shared with group %3$s by %2$s" : "%3$s グループと %2$s で共有しました", + "Shared via link by %2$s" : "リンク経由で %2$s が共有しました", + "Shared by %2$s" : "%2$s が共有", + "Shared via public link" : "公開リンク経由で共有中", "Shares" : "共有", + "You received %2$s as a remote share from %1$s" : "%1$s からリモート共有として %2$s を受け取りました。", "Accept" : "承諾", + "Decline" : "拒否《はてなキーワード》", "Share with me through my #ownCloud Federated Cloud ID, see %s" : "#ownCloud の「クラウド連携ID」で私と共有できます。こちらを見てください。%s", "Share with me through my #ownCloud Federated Cloud ID" : "#ownCloud の「クラウド連携ID」で私と共有できます。", "This share is password-protected" : "この共有はパスワードで保護されています", @@ -67,6 +80,7 @@ OC.L10N.register( "Federated Cloud" : "クラウド連携", "Your Federated Cloud ID:" : "あなたのクラウド連携ID:", "Share it:" : "以下で共有:", + "Add to your website" : "ウェブサイトに追加", "Share with me via ownCloud" : "OwnCloud経由で共有", "HTML Code:" : "HTMLコード:" }, diff --git a/apps/files_sharing/l10n/ja.json b/apps/files_sharing/l10n/ja.json index 65d762871de..8f9efffb782 100644 --- a/apps/files_sharing/l10n/ja.json +++ b/apps/files_sharing/l10n/ja.json @@ -36,10 +36,23 @@ "Public shared file %1$s was downloaded" : "公開共有ファイル %1$s がダウンロードされました", "You shared %1$s with %2$s" : "あなたは %1$s を %2$s と共有しました", "You shared %1$s with group %2$s" : "あなたは %1$s をグループ %2$s と共有しました", + "%2$s shared %1$s with %3$s" : "%2$s は %1$s を %3$s と共有しました", + "%2$s shared %1$s with group %3$s" : "%2$s は %1$s をグループ %3$s と共有しました", + "%2$s shared %1$s via link" : "%2$s はリンク経由で %1$s を共有しました", "%2$s shared %1$s with you" : "%2$s は %1$s をあなたと共有しました", "You shared %1$s via link" : "リンク経由で %1$s を共有しています", + "Downloaded via public link" : "公開リンクからダウンロードしました", + "Shared with %2$s" : "%2$s と共有しました", + "Shared with group %2$s" : "%2$s グループと共有しました", + "Shared with %3$s by %2$s" : "%3$s と %2$s で共有しました", + "Shared with group %3$s by %2$s" : "%3$s グループと %2$s で共有しました", + "Shared via link by %2$s" : "リンク経由で %2$s が共有しました", + "Shared by %2$s" : "%2$s が共有", + "Shared via public link" : "公開リンク経由で共有中", "Shares" : "共有", + "You received %2$s as a remote share from %1$s" : "%1$s からリモート共有として %2$s を受け取りました。", "Accept" : "承諾", + "Decline" : "拒否《はてなキーワード》", "Share with me through my #ownCloud Federated Cloud ID, see %s" : "#ownCloud の「クラウド連携ID」で私と共有できます。こちらを見てください。%s", "Share with me through my #ownCloud Federated Cloud ID" : "#ownCloud の「クラウド連携ID」で私と共有できます。", "This share is password-protected" : "この共有はパスワードで保護されています", @@ -65,6 +78,7 @@ "Federated Cloud" : "クラウド連携", "Your Federated Cloud ID:" : "あなたのクラウド連携ID:", "Share it:" : "以下で共有:", + "Add to your website" : "ウェブサイトに追加", "Share with me via ownCloud" : "OwnCloud経由で共有", "HTML Code:" : "HTMLコード:" },"pluralForm" :"nplurals=1; plural=0;" diff --git a/apps/files_sharing/l10n/lt_LT.js b/apps/files_sharing/l10n/lt_LT.js index 897bfe457d1..93848326605 100644 --- a/apps/files_sharing/l10n/lt_LT.js +++ b/apps/files_sharing/l10n/lt_LT.js @@ -1,27 +1,87 @@ OC.L10N.register( "files_sharing", { + "Server to server sharing is not enabled on this server" : "Serveris - serveris dalinimasis neįjungtas šiame serveryje", + "The mountpoint name contains invalid characters." : "Prijungimo taškas su neleistinais simboliais.", + "Invalid or untrusted SSL certificate" : "Netinkamas arba nepatikimas SSL sertifikatas", + "Could not authenticate to remote share, password might be wrong" : "Nepavyko identifikuotis serveryje, gal netinkamas slaptažodis", + "Storage not valid" : "Talpykla negalioja", + "Couldn't add remote share" : "Nepavyko pridėti nutolusio dalijimosi", + "Shared with you" : "Pasidalinta su tavimi", + "Shared with others" : "Pasidalinta su kitais", + "Shared by link" : "Pasidalinta su nuoroda", + "Nothing shared with you yet" : "Kol kas niekas su tavimi nesidalijama", + "Files and folders others share with you will show up here" : "Failai ir aplankai kurie dalinami ir tau, bus rodomi čia", + "Nothing shared yet" : "Niekas nepasidalinta", + "Files and folders you share will show up here" : "Failai ir aplankai kuriais daliniesi bus rodomi čia", + "No shared links" : "Nėra pasidalinimų nuoroda", + "Files and folders you share by link will show up here" : "Failai ir aplankai kuriais daliniesi su nuoroda bus rodomi čia", + "Do you want to add the remote share {name} from {owner}@{remote}?" : "Ar nori pridėti nutolusį dalijimąsi {name} nuo {owner}@{remote}?", + "Remote share" : "Nutolęs dalinimasis", + "Remote share password" : "Nutolusio dalijimosi slaptažodis", "Cancel" : "Atšaukti", + "Add remote share" : "Pridėti nutolusi dalijimąsi", + "You can upload into this folder" : "Gali įkelti į šį aplanką", + "No ownCloud installation (7 or higher) found at {remote}" : "Nerastas ownCloud (7 ar aukštesnė versiją) {remote} serveryje.", + "Invalid ownCloud url" : "Neteisinga ownCloud nuoroda", "Shared by" : "Dalinasi", "Sharing" : "Dalijimasis", "A file or folder has been <strong>shared</strong>" : "Failas ar aplankas buvo <strong>pasidalintas</strong>", + "A file or folder was shared from <strong>another server</strong>" : "Failas ar aplankas buvo pasidalintas iš <strong>kito serverio</strong>", + "A public shared file or folder was <strong>downloaded</strong>" : "Viešai pasidalintas failas ar aplankas <strong>parsiųstas</strong>", + "You received a new remote share %2$s from %1$s" : "Gavote naują nutolusį dalijimąsi %2$s nuo %1$s", + "You received a new remote share from %s" : "Gavote naują nutolusį dalijimąsi nuo %s", + "%1$s accepted remote share %2$s" : "%1$s priėmė nutolusį dalijimąsi %2$s", + "%1$s declined remote share %2$s" : "%1$s atmetė nutolusį dalijimąsi %2$s", + "%1$s unshared %2$s from you" : "%1$s nebesidalina %2$s su tavimi", + "Public shared folder %1$s was downloaded" : "Viešas dalijimosi aplankas %1$s parsiųstas", + "Public shared file %1$s was downloaded" : "Viešai dalinamas failas %1$s parsiųstas", "You shared %1$s with %2$s" : "Jūs pasidalinote %1$s su %2$s", "You shared %1$s with group %2$s" : "Jūs pasidalinote %1$s su grupe %2$s", + "%2$s shared %1$s with %3$s" : "%2$s pasidalino %1$s su %3$s", + "%2$s shared %1$s with group %3$s" : "%2$s pasidalino %1$s su grupe %3$s", + "%2$s shared %1$s via link" : "%2$s pasidalino %1$s nuoroda", "%2$s shared %1$s with you" : "%2$s pasidalino %1$s su jumis", "You shared %1$s via link" : "Pasidalinote %1$s per nuorodą", + "Downloaded via public link" : "Atsiųsti per viešą nuorodą", + "Shared with %2$s" : "Pasidalinta su %2$s", + "Shared with group %2$s" : "Pasidalinta su grupe %2$s", + "Shared with %3$s by %2$s" : "%2$s pasidalino %3$s", + "Shared with group %3$s by %2$s" : "%2$s pasidalino su grupe %3$s", + "Shared via link by %2$s" : "%2$s pasidalino nuoroda", + "Shared by %2$s" : "Pasidalino %2$s", + "Shared via public link" : "Pasidalinta vieša nuoroda", "Shares" : "Dalijimaisi", + "You received %2$s as a remote share from %1$s" : "Gavai dalijimąsi %2$s nuo %1$s", + "Accept" : "Priimti", + "Decline" : "Atmesti", + "Share with me through my #ownCloud Federated Cloud ID, see %s" : "Pasidalink su manimi per #ownCloud padebesius, plačiau %s", + "Share with me through my #ownCloud Federated Cloud ID" : "Pasidalink su manimi per #ownCloud padebesius", "This share is password-protected" : "Turinys apsaugotas slaptažodžiu", "The password is wrong. Try again." : "Netinka slaptažodis: Bandykite dar kartą.", "Password" : "Slaptažodis", "No entries found in this folder" : "Nerasta įrašų šiame aplanke", "Name" : "Pavadinimas", + "Share time" : "Dalijimosi laikas", "Sorry, this link doesn’t seem to work anymore." : "Atleiskite, panašu, kad nuoroda yra neveiksni.", "Reasons might be:" : "Galimos priežastys:", "the item was removed" : "elementas buvo pašalintas", "the link expired" : "baigėsi nuorodos galiojimo laikas", "sharing is disabled" : "dalinimasis yra išjungtas", "For more info, please ask the person who sent this link." : "Dėl tikslesnės informacijos susisiekite su asmeniu atsiuntusiu nuorodą.", + "Add to your ownCloud" : "Pridėti prie tavo ownCloud", "Download" : "Atsisiųsti", - "Direct link" : "Tiesioginė nuoroda" + "Download %s" : "Atsiųsti %s", + "Direct link" : "Tiesioginė nuoroda", + "Federated Cloud Sharing" : "Viešas dalijimasis padebesiu", + "Open documentation" : "Atidaryti dokumentą", + "Allow users on this server to send shares to other servers" : "Leisti vartotojams šiame serveryje dalintis su kitais serveriais", + "Allow users on this server to receive shares from other servers" : "Leisti vartotojams šiame serveryje priimti dalijimusis iš kitų serverių", + "Federated Cloud" : "Viešas debesis", + "Your Federated Cloud ID:" : "Tavo debesies ID:", + "Share it:" : "Pasidalink:", + "Add to your website" : "Pridėti tavo puslapį", + "Share with me via ownCloud" : "Pasidalink su manimi per ownCloud", + "HTML Code:" : "HTML kodas:" }, "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_sharing/l10n/lt_LT.json b/apps/files_sharing/l10n/lt_LT.json index c27668b24c7..6d777024052 100644 --- a/apps/files_sharing/l10n/lt_LT.json +++ b/apps/files_sharing/l10n/lt_LT.json @@ -1,25 +1,85 @@ { "translations": { + "Server to server sharing is not enabled on this server" : "Serveris - serveris dalinimasis neįjungtas šiame serveryje", + "The mountpoint name contains invalid characters." : "Prijungimo taškas su neleistinais simboliais.", + "Invalid or untrusted SSL certificate" : "Netinkamas arba nepatikimas SSL sertifikatas", + "Could not authenticate to remote share, password might be wrong" : "Nepavyko identifikuotis serveryje, gal netinkamas slaptažodis", + "Storage not valid" : "Talpykla negalioja", + "Couldn't add remote share" : "Nepavyko pridėti nutolusio dalijimosi", + "Shared with you" : "Pasidalinta su tavimi", + "Shared with others" : "Pasidalinta su kitais", + "Shared by link" : "Pasidalinta su nuoroda", + "Nothing shared with you yet" : "Kol kas niekas su tavimi nesidalijama", + "Files and folders others share with you will show up here" : "Failai ir aplankai kurie dalinami ir tau, bus rodomi čia", + "Nothing shared yet" : "Niekas nepasidalinta", + "Files and folders you share will show up here" : "Failai ir aplankai kuriais daliniesi bus rodomi čia", + "No shared links" : "Nėra pasidalinimų nuoroda", + "Files and folders you share by link will show up here" : "Failai ir aplankai kuriais daliniesi su nuoroda bus rodomi čia", + "Do you want to add the remote share {name} from {owner}@{remote}?" : "Ar nori pridėti nutolusį dalijimąsi {name} nuo {owner}@{remote}?", + "Remote share" : "Nutolęs dalinimasis", + "Remote share password" : "Nutolusio dalijimosi slaptažodis", "Cancel" : "Atšaukti", + "Add remote share" : "Pridėti nutolusi dalijimąsi", + "You can upload into this folder" : "Gali įkelti į šį aplanką", + "No ownCloud installation (7 or higher) found at {remote}" : "Nerastas ownCloud (7 ar aukštesnė versiją) {remote} serveryje.", + "Invalid ownCloud url" : "Neteisinga ownCloud nuoroda", "Shared by" : "Dalinasi", "Sharing" : "Dalijimasis", "A file or folder has been <strong>shared</strong>" : "Failas ar aplankas buvo <strong>pasidalintas</strong>", + "A file or folder was shared from <strong>another server</strong>" : "Failas ar aplankas buvo pasidalintas iš <strong>kito serverio</strong>", + "A public shared file or folder was <strong>downloaded</strong>" : "Viešai pasidalintas failas ar aplankas <strong>parsiųstas</strong>", + "You received a new remote share %2$s from %1$s" : "Gavote naują nutolusį dalijimąsi %2$s nuo %1$s", + "You received a new remote share from %s" : "Gavote naują nutolusį dalijimąsi nuo %s", + "%1$s accepted remote share %2$s" : "%1$s priėmė nutolusį dalijimąsi %2$s", + "%1$s declined remote share %2$s" : "%1$s atmetė nutolusį dalijimąsi %2$s", + "%1$s unshared %2$s from you" : "%1$s nebesidalina %2$s su tavimi", + "Public shared folder %1$s was downloaded" : "Viešas dalijimosi aplankas %1$s parsiųstas", + "Public shared file %1$s was downloaded" : "Viešai dalinamas failas %1$s parsiųstas", "You shared %1$s with %2$s" : "Jūs pasidalinote %1$s su %2$s", "You shared %1$s with group %2$s" : "Jūs pasidalinote %1$s su grupe %2$s", + "%2$s shared %1$s with %3$s" : "%2$s pasidalino %1$s su %3$s", + "%2$s shared %1$s with group %3$s" : "%2$s pasidalino %1$s su grupe %3$s", + "%2$s shared %1$s via link" : "%2$s pasidalino %1$s nuoroda", "%2$s shared %1$s with you" : "%2$s pasidalino %1$s su jumis", "You shared %1$s via link" : "Pasidalinote %1$s per nuorodą", + "Downloaded via public link" : "Atsiųsti per viešą nuorodą", + "Shared with %2$s" : "Pasidalinta su %2$s", + "Shared with group %2$s" : "Pasidalinta su grupe %2$s", + "Shared with %3$s by %2$s" : "%2$s pasidalino %3$s", + "Shared with group %3$s by %2$s" : "%2$s pasidalino su grupe %3$s", + "Shared via link by %2$s" : "%2$s pasidalino nuoroda", + "Shared by %2$s" : "Pasidalino %2$s", + "Shared via public link" : "Pasidalinta vieša nuoroda", "Shares" : "Dalijimaisi", + "You received %2$s as a remote share from %1$s" : "Gavai dalijimąsi %2$s nuo %1$s", + "Accept" : "Priimti", + "Decline" : "Atmesti", + "Share with me through my #ownCloud Federated Cloud ID, see %s" : "Pasidalink su manimi per #ownCloud padebesius, plačiau %s", + "Share with me through my #ownCloud Federated Cloud ID" : "Pasidalink su manimi per #ownCloud padebesius", "This share is password-protected" : "Turinys apsaugotas slaptažodžiu", "The password is wrong. Try again." : "Netinka slaptažodis: Bandykite dar kartą.", "Password" : "Slaptažodis", "No entries found in this folder" : "Nerasta įrašų šiame aplanke", "Name" : "Pavadinimas", + "Share time" : "Dalijimosi laikas", "Sorry, this link doesn’t seem to work anymore." : "Atleiskite, panašu, kad nuoroda yra neveiksni.", "Reasons might be:" : "Galimos priežastys:", "the item was removed" : "elementas buvo pašalintas", "the link expired" : "baigėsi nuorodos galiojimo laikas", "sharing is disabled" : "dalinimasis yra išjungtas", "For more info, please ask the person who sent this link." : "Dėl tikslesnės informacijos susisiekite su asmeniu atsiuntusiu nuorodą.", + "Add to your ownCloud" : "Pridėti prie tavo ownCloud", "Download" : "Atsisiųsti", - "Direct link" : "Tiesioginė nuoroda" + "Download %s" : "Atsiųsti %s", + "Direct link" : "Tiesioginė nuoroda", + "Federated Cloud Sharing" : "Viešas dalijimasis padebesiu", + "Open documentation" : "Atidaryti dokumentą", + "Allow users on this server to send shares to other servers" : "Leisti vartotojams šiame serveryje dalintis su kitais serveriais", + "Allow users on this server to receive shares from other servers" : "Leisti vartotojams šiame serveryje priimti dalijimusis iš kitų serverių", + "Federated Cloud" : "Viešas debesis", + "Your Federated Cloud ID:" : "Tavo debesies ID:", + "Share it:" : "Pasidalink:", + "Add to your website" : "Pridėti tavo puslapį", + "Share with me via ownCloud" : "Pasidalink su manimi per ownCloud", + "HTML Code:" : "HTML kodas:" },"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_sharing/l10n/lv.js b/apps/files_sharing/l10n/lv.js index 9c2f4d3fe48..f59a8d0b395 100644 --- a/apps/files_sharing/l10n/lv.js +++ b/apps/files_sharing/l10n/lv.js @@ -56,6 +56,7 @@ OC.L10N.register( "Download %s" : "Lejupielādēt %s", "Direct link" : "Tiešā saite", "Federated Cloud Sharing" : "Federatīva mākoņkoplietošana", + "Open documentation" : "Atvērt dokumentāciju", "Allow users on this server to send shares to other servers" : "Atļaut šī servera lietotājiem sūtīt koplietotnes uz citiem serveriem", "Allow users on this server to receive shares from other servers" : "Atļaut šī servera lietotājiem saņem koplietotnes no citiem serveriem" }, diff --git a/apps/files_sharing/l10n/lv.json b/apps/files_sharing/l10n/lv.json index abc16e3ad68..7c7e43cce4b 100644 --- a/apps/files_sharing/l10n/lv.json +++ b/apps/files_sharing/l10n/lv.json @@ -54,6 +54,7 @@ "Download %s" : "Lejupielādēt %s", "Direct link" : "Tiešā saite", "Federated Cloud Sharing" : "Federatīva mākoņkoplietošana", + "Open documentation" : "Atvērt dokumentāciju", "Allow users on this server to send shares to other servers" : "Atļaut šī servera lietotājiem sūtīt koplietotnes uz citiem serveriem", "Allow users on this server to receive shares from other servers" : "Atļaut šī servera lietotājiem saņem koplietotnes no citiem serveriem" },"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);" diff --git a/apps/files_sharing/l10n/nb_NO.js b/apps/files_sharing/l10n/nb_NO.js index a8f7fbdbc9b..4f7fb08ef16 100644 --- a/apps/files_sharing/l10n/nb_NO.js +++ b/apps/files_sharing/l10n/nb_NO.js @@ -43,6 +43,14 @@ OC.L10N.register( "%2$s shared %1$s via link" : "%2$s delte %1$s via lenke", "%2$s shared %1$s with you" : "%2$s delte %1$s med deg", "You shared %1$s via link" : "Du delte %1$s via lenke", + "Downloaded via public link" : "Nedlastet via offentlig lenke", + "Shared with %2$s" : "Delt med %2$s", + "Shared with group %2$s" : "Delt med gruppe %2$s", + "Shared with %3$s by %2$s" : "Delt med %3$s av %2$s", + "Shared with group %3$s by %2$s" : "Delt med gruppe %3$s av %2$s", + "Shared via link by %2$s" : "Delt via lenke av %2$s", + "Shared by %2$s" : "Delt av %2$s", + "Shared via public link" : "Delt via offentlig lenke", "Shares" : "Delinger", "You received %2$s as a remote share from %1$s" : "Du mottok %2$s som en ekstern deling fra %1$s", "Accept" : "Aksepter", diff --git a/apps/files_sharing/l10n/nb_NO.json b/apps/files_sharing/l10n/nb_NO.json index e9c67955708..e75f095f354 100644 --- a/apps/files_sharing/l10n/nb_NO.json +++ b/apps/files_sharing/l10n/nb_NO.json @@ -41,6 +41,14 @@ "%2$s shared %1$s via link" : "%2$s delte %1$s via lenke", "%2$s shared %1$s with you" : "%2$s delte %1$s med deg", "You shared %1$s via link" : "Du delte %1$s via lenke", + "Downloaded via public link" : "Nedlastet via offentlig lenke", + "Shared with %2$s" : "Delt med %2$s", + "Shared with group %2$s" : "Delt med gruppe %2$s", + "Shared with %3$s by %2$s" : "Delt med %3$s av %2$s", + "Shared with group %3$s by %2$s" : "Delt med gruppe %3$s av %2$s", + "Shared via link by %2$s" : "Delt via lenke av %2$s", + "Shared by %2$s" : "Delt av %2$s", + "Shared via public link" : "Delt via offentlig lenke", "Shares" : "Delinger", "You received %2$s as a remote share from %1$s" : "Du mottok %2$s som en ekstern deling fra %1$s", "Accept" : "Aksepter", diff --git a/apps/files_sharing/l10n/oc.js b/apps/files_sharing/l10n/oc.js index 54924e11121..6a1329bf5bd 100644 --- a/apps/files_sharing/l10n/oc.js +++ b/apps/files_sharing/l10n/oc.js @@ -43,6 +43,14 @@ OC.L10N.register( "%2$s shared %1$s via link" : "%2$s a partejat %1$s per ligam public", "%2$s shared %1$s with you" : "%2$s a partejat %1$s amb vos", "You shared %1$s via link" : "Avètz partejat %1$s per ligam public", + "Downloaded via public link" : "Telecargat per ligam public", + "Shared with %2$s" : "Partejat amb %2$s", + "Shared with group %2$s" : "Partejat amb lo grop %2$s", + "Shared with %3$s by %2$s" : "Partejat amb %3$s per %2$s", + "Shared with group %3$s by %2$s" : "Partejat amb lo grop %3$s per %2$s", + "Shared via link by %2$s" : "Partejat via ligam per %2$s", + "Shared by %2$s" : "Partejat per %2$s", + "Shared via public link" : "Partejat per ligam public", "Shares" : "Partiments", "You received %2$s as a remote share from %1$s" : "Avètz recebut %2$s en tant que partiment distant per %1$s", "Accept" : "Acceptar", diff --git a/apps/files_sharing/l10n/oc.json b/apps/files_sharing/l10n/oc.json index 2194f0aa1d2..591090742c6 100644 --- a/apps/files_sharing/l10n/oc.json +++ b/apps/files_sharing/l10n/oc.json @@ -41,6 +41,14 @@ "%2$s shared %1$s via link" : "%2$s a partejat %1$s per ligam public", "%2$s shared %1$s with you" : "%2$s a partejat %1$s amb vos", "You shared %1$s via link" : "Avètz partejat %1$s per ligam public", + "Downloaded via public link" : "Telecargat per ligam public", + "Shared with %2$s" : "Partejat amb %2$s", + "Shared with group %2$s" : "Partejat amb lo grop %2$s", + "Shared with %3$s by %2$s" : "Partejat amb %3$s per %2$s", + "Shared with group %3$s by %2$s" : "Partejat amb lo grop %3$s per %2$s", + "Shared via link by %2$s" : "Partejat via ligam per %2$s", + "Shared by %2$s" : "Partejat per %2$s", + "Shared via public link" : "Partejat per ligam public", "Shares" : "Partiments", "You received %2$s as a remote share from %1$s" : "Avètz recebut %2$s en tant que partiment distant per %1$s", "Accept" : "Acceptar", diff --git a/apps/files_sharing/l10n/pt_PT.js b/apps/files_sharing/l10n/pt_PT.js index dc501ebe048..c0a79ac58fa 100644 --- a/apps/files_sharing/l10n/pt_PT.js +++ b/apps/files_sharing/l10n/pt_PT.js @@ -38,10 +38,23 @@ OC.L10N.register( "Public shared file %1$s was downloaded" : "Foi transferido o ficheiro %1$s partilhado publicamente", "You shared %1$s with %2$s" : "Partilhou %1$s com %2$s", "You shared %1$s with group %2$s" : "Partilhou %1$s com o grupo %2$s", + "%2$s shared %1$s with %3$s" : "%2$s partilhou %1$s com %3$s", + "%2$s shared %1$s with group %3$s" : "%2$s partilhou %1$s com o grupo %3$s", + "%2$s shared %1$s via link" : "%2$s partilhou %1$s via hiperligação", "%2$s shared %1$s with you" : "%2$s partilhou %1$s consigo", "You shared %1$s via link" : "Partilhou %1$s através de uma hiperligação", + "Downloaded via public link" : "Transferido via hiperligação pública", + "Shared with %2$s" : "Partilhado com %2$s", + "Shared with group %2$s" : "Partilhado com o grupo %2$s", + "Shared with %3$s by %2$s" : "Partilhado com %3$s por %2$s", + "Shared with group %3$s by %2$s" : "Partilhado com o grupo %3$s por %2$s", + "Shared via link by %2$s" : "Partilhado via hiperligação por %2$s", + "Shared by %2$s" : "Partilhado por %2$s", + "Shared via public link" : "Partilhado via hiperligação pública", "Shares" : "Partilhas", + "You received %2$s as a remote share from %1$s" : "Recebeu %2$s como uma partilha remota de %1$s", "Accept" : "Aceitar", + "Decline" : "Recusar", "Share with me through my #ownCloud Federated Cloud ID, see %s" : "Partilhe comigo através da minha Id. da Nuvem Federada #ownCloud, veja %s", "Share with me through my #ownCloud Federated Cloud ID" : "Partilhe comigo através da minha Id. da Nuvem Federada #ownCloud", "This share is password-protected" : "Esta partilha está protegida por senha", diff --git a/apps/files_sharing/l10n/pt_PT.json b/apps/files_sharing/l10n/pt_PT.json index 9c5bc14e610..f57f939e5cb 100644 --- a/apps/files_sharing/l10n/pt_PT.json +++ b/apps/files_sharing/l10n/pt_PT.json @@ -36,10 +36,23 @@ "Public shared file %1$s was downloaded" : "Foi transferido o ficheiro %1$s partilhado publicamente", "You shared %1$s with %2$s" : "Partilhou %1$s com %2$s", "You shared %1$s with group %2$s" : "Partilhou %1$s com o grupo %2$s", + "%2$s shared %1$s with %3$s" : "%2$s partilhou %1$s com %3$s", + "%2$s shared %1$s with group %3$s" : "%2$s partilhou %1$s com o grupo %3$s", + "%2$s shared %1$s via link" : "%2$s partilhou %1$s via hiperligação", "%2$s shared %1$s with you" : "%2$s partilhou %1$s consigo", "You shared %1$s via link" : "Partilhou %1$s através de uma hiperligação", + "Downloaded via public link" : "Transferido via hiperligação pública", + "Shared with %2$s" : "Partilhado com %2$s", + "Shared with group %2$s" : "Partilhado com o grupo %2$s", + "Shared with %3$s by %2$s" : "Partilhado com %3$s por %2$s", + "Shared with group %3$s by %2$s" : "Partilhado com o grupo %3$s por %2$s", + "Shared via link by %2$s" : "Partilhado via hiperligação por %2$s", + "Shared by %2$s" : "Partilhado por %2$s", + "Shared via public link" : "Partilhado via hiperligação pública", "Shares" : "Partilhas", + "You received %2$s as a remote share from %1$s" : "Recebeu %2$s como uma partilha remota de %1$s", "Accept" : "Aceitar", + "Decline" : "Recusar", "Share with me through my #ownCloud Federated Cloud ID, see %s" : "Partilhe comigo através da minha Id. da Nuvem Federada #ownCloud, veja %s", "Share with me through my #ownCloud Federated Cloud ID" : "Partilhe comigo através da minha Id. da Nuvem Federada #ownCloud", "This share is password-protected" : "Esta partilha está protegida por senha", diff --git a/apps/files_sharing/l10n/sk_SK.js b/apps/files_sharing/l10n/sk_SK.js index 1f109b739e5..465d50d4163 100644 --- a/apps/files_sharing/l10n/sk_SK.js +++ b/apps/files_sharing/l10n/sk_SK.js @@ -43,6 +43,14 @@ OC.L10N.register( "%2$s shared %1$s via link" : "%2$s zdieľané %1$s pomocou linky", "%2$s shared %1$s with you" : "%2$s vám zdieľal %1$s", "You shared %1$s via link" : "Zdieľate %1$s prostredníctvom odkazu", + "Downloaded via public link" : "Stiahnuté prostredníctvom verejného odkazu", + "Shared with %2$s" : "Zdieľané s %2$s", + "Shared with group %2$s" : "Zdieľané so skupinou %2$s", + "Shared with %3$s by %2$s" : "Zdieľané s %3$s prostredníctvom %2$s", + "Shared with group %3$s by %2$s" : "Zdieľané so skupinou %3$s prostredníctvom %2$s", + "Shared via link by %2$s" : "Zdieľané prostredníctvom odkazu s %2$s", + "Shared by %2$s" : "Zdieľané s %2$s", + "Shared via public link" : "Zdieľané prostredníctvom verejného odkazu", "Shares" : "Zdieľanie", "You received %2$s as a remote share from %1$s" : "Dostali ste %2$s, ako vzdialené zdieľanie od %1$s", "Accept" : "Schváliť", diff --git a/apps/files_sharing/l10n/sk_SK.json b/apps/files_sharing/l10n/sk_SK.json index dab3d4105c4..80af61adb2b 100644 --- a/apps/files_sharing/l10n/sk_SK.json +++ b/apps/files_sharing/l10n/sk_SK.json @@ -41,6 +41,14 @@ "%2$s shared %1$s via link" : "%2$s zdieľané %1$s pomocou linky", "%2$s shared %1$s with you" : "%2$s vám zdieľal %1$s", "You shared %1$s via link" : "Zdieľate %1$s prostredníctvom odkazu", + "Downloaded via public link" : "Stiahnuté prostredníctvom verejného odkazu", + "Shared with %2$s" : "Zdieľané s %2$s", + "Shared with group %2$s" : "Zdieľané so skupinou %2$s", + "Shared with %3$s by %2$s" : "Zdieľané s %3$s prostredníctvom %2$s", + "Shared with group %3$s by %2$s" : "Zdieľané so skupinou %3$s prostredníctvom %2$s", + "Shared via link by %2$s" : "Zdieľané prostredníctvom odkazu s %2$s", + "Shared by %2$s" : "Zdieľané s %2$s", + "Shared via public link" : "Zdieľané prostredníctvom verejného odkazu", "Shares" : "Zdieľanie", "You received %2$s as a remote share from %1$s" : "Dostali ste %2$s, ako vzdialené zdieľanie od %1$s", "Accept" : "Schváliť", diff --git a/apps/files_sharing/l10n/sq.js b/apps/files_sharing/l10n/sq.js index 6127399e1c8..413214d58de 100644 --- a/apps/files_sharing/l10n/sq.js +++ b/apps/files_sharing/l10n/sq.js @@ -7,9 +7,9 @@ OC.L10N.register( "Could not authenticate to remote share, password might be wrong" : "S’bëri dot mirëfilltësimin te ndarja e largët, fjalëkalimi mund të jetë i gabuar", "Storage not valid" : "Depozitë jo e vlefshme", "Couldn't add remote share" : "S’shtoi dotë ndarje të largët", - "Shared with you" : "Ndarë me ju", - "Shared with others" : "Ndarë me të tjerët", - "Shared by link" : "Ndarë me lidhje", + "Shared with you" : "Të ndara me ju", + "Shared with others" : "Të ndara me të tjerët", + "Shared by link" : "Të ndara me lidhje", "Nothing shared with you yet" : "Ende pa ndarë gjë me ju", "Files and folders others share with you will show up here" : "Këtu do të shfaqen kartelat dhe dosjet që të jerët ndajnë me ju", "Nothing shared yet" : "Ende pa ndarë gjë", @@ -41,7 +41,7 @@ OC.L10N.register( "%2$s shared %1$s with group %3$s" : "%2$s ndau %1$s me grupin %3$s", "%2$s shared %1$s via link" : "%2$s ndau %1$s përmes një lidhjeje", "%2$s shared %1$s with you" : "%2$s ndau %1$s me ju", - "You shared %1$s via link" : "E ndatë %1$s përmes një lidhjeje", + "You shared %1$s via link" : "Ndatë %1$s përmes një lidhjeje", "Downloaded via public link" : "Shkarkuar përmes një lidhjeje publike", "Shared with %2$s" : "U nda me %2$s", "Shared with group %2$s" : "U nda me grupin %2$s", @@ -61,6 +61,7 @@ OC.L10N.register( "Password" : "Fjalëkalim", "No entries found in this folder" : "S’u gjetën zëra në këtë dosje", "Name" : "Emër", + "Share time" : "Kohë ndarjeje", "Sorry, this link doesn’t seem to work anymore." : "Na ndjeni, kjo lidhje duket se nuk funksionon më.", "Reasons might be:" : "Arsyet mund të jenë:", "the item was removed" : "objekti është hequr", diff --git a/apps/files_sharing/l10n/sq.json b/apps/files_sharing/l10n/sq.json index 7c5cfcc068d..8722966f5da 100644 --- a/apps/files_sharing/l10n/sq.json +++ b/apps/files_sharing/l10n/sq.json @@ -5,9 +5,9 @@ "Could not authenticate to remote share, password might be wrong" : "S’bëri dot mirëfilltësimin te ndarja e largët, fjalëkalimi mund të jetë i gabuar", "Storage not valid" : "Depozitë jo e vlefshme", "Couldn't add remote share" : "S’shtoi dotë ndarje të largët", - "Shared with you" : "Ndarë me ju", - "Shared with others" : "Ndarë me të tjerët", - "Shared by link" : "Ndarë me lidhje", + "Shared with you" : "Të ndara me ju", + "Shared with others" : "Të ndara me të tjerët", + "Shared by link" : "Të ndara me lidhje", "Nothing shared with you yet" : "Ende pa ndarë gjë me ju", "Files and folders others share with you will show up here" : "Këtu do të shfaqen kartelat dhe dosjet që të jerët ndajnë me ju", "Nothing shared yet" : "Ende pa ndarë gjë", @@ -39,7 +39,7 @@ "%2$s shared %1$s with group %3$s" : "%2$s ndau %1$s me grupin %3$s", "%2$s shared %1$s via link" : "%2$s ndau %1$s përmes një lidhjeje", "%2$s shared %1$s with you" : "%2$s ndau %1$s me ju", - "You shared %1$s via link" : "E ndatë %1$s përmes një lidhjeje", + "You shared %1$s via link" : "Ndatë %1$s përmes një lidhjeje", "Downloaded via public link" : "Shkarkuar përmes një lidhjeje publike", "Shared with %2$s" : "U nda me %2$s", "Shared with group %2$s" : "U nda me grupin %2$s", @@ -59,6 +59,7 @@ "Password" : "Fjalëkalim", "No entries found in this folder" : "S’u gjetën zëra në këtë dosje", "Name" : "Emër", + "Share time" : "Kohë ndarjeje", "Sorry, this link doesn’t seem to work anymore." : "Na ndjeni, kjo lidhje duket se nuk funksionon më.", "Reasons might be:" : "Arsyet mund të jenë:", "the item was removed" : "objekti është hequr", diff --git a/apps/files_sharing/l10n/sv.js b/apps/files_sharing/l10n/sv.js index 9b1d9ccb591..47f5f6b368c 100644 --- a/apps/files_sharing/l10n/sv.js +++ b/apps/files_sharing/l10n/sv.js @@ -40,6 +40,7 @@ OC.L10N.register( "This share is password-protected" : "Den här delningen är lösenordsskyddad", "The password is wrong. Try again." : "Lösenordet är fel. Försök igen.", "Password" : "Lösenord", + "No entries found in this folder" : "nga Filer hittades i denna mapp", "Name" : "Namn", "Share time" : "Delningstid", "Sorry, this link doesn’t seem to work anymore." : "Tyvärr, denna länk verkar inte fungera längre.", diff --git a/apps/files_sharing/l10n/sv.json b/apps/files_sharing/l10n/sv.json index 0d13069dfba..b20343b3594 100644 --- a/apps/files_sharing/l10n/sv.json +++ b/apps/files_sharing/l10n/sv.json @@ -38,6 +38,7 @@ "This share is password-protected" : "Den här delningen är lösenordsskyddad", "The password is wrong. Try again." : "Lösenordet är fel. Försök igen.", "Password" : "Lösenord", + "No entries found in this folder" : "nga Filer hittades i denna mapp", "Name" : "Namn", "Share time" : "Delningstid", "Sorry, this link doesn’t seem to work anymore." : "Tyvärr, denna länk verkar inte fungera längre.", diff --git a/apps/files_sharing/l10n/zh_TW.js b/apps/files_sharing/l10n/zh_TW.js index bc49d1d8a48..58d0398a1d5 100644 --- a/apps/files_sharing/l10n/zh_TW.js +++ b/apps/files_sharing/l10n/zh_TW.js @@ -2,24 +2,61 @@ OC.L10N.register( "files_sharing", { "Server to server sharing is not enabled on this server" : "伺服器對伺服器共享在這台伺服器上面並未啟用", + "The mountpoint name contains invalid characters." : "掛載的名稱含有不合法的字元", + "Invalid or untrusted SSL certificate" : "無效或是不信任的SSL憑證", + "Could not authenticate to remote share, password might be wrong" : "無法驗證遠端分享,可能是密碼錯誤", + "Storage not valid" : "儲存空間無法使用", "Couldn't add remote share" : "無法加入遠端分享", "Shared with you" : "與你分享", "Shared with others" : "與其他人分享", "Shared by link" : "由連結分享", + "Nothing shared with you yet" : "目前沒有任何與您分享的內容", + "Files and folders others share with you will show up here" : "與您分享的檔案與資料夾將會顯示在這裡", + "Nothing shared yet" : "目前沒有分享內容", + "Files and folders you share will show up here" : "您分享的檔案與資料夾將會顯示在這裡", + "No shared links" : "沒有已分享的連結", + "Files and folders you share by link will show up here" : "您分享的檔案與資料夾連結將會顯示在這裡", "Do you want to add the remote share {name} from {owner}@{remote}?" : "是否要加入來自 {owner}@{remote} 的遠端分享 {name} ?", "Remote share" : "遠端分享", "Remote share password" : "遠端分享密碼", "Cancel" : "取消", "Add remote share" : "加入遠端分享", + "You can upload into this folder" : "你可以上傳內容到此資料夾", + "No ownCloud installation (7 or higher) found at {remote}" : "沒有在 {remote} 找到 ownCloud (本版7 或 更新版)", "Invalid ownCloud url" : "無效的 ownCloud URL", "Shared by" : "由...分享", "Sharing" : "分享", "A file or folder has been <strong>shared</strong>" : "檔案或目錄已被 <strong>分享</strong>", + "A file or folder was shared from <strong>another server</strong>" : "檔案或目錄已被 <strong>其他伺服器</strong> 分享", + "A public shared file or folder was <strong>downloaded</strong>" : "共享檔案或目錄已被 <strong>下載</strong>", + "You received a new remote share %2$s from %1$s" : "您收到了一個遠端分享 %2$s 來自於 %1$s", + "You received a new remote share from %s" : "您收到了一個遠端分享來自於 %s", + "%1$s accepted remote share %2$s" : "%1$s 接受了遠端分享 %2$s", + "%1$s declined remote share %2$s" : "%1$s 拒絕了遠端分享 %2$s", + "%1$s unshared %2$s from you" : "%1$s 取消與你分享 %2$s", + "Public shared folder %1$s was downloaded" : "共享資料夾 %1$s 已被下載", + "Public shared file %1$s was downloaded" : "共享檔案 %1$s 已被下載", "You shared %1$s with %2$s" : "您與 %2$s 分享了 %1$s", "You shared %1$s with group %2$s" : "您與 %2$s 群組分享了 %1$s", + "%2$s shared %1$s with %3$s" : "%2$s 與 %3$s 分享了 %1$s", + "%2$s shared %1$s with group %3$s" : "%2$s 與群組 %3$s 分享了 %1$s", + "%2$s shared %1$s via link" : "%2$s 透過連結分享了 %1$s ", "%2$s shared %1$s with you" : "%2$s 與您分享了 %1$s", "You shared %1$s via link" : "您以連結分享了 %1$s", + "Downloaded via public link" : "透過公用連結下載", + "Shared with %2$s" : "與 %2$s 分享", + "Shared with group %2$s" : "與群組 %2$s 分享", + "Shared with %3$s by %2$s" : "透過 %2$s 與 %3$s 分享", + "Shared with group %3$s by %2$s" : "透過 %2$s 與群組 %3$s 分享", + "Shared via link by %2$s" : "%2$s 透過連結分享", + "Shared by %2$s" : "由 %2$s 分享", + "Shared via public link" : "透過公用連結分享", "Shares" : "分享", + "You received %2$s as a remote share from %1$s" : "您收到了來自%1$s的一個遠端分享 %2$s ", + "Accept" : "接受", + "Decline" : "拒絕", + "Share with me through my #ownCloud Federated Cloud ID, see %s" : "可透過我的 #ownCloud 聯合 ID,與我分享,請看 %s", + "Share with me through my #ownCloud Federated Cloud ID" : "可透過我的 #ownCloud 聯合 ID,與我分享", "This share is password-protected" : "這個分享有密碼保護", "The password is wrong. Try again." : "請檢查您的密碼並再試一次", "Password" : "密碼", @@ -36,6 +73,15 @@ OC.L10N.register( "Download" : "下載", "Download %s" : "下載 %s", "Direct link" : "直接連結", - "Federated Cloud Sharing" : "聯盟式雲端分享" + "Federated Cloud Sharing" : "聯盟式雲端分享", + "Open documentation" : "開啟文件", + "Allow users on this server to send shares to other servers" : "允許這台伺服器上的使用者發送分享給其他伺服器", + "Allow users on this server to receive shares from other servers" : "允許這台伺服器上的使用者發送接收來自其他伺服器的分享", + "Federated Cloud" : "聯盟式雲端", + "Your Federated Cloud ID:" : "您的雲端聯盟ID:", + "Share it:" : "分享它:", + "Add to your website" : "新增至您的網站", + "Share with me via ownCloud" : "透果ownCloud與我分享", + "HTML Code:" : "HTML 代碼:" }, "nplurals=1; plural=0;"); diff --git a/apps/files_sharing/l10n/zh_TW.json b/apps/files_sharing/l10n/zh_TW.json index 3567ed51df4..e73bbfa6574 100644 --- a/apps/files_sharing/l10n/zh_TW.json +++ b/apps/files_sharing/l10n/zh_TW.json @@ -1,23 +1,60 @@ { "translations": { "Server to server sharing is not enabled on this server" : "伺服器對伺服器共享在這台伺服器上面並未啟用", + "The mountpoint name contains invalid characters." : "掛載的名稱含有不合法的字元", + "Invalid or untrusted SSL certificate" : "無效或是不信任的SSL憑證", + "Could not authenticate to remote share, password might be wrong" : "無法驗證遠端分享,可能是密碼錯誤", + "Storage not valid" : "儲存空間無法使用", "Couldn't add remote share" : "無法加入遠端分享", "Shared with you" : "與你分享", "Shared with others" : "與其他人分享", "Shared by link" : "由連結分享", + "Nothing shared with you yet" : "目前沒有任何與您分享的內容", + "Files and folders others share with you will show up here" : "與您分享的檔案與資料夾將會顯示在這裡", + "Nothing shared yet" : "目前沒有分享內容", + "Files and folders you share will show up here" : "您分享的檔案與資料夾將會顯示在這裡", + "No shared links" : "沒有已分享的連結", + "Files and folders you share by link will show up here" : "您分享的檔案與資料夾連結將會顯示在這裡", "Do you want to add the remote share {name} from {owner}@{remote}?" : "是否要加入來自 {owner}@{remote} 的遠端分享 {name} ?", "Remote share" : "遠端分享", "Remote share password" : "遠端分享密碼", "Cancel" : "取消", "Add remote share" : "加入遠端分享", + "You can upload into this folder" : "你可以上傳內容到此資料夾", + "No ownCloud installation (7 or higher) found at {remote}" : "沒有在 {remote} 找到 ownCloud (本版7 或 更新版)", "Invalid ownCloud url" : "無效的 ownCloud URL", "Shared by" : "由...分享", "Sharing" : "分享", "A file or folder has been <strong>shared</strong>" : "檔案或目錄已被 <strong>分享</strong>", + "A file or folder was shared from <strong>another server</strong>" : "檔案或目錄已被 <strong>其他伺服器</strong> 分享", + "A public shared file or folder was <strong>downloaded</strong>" : "共享檔案或目錄已被 <strong>下載</strong>", + "You received a new remote share %2$s from %1$s" : "您收到了一個遠端分享 %2$s 來自於 %1$s", + "You received a new remote share from %s" : "您收到了一個遠端分享來自於 %s", + "%1$s accepted remote share %2$s" : "%1$s 接受了遠端分享 %2$s", + "%1$s declined remote share %2$s" : "%1$s 拒絕了遠端分享 %2$s", + "%1$s unshared %2$s from you" : "%1$s 取消與你分享 %2$s", + "Public shared folder %1$s was downloaded" : "共享資料夾 %1$s 已被下載", + "Public shared file %1$s was downloaded" : "共享檔案 %1$s 已被下載", "You shared %1$s with %2$s" : "您與 %2$s 分享了 %1$s", "You shared %1$s with group %2$s" : "您與 %2$s 群組分享了 %1$s", + "%2$s shared %1$s with %3$s" : "%2$s 與 %3$s 分享了 %1$s", + "%2$s shared %1$s with group %3$s" : "%2$s 與群組 %3$s 分享了 %1$s", + "%2$s shared %1$s via link" : "%2$s 透過連結分享了 %1$s ", "%2$s shared %1$s with you" : "%2$s 與您分享了 %1$s", "You shared %1$s via link" : "您以連結分享了 %1$s", + "Downloaded via public link" : "透過公用連結下載", + "Shared with %2$s" : "與 %2$s 分享", + "Shared with group %2$s" : "與群組 %2$s 分享", + "Shared with %3$s by %2$s" : "透過 %2$s 與 %3$s 分享", + "Shared with group %3$s by %2$s" : "透過 %2$s 與群組 %3$s 分享", + "Shared via link by %2$s" : "%2$s 透過連結分享", + "Shared by %2$s" : "由 %2$s 分享", + "Shared via public link" : "透過公用連結分享", "Shares" : "分享", + "You received %2$s as a remote share from %1$s" : "您收到了來自%1$s的一個遠端分享 %2$s ", + "Accept" : "接受", + "Decline" : "拒絕", + "Share with me through my #ownCloud Federated Cloud ID, see %s" : "可透過我的 #ownCloud 聯合 ID,與我分享,請看 %s", + "Share with me through my #ownCloud Federated Cloud ID" : "可透過我的 #ownCloud 聯合 ID,與我分享", "This share is password-protected" : "這個分享有密碼保護", "The password is wrong. Try again." : "請檢查您的密碼並再試一次", "Password" : "密碼", @@ -34,6 +71,15 @@ "Download" : "下載", "Download %s" : "下載 %s", "Direct link" : "直接連結", - "Federated Cloud Sharing" : "聯盟式雲端分享" + "Federated Cloud Sharing" : "聯盟式雲端分享", + "Open documentation" : "開啟文件", + "Allow users on this server to send shares to other servers" : "允許這台伺服器上的使用者發送分享給其他伺服器", + "Allow users on this server to receive shares from other servers" : "允許這台伺服器上的使用者發送接收來自其他伺服器的分享", + "Federated Cloud" : "聯盟式雲端", + "Your Federated Cloud ID:" : "您的雲端聯盟ID:", + "Share it:" : "分享它:", + "Add to your website" : "新增至您的網站", + "Share with me via ownCloud" : "透果ownCloud與我分享", + "HTML Code:" : "HTML 代碼:" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php index fa6c2d4c4f5..2e615e231f1 100644 --- a/apps/files_sharing/lib/cache.php +++ b/apps/files_sharing/lib/cache.php @@ -8,7 +8,7 @@ * @author Morris Jobke <hey@morrisjobke.de> * @author Robin Appelman <icewind@owncloud.com> * @author Robin McCorkell <rmccorkell@karoshi.org.uk> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Scrutinizer Auto-Fixer <auto-fixer@scrutinizer-ci.com> * @author Thomas Müller <thomas.mueller@tmit.eu> * @author Vincent Petry <pvince81@owncloud.com> @@ -32,6 +32,7 @@ namespace OC\Files\Cache; +use OC\User\NoUserException; use OCP\Share_Backend_Collection; /** @@ -64,7 +65,12 @@ class Shared_Cache extends Cache { } $source = \OC_Share_Backend_File::getSource($target, $this->storage->getShare()); if (isset($source['path']) && isset($source['fileOwner'])) { - \OC\Files\Filesystem::initMountPoints($source['fileOwner']); + try { + \OC\Files\Filesystem::initMountPoints($source['fileOwner']); + } catch(NoUserException $e) { + \OC::$server->getLogger()->logException($e, ['app' => 'files_sharing']); + return false; + } $mounts = \OC\Files\Filesystem::getMountByNumericId($source['storage']); if (is_array($mounts) and !empty($mounts)) { $fullPath = $mounts[0]->getMountPoint() . $source['path']; diff --git a/apps/files_sharing/lib/capabilities.php b/apps/files_sharing/lib/capabilities.php index c8ba1273281..220878ec2aa 100644 --- a/apps/files_sharing/lib/capabilities.php +++ b/apps/files_sharing/lib/capabilities.php @@ -1,6 +1,6 @@ <?php /** - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 diff --git a/apps/files_sharing/lib/controllers/externalsharescontroller.php b/apps/files_sharing/lib/controllers/externalsharescontroller.php index 71cc956ec98..edf065ab476 100644 --- a/apps/files_sharing/lib/controllers/externalsharescontroller.php +++ b/apps/files_sharing/lib/controllers/externalsharescontroller.php @@ -3,7 +3,7 @@ * @author Björn Schießle <schiessle@owncloud.com> * @author Lukas Reschke <lukas@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 diff --git a/apps/files_sharing/lib/controllers/sharecontroller.php b/apps/files_sharing/lib/controllers/sharecontroller.php index 616b64e6c59..4b446d79ada 100644 --- a/apps/files_sharing/lib/controllers/sharecontroller.php +++ b/apps/files_sharing/lib/controllers/sharecontroller.php @@ -7,6 +7,7 @@ * @author Morris Jobke <hey@morrisjobke.de> * @author Robin Appelman <icewind@owncloud.com> * @author Robin McCorkell <rmccorkell@karoshi.org.uk> + * @author Vincent Petry <pvince81@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 @@ -333,8 +334,7 @@ class ShareController extends Controller { OC_Util::tearDownFS(); OC_Util::setupFS($rootLinkItem['uid_owner']); $path = Filesystem::getPath($linkItem['file_source']); - - if(!empty($path) && Filesystem::isReadable($path)) { + if(Filesystem::isReadable($path)) { return $path; } } diff --git a/apps/files_sharing/lib/exceptions/s2sexception.php b/apps/files_sharing/lib/exceptions/s2sexception.php index d914e9e06db..fe2659d36ff 100644 --- a/apps/files_sharing/lib/exceptions/s2sexception.php +++ b/apps/files_sharing/lib/exceptions/s2sexception.php @@ -2,7 +2,7 @@ /** * @author Björn Schießle <schiessle@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 diff --git a/apps/files_sharing/lib/external/manager.php b/apps/files_sharing/lib/external/manager.php index 86b8904cc9a..93e2cdb540b 100644 --- a/apps/files_sharing/lib/external/manager.php +++ b/apps/files_sharing/lib/external/manager.php @@ -5,8 +5,7 @@ * @author Jörn Friedrich Dreyer <jfd@butonic.de> * @author Morris Jobke <hey@morrisjobke.de> * @author Robin Appelman <icewind@owncloud.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Vincent Petry <pvince81@owncloud.com> + * @author Roeland Jago Douma <rullzer@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 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; + } } diff --git a/apps/files_sharing/lib/helper.php b/apps/files_sharing/lib/helper.php index b15f70fcde3..a804737c490 100644 --- a/apps/files_sharing/lib/helper.php +++ b/apps/files_sharing/lib/helper.php @@ -7,7 +7,7 @@ * @author Lukas Reschke <lukas@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> * @author Robin Appelman <icewind@owncloud.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Vincent Petry <pvince81@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. @@ -28,6 +28,8 @@ */ namespace OCA\Files_Sharing; +use OCP\Files\NotFoundException; + class Helper { public static function registerHooks() { @@ -48,6 +50,7 @@ class Helper { * @param string $token string share token * @param string $relativePath optional path relative to the share * @param string $password optional password + * @return array */ public static function setupFromToken($token, $relativePath = null, $password = null) { \OC_User::setIncognitoMode(true); @@ -71,10 +74,11 @@ class Helper { \OCP\JSON::checkUserExists($rootLinkItem['uid_owner']); \OC_Util::tearDownFS(); \OC_Util::setupFS($rootLinkItem['uid_owner']); - $path = \OC\Files\Filesystem::getPath($linkItem['file_source']); } - if ($path === null) { + try { + $path = \OC\Files\Filesystem::getPath($linkItem['file_source']); + } catch (NotFoundException $e) { \OCP\Util::writeLog('share', 'could not resolve linkItem', \OCP\Util::DEBUG); \OC_Response::setStatus(404); \OCP\JSON::error(array('success' => false)); diff --git a/apps/files_sharing/lib/middleware/sharingcheckmiddleware.php b/apps/files_sharing/lib/middleware/sharingcheckmiddleware.php index 9170c08b59d..22b9d32a275 100644 --- a/apps/files_sharing/lib/middleware/sharingcheckmiddleware.php +++ b/apps/files_sharing/lib/middleware/sharingcheckmiddleware.php @@ -2,7 +2,7 @@ /** * @author Lukas Reschke <lukas@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Thomas Müller <thomas.mueller@tmit.eu> * * @copyright Copyright (c) 2015, ownCloud, Inc. diff --git a/apps/files_sharing/lib/propagation/propagationmanager.php b/apps/files_sharing/lib/propagation/propagationmanager.php index 6ed70e93f84..aac9428240d 100644 --- a/apps/files_sharing/lib/propagation/propagationmanager.php +++ b/apps/files_sharing/lib/propagation/propagationmanager.php @@ -1,6 +1,7 @@ <?php /** * @author Robin Appelman <icewind@owncloud.com> + * @author Vincent Petry <pvince81@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 diff --git a/apps/files_sharing/lib/propagation/recipientpropagator.php b/apps/files_sharing/lib/propagation/recipientpropagator.php index 8e064e2ee54..5eacf4c0f6e 100644 --- a/apps/files_sharing/lib/propagation/recipientpropagator.php +++ b/apps/files_sharing/lib/propagation/recipientpropagator.php @@ -1,5 +1,6 @@ <?php /** + * @author Lukas Reschke <lukas@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> * @author Robin Appelman <icewind@owncloud.com> * @@ -25,6 +26,7 @@ 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 @@ -128,6 +130,9 @@ class RecipientPropagator { protected $propagatingIds = []; + /** + * @param int $id + */ public function propagateById($id) { if (isset($this->propagatingIds[$id])) { return; @@ -142,7 +147,13 @@ class RecipientPropagator { if ($share['share_with'] === $this->userId) { $user = $share['uid_owner']; $view = new View('/' . $user . '/files'); - $path = $view->getPath($share['file_source']); + + try { + $path = $view->getPath($share['file_source']); + } catch (NotFoundException $e) { + $path = null; + } + $watcher = new ChangeWatcher($view, $this->manager->getSharePropagator($user)); $watcher->writeHook(['path' => $path]); } diff --git a/apps/files_sharing/lib/share/file.php b/apps/files_sharing/lib/share/file.php index 6c676f47a0c..ffc417db2f4 100644 --- a/apps/files_sharing/lib/share/file.php +++ b/apps/files_sharing/lib/share/file.php @@ -3,10 +3,11 @@ * @author Andreas Fischer <bantu@owncloud.com> * @author Bart Visscher <bartv@thisnet.nl> * @author Björn Schießle <schiessle@owncloud.com> + * @author Lukas Reschke <lukas@owncloud.com> * @author Michael Gapczynski <GapczynskiM@gmail.com> * @author Morris Jobke <hey@morrisjobke.de> * @author Robin Appelman <icewind@owncloud.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Thomas Müller <thomas.mueller@tmit.eu> * @author Vincent Petry <pvince81@owncloud.com> * @@ -40,15 +41,16 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent { private $path; public function isValidSource($itemSource, $uidOwner) { - $path = \OC\Files\Filesystem::getPath($itemSource); - if ($path) { + try { + $path = \OC\Files\Filesystem::getPath($itemSource); // FIXME: attributes should not be set here, // keeping this pattern for now to avoid unexpected // regressions $this->path = \OC\Files\Filesystem::normalizePath(basename($path)); return true; + } catch (\OCP\Files\NotFoundException $e) { + return false; } - return false; } public function getFilePath($itemSource, $uidOwner) { @@ -57,12 +59,13 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent { $this->path = null; return $path; } else { - $path = \OC\Files\Filesystem::getPath($itemSource); - if ($path) { + try { + $path = \OC\Files\Filesystem::getPath($itemSource); return $path; + } catch (\OCP\Files\NotFoundException $e) { + return false; } } - return false; } /** diff --git a/apps/files_sharing/lib/share/folder.php b/apps/files_sharing/lib/share/folder.php index daa5b5e9eb8..5e7cd8099db 100644 --- a/apps/files_sharing/lib/share/folder.php +++ b/apps/files_sharing/lib/share/folder.php @@ -5,7 +5,7 @@ * @author Michael Gapczynski <GapczynskiM@gmail.com> * @author Morris Jobke <hey@morrisjobke.de> * @author Robin McCorkell <rmccorkell@karoshi.org.uk> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 diff --git a/apps/files_sharing/lib/sharedmount.php b/apps/files_sharing/lib/sharedmount.php index 85eb264ce09..a1387957867 100644 --- a/apps/files_sharing/lib/sharedmount.php +++ b/apps/files_sharing/lib/sharedmount.php @@ -4,7 +4,7 @@ * @author Joas Schilling <nickvergessen@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> * @author Robin Appelman <icewind@owncloud.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index b0e56f5f054..18e02844179 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -7,7 +7,7 @@ * @author Morris Jobke <hey@morrisjobke.de> * @author Robin Appelman <icewind@owncloud.com> * @author Robin McCorkell <rmccorkell@karoshi.org.uk> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author scambra <sergio@entrecables.com> * @author Vincent Petry <pvince81@owncloud.com> * diff --git a/apps/files_sharing/lib/updater.php b/apps/files_sharing/lib/updater.php index d70ed23b941..26044cc1c8e 100644 --- a/apps/files_sharing/lib/updater.php +++ b/apps/files_sharing/lib/updater.php @@ -5,7 +5,7 @@ * @author Michael Gapczynski <GapczynskiM@gmail.com> * @author Morris Jobke <hey@morrisjobke.de> * @author Robin Appelman <icewind@owncloud.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Vincent Petry <pvince81@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. diff --git a/apps/files_sharing/lib/watcher.php b/apps/files_sharing/lib/watcher.php index dc95dde480e..3af6f733b51 100644 --- a/apps/files_sharing/lib/watcher.php +++ b/apps/files_sharing/lib/watcher.php @@ -29,41 +29,41 @@ namespace OC\Files\Cache; * check the storage backends for updates and change the cache accordingly */ class Shared_Watcher extends Watcher { + /** + * @var \OC\Files\Storage\Shared $storage + */ + protected $storage; /** - * check $path for updates + * Update the cache for changes to $path * * @param string $path - * @param array $cachedEntry - * @return boolean true if path was updated + * @param array $cachedData */ - public function checkUpdate($path, $cachedEntry = null) { - if (parent::checkUpdate($path, $cachedEntry) === true) { - // since checkUpdate() has already updated the size of the subdirs, - // only apply the update to the owner's parent dirs - - // find last parent before reaching the shared storage root, - // which is the actual shared dir from the owner - $sepPos = strpos($path, '/'); - if ($sepPos > 0) { - $baseDir = substr($path, 0, $sepPos); - } else { - $baseDir = $path; - } + public function update($path, $cachedData) { + parent::update($path, $cachedData); + // since parent::update() has already updated the size of the subdirs, + // only apply the update to the owner's parent dirs - // find the path relative to the data dir - $file = $this->storage->getFile($baseDir); - $view = new \OC\Files\View('/' . $file['fileOwner']); + // find last parent before reaching the shared storage root, + // which is the actual shared dir from the owner + $sepPos = strpos($path, '/'); + if ($sepPos > 0) { + $baseDir = substr($path, 0, $sepPos); + } else { + $baseDir = $path; + } - // find the owner's storage and path - list($storage, $internalPath) = $view->resolvePath($file['path']); + // find the path relative to the data dir + $file = $this->storage->getFile($baseDir); + $view = new \OC\Files\View('/' . $file['fileOwner']); - // update the parent dirs' sizes in the owner's cache - $storage->getCache()->correctFolderSize(dirname($internalPath)); + // find the owner's storage and path + /** @var \OC\Files\Storage\Storage $storage */ + list($storage, $internalPath) = $view->resolvePath($file['path']); - return true; - } - return false; + // update the parent dirs' sizes in the owner's cache + $storage->getCache()->correctFolderSize(dirname($internalPath)); } /** diff --git a/apps/files_sharing/templates/authenticate.php b/apps/files_sharing/templates/authenticate.php index 769b7929144..72adf0d1674 100644 --- a/apps/files_sharing/templates/authenticate.php +++ b/apps/files_sharing/templates/authenticate.php @@ -18,7 +18,6 @@ placeholder="<?php p($l->t('Password')); ?>" value="" autocomplete="off" autocapitalize="off" autocorrect="off" autofocus /> - <img class="svg" id="password-icon" src="<?php print_unescaped(image_path('', 'actions/password.svg')); ?>" alt=""/> <input type="submit" value="" class="svg icon-confirm input-button-inline" /> </p> diff --git a/apps/files_sharing/tests/api.php b/apps/files_sharing/tests/api.php index 3809b812051..760bc0591e5 100644 --- a/apps/files_sharing/tests/api.php +++ b/apps/files_sharing/tests/api.php @@ -5,7 +5,7 @@ * @author Morris Jobke <hey@morrisjobke.de> * @author Robin Appelman <icewind@owncloud.com> * @author Robin McCorkell <rmccorkell@karoshi.org.uk> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Thomas Müller <thomas.mueller@tmit.eu> * @author Vincent Petry <pvince81@owncloud.com> * diff --git a/apps/files_sharing/tests/api/share20ocstest.php b/apps/files_sharing/tests/api/share20ocstest.php new file mode 100644 index 00000000000..f74585eb47d --- /dev/null +++ b/apps/files_sharing/tests/api/share20ocstest.php @@ -0,0 +1,346 @@ +<?php +/** + * @author Roeland Jago Douma <rullzer@owncloud.com> + * + * @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 <http://www.gnu.org/licenses/> + * + */ +namespace OCA\Files_Sharing\Tests\API; + +use OCA\Files_Sharing\API\Share20OCS; + +class Share20OCSTest extends \Test\TestCase { + + /** @var OC\Share20\Manager */ + private $shareManager; + + /** @var OCP\IGroupManager */ + private $groupManager; + + /** @var OCP\IUserManager */ + private $userManager; + + /** @var OCP\IRequest */ + private $request; + + /** @var OCP\Files\Folder */ + private $userFolder; + + /** @var OCP\IURLGenerator */ + private $urlGenerator; + + /** @var OCS */ + private $ocs; + + protected function setUp() { + $this->shareManager = $this->getMockBuilder('OC\Share20\Manager') + ->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->urlGenerator); + } + + public function testDeleteShareShareNotFound() { + $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->deleteShare(42)); + } + + public function testDeleteShareCouldNotDelete() { + $share = $this->getMock('OC\Share20\IShare'); + $this->shareManager + ->expects($this->once()) + ->method('getShareById') + ->with(42) + ->willReturn($share); + $this->shareManager + ->expects($this->once()) + ->method('deleteShare') + ->with($share) + ->will($this->throwException(new \OC\Share20\Exception\BackendError())); + + + $expected = new \OC_OCS_Result(null, 404, 'could not delete share'); + $this->assertEquals($expected, $this->ocs->deleteShare(42)); + } + + public function testDeleteShare() { + $share = $this->getMock('OC\Share20\IShare'); + $this->shareManager + ->expects($this->once()) + ->method('getShareById') + ->with(42) + ->willReturn($share); + $this->shareManager + ->expects($this->once()) + ->method('deleteShare') + ->with($share); + + $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/apps/files_sharing/tests/api/shareestest.php b/apps/files_sharing/tests/api/shareestest.php index 923881d4569..8a35350aeb5 100644 --- a/apps/files_sharing/tests/api/shareestest.php +++ b/apps/files_sharing/tests/api/shareestest.php @@ -1,7 +1,7 @@ <?php /** * @author Joas Schilling <nickvergessen@owncloud.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 diff --git a/apps/files_sharing/tests/capabilities.php b/apps/files_sharing/tests/capabilities.php index b151f47a468..8bebde9f2d1 100644 --- a/apps/files_sharing/tests/capabilities.php +++ b/apps/files_sharing/tests/capabilities.php @@ -1,7 +1,7 @@ <?php /** * @author Joas Schilling <nickvergessen@owncloud.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 diff --git a/apps/files_sharing/tests/controller/externalsharecontroller.php b/apps/files_sharing/tests/controller/externalsharecontroller.php index 7bc11f7fb94..4913c7308ba 100644 --- a/apps/files_sharing/tests/controller/externalsharecontroller.php +++ b/apps/files_sharing/tests/controller/externalsharecontroller.php @@ -1,7 +1,7 @@ <?php /** * @author Lukas Reschke <lukas@owncloud.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 diff --git a/apps/files_sharing/tests/controller/sharecontroller.php b/apps/files_sharing/tests/controller/sharecontroller.php index 0b56aafc8a9..db5eb75d761 100644 --- a/apps/files_sharing/tests/controller/sharecontroller.php +++ b/apps/files_sharing/tests/controller/sharecontroller.php @@ -199,8 +199,7 @@ class ShareControllerTest extends \Test\TestCase { } /** - * @expectedException \Exception - * @expectedExceptionMessage No file found belonging to file. + * @expectedException \OCP\Files\NotFoundException */ public function testShowShareWithDeletedFile() { $this->container['UserManager']->expects($this->once()) @@ -216,8 +215,7 @@ class ShareControllerTest extends \Test\TestCase { } /** - * @expectedException \Exception - * @expectedExceptionMessage No file found belonging to file. + * @expectedException \OCP\Files\NotFoundException */ public function testDownloadShareWithDeletedFile() { $this->container['UserManager']->expects($this->once()) diff --git a/apps/files_sharing/tests/etagpropagation.php b/apps/files_sharing/tests/etagpropagation.php index 2490fef03e1..1abf04df84f 100644 --- a/apps/files_sharing/tests/etagpropagation.php +++ b/apps/files_sharing/tests/etagpropagation.php @@ -1,5 +1,7 @@ <?php /** + * @author Jörn Friedrich Dreyer <jfd@butonic.de> + * @author Lukas Reschke <lukas@owncloud.com> * @author Robin Appelman <icewind@owncloud.com> * @author Vincent Petry <pvince81@owncloud.com> * @@ -173,7 +175,7 @@ class EtagPropagation extends TestCase { $this->assertEtagsChanged($users, 'sub1/sub2'); } - private function assertAllUnchaged() { + private function assertAllUnchanged() { $users = [self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]; $this->assertEtagsNotChanged($users); @@ -186,7 +188,7 @@ class EtagPropagation extends TestCase { $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER3]); - $this->assertAllUnchaged(); + $this->assertAllUnchanged(); } public function testOwnerWritesToSingleFileShare() { @@ -195,7 +197,7 @@ class EtagPropagation extends TestCase { $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]); - $this->assertAllUnchaged(); + $this->assertAllUnchanged(); } public function testOwnerWritesToShareWithReshare() { @@ -204,7 +206,7 @@ class EtagPropagation extends TestCase { $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - $this->assertAllUnchaged(); + $this->assertAllUnchanged(); } public function testOwnerRenameInShare() { @@ -214,7 +216,7 @@ class EtagPropagation extends TestCase { $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER3]); - $this->assertAllUnchaged(); + $this->assertAllUnchanged(); } public function testOwnerRenameInReShare() { @@ -223,7 +225,7 @@ class EtagPropagation extends TestCase { $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - $this->assertAllUnchaged(); + $this->assertAllUnchanged(); } public function testOwnerRenameIntoReShare() { @@ -232,7 +234,7 @@ class EtagPropagation extends TestCase { $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - $this->assertAllUnchaged(); + $this->assertAllUnchanged(); } public function testOwnerRenameOutOfReShare() { @@ -241,7 +243,7 @@ class EtagPropagation extends TestCase { $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - $this->assertAllUnchaged(); + $this->assertAllUnchanged(); } public function testOwnerDeleteInShare() { @@ -251,7 +253,7 @@ class EtagPropagation extends TestCase { $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER3]); - $this->assertAllUnchaged(); + $this->assertAllUnchanged(); } public function testOwnerDeleteInReShare() { @@ -260,7 +262,7 @@ class EtagPropagation extends TestCase { $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - $this->assertAllUnchaged(); + $this->assertAllUnchanged(); } public function testOwnerUnshares() { @@ -283,7 +285,7 @@ class EtagPropagation extends TestCase { self::TEST_FILES_SHARING_API_USER4, ]); - $this->assertAllUnchaged(); + $this->assertAllUnchanged(); } public function testRecipientUnsharesFromSelf() { @@ -298,7 +300,7 @@ class EtagPropagation extends TestCase { self::TEST_FILES_SHARING_API_USER4, ]); - $this->assertAllUnchaged(); + $this->assertAllUnchanged(); } public function testRecipientWritesToShare() { @@ -308,7 +310,7 @@ class EtagPropagation extends TestCase { $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER3]); - $this->assertAllUnchaged(); + $this->assertAllUnchanged(); } public function testRecipientWritesToReshare() { @@ -317,7 +319,7 @@ class EtagPropagation extends TestCase { $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - $this->assertAllUnchaged(); + $this->assertAllUnchanged(); } public function testRecipientWritesToOtherRecipientsReshare() { @@ -326,7 +328,7 @@ class EtagPropagation extends TestCase { $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - $this->assertAllUnchaged(); + $this->assertAllUnchanged(); } public function testRecipientRenameInShare() { @@ -336,7 +338,7 @@ class EtagPropagation extends TestCase { $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER3]); - $this->assertAllUnchaged(); + $this->assertAllUnchanged(); } public function testRecipientRenameInReShare() { @@ -345,7 +347,7 @@ class EtagPropagation extends TestCase { $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - $this->assertAllUnchaged(); + $this->assertAllUnchanged(); } public function testRecipientRenameResharedFolder() { @@ -356,7 +358,7 @@ class EtagPropagation extends TestCase { $this->assertEtagsChanged([self::TEST_FILES_SHARING_API_USER2], 'sub1'); - $this->assertAllUnchaged(); + $this->assertAllUnchanged(); } public function testRecipientDeleteInShare() { @@ -366,7 +368,7 @@ class EtagPropagation extends TestCase { $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER3]); - $this->assertAllUnchaged(); + $this->assertAllUnchanged(); } public function testRecipientDeleteInReShare() { @@ -375,7 +377,7 @@ class EtagPropagation extends TestCase { $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - $this->assertAllUnchaged(); + $this->assertAllUnchanged(); } public function testReshareRecipientWritesToReshare() { @@ -384,7 +386,7 @@ class EtagPropagation extends TestCase { $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - $this->assertAllUnchaged(); + $this->assertAllUnchanged(); } public function testReshareRecipientRenameInReShare() { @@ -393,7 +395,7 @@ class EtagPropagation extends TestCase { $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - $this->assertAllUnchaged(); + $this->assertAllUnchanged(); } public function testReshareRecipientDeleteInReShare() { @@ -402,7 +404,7 @@ class EtagPropagation extends TestCase { $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - $this->assertAllUnchaged(); + $this->assertAllUnchanged(); } public function testRecipientUploadInDirectReshare() { @@ -411,7 +413,7 @@ class EtagPropagation extends TestCase { $this->assertEtagsNotChanged([self::TEST_FILES_SHARING_API_USER3]); $this->assertEtagsChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER4]); - $this->assertAllUnchaged(); + $this->assertAllUnchanged(); } public function testEtagChangeOnPermissionsChange() { @@ -424,6 +426,6 @@ class EtagPropagation extends TestCase { $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER4]); - $this->assertAllUnchaged(); + $this->assertAllUnchanged(); } } diff --git a/apps/files_sharing/tests/expiresharesjobtest.php b/apps/files_sharing/tests/expiresharesjobtest.php index 90da4011d8b..63a2c46f647 100644 --- a/apps/files_sharing/tests/expiresharesjobtest.php +++ b/apps/files_sharing/tests/expiresharesjobtest.php @@ -1,6 +1,6 @@ <?php /** - * @author Vincent Petry <pvince81@owncloud.com> + * @author Roeland Jago Douma <rullzer@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 diff --git a/apps/files_sharing/tests/external/managertest.php b/apps/files_sharing/tests/external/managertest.php index 7242779d455..5b93b7494e9 100644 --- a/apps/files_sharing/tests/external/managertest.php +++ b/apps/files_sharing/tests/external/managertest.php @@ -1,6 +1,7 @@ <?php /** * @author Joas Schilling <nickvergessen@owncloud.com> + * @author Robin Appelman <icewind@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 diff --git a/apps/files_sharing/tests/grouppropagationmanager.php b/apps/files_sharing/tests/grouppropagationmanager.php index 6fc6ef7a532..ea32ca4f7ec 100644 --- a/apps/files_sharing/tests/grouppropagationmanager.php +++ b/apps/files_sharing/tests/grouppropagationmanager.php @@ -1,7 +1,5 @@ <?php /** - * @author Morris Jobke <hey@morrisjobke.de> - * @author Robin Appelman <icewind@owncloud.com> * @author Vincent Petry <pvince81@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. diff --git a/apps/files_sharing/tests/js/sharedfilelistSpec.js b/apps/files_sharing/tests/js/sharedfilelistSpec.js index 90ae9c2d6da..b4b6ac4954a 100644 --- a/apps/files_sharing/tests/js/sharedfilelistSpec.js +++ b/apps/files_sharing/tests/js/sharedfilelistSpec.js @@ -85,7 +85,7 @@ describe('OCA.Sharing.FileList tests', function() { file_source: 49, file_target: '/local path/local name.txt', path: 'files/something shared.txt', - permissions: OC.PERMISSION_ALL, + permissions: 31, stime: 11111, share_type: OC.Share.SHARE_TYPE_USER, share_with: 'user1', @@ -159,8 +159,7 @@ describe('OCA.Sharing.FileList tests', function() { expect($tr.attr('data-file')).toEqual('local name.txt'); expect($tr.attr('data-path')).toEqual('/local path'); expect($tr.attr('data-size')).not.toBeDefined(); - expect(parseInt($tr.attr('data-permissions'), 10)) - .toEqual(OC.PERMISSION_ALL); // read and delete + expect($tr.attr('data-permissions')).toEqual('31'); // read and delete expect($tr.attr('data-mime')).toEqual('text/plain'); expect($tr.attr('data-mtime')).toEqual('11111000'); expect($tr.attr('data-share-owner')).toEqual('User Two'); @@ -236,8 +235,7 @@ describe('OCA.Sharing.FileList tests', function() { expect($tr.attr('data-file')).toEqual('local name'); expect($tr.attr('data-path')).toEqual('/local path'); expect($tr.attr('data-size')).not.toBeDefined(); - expect(parseInt($tr.attr('data-permissions'), 10)) - .toEqual(OC.PERMISSION_ALL); // read and delete + expect($tr.attr('data-permissions')).toEqual('31'); // read and delete expect($tr.attr('data-mime')).toEqual('httpd/unix-directory'); expect($tr.attr('data-mtime')).toEqual('11111000'); expect($tr.attr('data-share-owner')).toEqual('User Two'); @@ -333,8 +331,7 @@ describe('OCA.Sharing.FileList tests', function() { expect($tr.attr('data-file')).toEqual('local name.txt'); expect($tr.attr('data-path')).toEqual('/local path'); expect($tr.attr('data-size')).not.toBeDefined(); - expect(parseInt($tr.attr('data-permissions'), 10)) - .toEqual(OC.PERMISSION_ALL - OC.PERMISSION_DELETE); // read + expect($tr.attr('data-permissions')).toEqual('31'); // read and delete expect($tr.attr('data-mime')).toEqual('text/plain'); expect($tr.attr('data-mtime')).toEqual('11111000'); expect($tr.attr('data-share-owner')).not.toBeDefined(); @@ -375,8 +372,7 @@ describe('OCA.Sharing.FileList tests', function() { expect($tr.attr('data-file')).toEqual('local name'); expect($tr.attr('data-path')).toEqual('/local path'); expect($tr.attr('data-size')).not.toBeDefined(); - expect(parseInt($tr.attr('data-permissions'), 10)) - .toEqual(OC.PERMISSION_ALL - OC.PERMISSION_DELETE); // read + expect($tr.attr('data-permissions')).toEqual('31'); // read and delete expect($tr.attr('data-mime')).toEqual('httpd/unix-directory'); expect($tr.attr('data-mtime')).toEqual('11111000'); expect($tr.attr('data-share-owner')).not.toBeDefined(); @@ -427,8 +423,7 @@ describe('OCA.Sharing.FileList tests', function() { expect($tr.attr('data-file')).toEqual('local name.txt'); expect($tr.attr('data-path')).toEqual('/local path'); expect($tr.attr('data-size')).not.toBeDefined(); - expect(parseInt($tr.attr('data-permissions'), 10)) - .toEqual(OC.PERMISSION_ALL - OC.PERMISSION_DELETE); // read + expect($tr.attr('data-permissions')).toEqual('31'); // read and delete expect($tr.attr('data-mime')).toEqual('text/plain'); expect($tr.attr('data-mtime')).toEqual('11111000'); expect($tr.attr('data-share-owner')).not.toBeDefined(); @@ -496,8 +491,7 @@ describe('OCA.Sharing.FileList tests', function() { expect($tr.attr('data-file')).toEqual('local name.txt'); expect($tr.attr('data-path')).toEqual('/local path'); expect($tr.attr('data-size')).not.toBeDefined(); - expect(parseInt($tr.attr('data-permissions'), 10)) - .toEqual(OC.PERMISSION_ALL - OC.PERMISSION_DELETE); // read + expect($tr.attr('data-permissions')).toEqual('31'); // read and delete expect($tr.attr('data-mime')).toEqual('text/plain'); // always use the most recent stime expect($tr.attr('data-mtime')).toEqual('22222000'); @@ -591,8 +585,7 @@ describe('OCA.Sharing.FileList tests', function() { expect($tr.attr('data-file')).toEqual('local name.txt'); expect($tr.attr('data-path')).toEqual('/local path'); expect($tr.attr('data-size')).not.toBeDefined(); - expect(parseInt($tr.attr('data-permissions'), 10)) - .toEqual(OC.PERMISSION_ALL - OC.PERMISSION_DELETE); // read + expect($tr.attr('data-permissions')).toEqual('31'); // read and delete expect($tr.attr('data-mime')).toEqual('text/plain'); expect($tr.attr('data-mtime')).toEqual('11111000'); expect($tr.attr('data-share-recipients')).not.toBeDefined(); @@ -633,8 +626,7 @@ describe('OCA.Sharing.FileList tests', function() { expect($tr.attr('data-file')).toEqual('local name.txt'); expect($tr.attr('data-path')).toEqual('/local path'); expect($tr.attr('data-size')).not.toBeDefined(); - expect(parseInt($tr.attr('data-permissions'), 10)) - .toEqual(OC.PERMISSION_ALL - OC.PERMISSION_DELETE); // read + expect($tr.attr('data-permissions')).toEqual('31'); // read and delete expect($tr.attr('data-mime')).toEqual('text/plain'); expect($tr.attr('data-mtime')).toEqual('11111000'); expect($tr.attr('data-share-recipients')).not.toBeDefined(); diff --git a/apps/files_sharing/tests/middleware/sharingcheckmiddleware.php b/apps/files_sharing/tests/middleware/sharingcheckmiddleware.php index 0269f77d0d5..031f8c1b970 100644 --- a/apps/files_sharing/tests/middleware/sharingcheckmiddleware.php +++ b/apps/files_sharing/tests/middleware/sharingcheckmiddleware.php @@ -2,7 +2,7 @@ /** * @author Lukas Reschke <lukas@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Thomas Müller <thomas.mueller@tmit.eu> * * @copyright Copyright (c) 2015, ownCloud, Inc. diff --git a/apps/files_sharing/tests/share.php b/apps/files_sharing/tests/share.php index abff820c168..896191dfe51 100644 --- a/apps/files_sharing/tests/share.php +++ b/apps/files_sharing/tests/share.php @@ -322,6 +322,22 @@ class Test_Files_Sharing extends OCA\Files_sharing\Tests\TestCase { ); } + public function testFileOwner() { + + $fileinfo = $this->view->getFileInfo($this->filename); + + $result = \OCP\Share::shareItem('file', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER, + \Test_Files_Sharing::TEST_FILES_SHARING_API_USER2, \OCP\Constants::PERMISSION_ALL); + + $this->assertTrue($result); + + $this->loginHelper(\Test_Files_Sharing::TEST_FILES_SHARING_API_USER2); + + $info = \OC\Files\Filesystem::getFileInfo($this->filename); + + $this->assertSame(\Test_Files_Sharing::TEST_FILES_SHARING_API_USER1, $info->getOwner()->getUID()); + } + /** * @dataProvider dataProviderGetUsersSharingFile * diff --git a/apps/files_sharing/tests/sharedmount.php b/apps/files_sharing/tests/sharedmount.php index 6f487892b8f..94c0ad448bc 100644 --- a/apps/files_sharing/tests/sharedmount.php +++ b/apps/files_sharing/tests/sharedmount.php @@ -4,7 +4,7 @@ * @author Joas Schilling <nickvergessen@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> * @author Robin Appelman <icewind@owncloud.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Thomas Müller <thomas.mueller@tmit.eu> * @author Vincent Petry <pvince81@owncloud.com> * diff --git a/apps/files_sharing/tests/sizepropagation.php b/apps/files_sharing/tests/sizepropagation.php index c596003de76..1d09f69449f 100644 --- a/apps/files_sharing/tests/sizepropagation.php +++ b/apps/files_sharing/tests/sizepropagation.php @@ -1,5 +1,6 @@ <?php /** + * @author Jörn Friedrich Dreyer <jfd@butonic.de> * @author Robin Appelman <icewind@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. diff --git a/apps/files_trashbin/ajax/delete.php b/apps/files_trashbin/ajax/delete.php index 7ce8d632e4b..40d1811717c 100644 --- a/apps/files_trashbin/ajax/delete.php +++ b/apps/files_trashbin/ajax/delete.php @@ -4,7 +4,7 @@ * @author Björn Schießle <schiessle@owncloud.com> * @author Lukas Reschke <lukas@owncloud.com> * @author Robin Appelman <icewind@owncloud.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Vincent Petry <pvince81@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. diff --git a/apps/files_trashbin/ajax/preview.php b/apps/files_trashbin/ajax/preview.php index 90add53f77f..49d6d93f574 100644 --- a/apps/files_trashbin/ajax/preview.php +++ b/apps/files_trashbin/ajax/preview.php @@ -3,7 +3,7 @@ * @author Björn Schießle <schiessle@owncloud.com> * @author Georg Ehrke <georg@owncloud.com> * @author Lukas Reschke <lukas@owncloud.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Vincent Petry <pvince81@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. diff --git a/apps/files_trashbin/ajax/undelete.php b/apps/files_trashbin/ajax/undelete.php index 01dc91f9bac..f0e5ce6d889 100644 --- a/apps/files_trashbin/ajax/undelete.php +++ b/apps/files_trashbin/ajax/undelete.php @@ -4,7 +4,7 @@ * @author Björn Schießle <schiessle@owncloud.com> * @author Lukas Reschke <lukas@owncloud.com> * @author Robin Appelman <icewind@owncloud.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Thomas Müller <thomas.mueller@tmit.eu> * @author Vincent Petry <pvince81@owncloud.com> * diff --git a/apps/files_trashbin/appinfo/application.php b/apps/files_trashbin/appinfo/application.php index 08ab7cd5c1d..59553abfb14 100644 --- a/apps/files_trashbin/appinfo/application.php +++ b/apps/files_trashbin/appinfo/application.php @@ -1,6 +1,6 @@ <?php /** - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Victor Dubiniuk <dubiniuk@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. diff --git a/apps/files_trashbin/appinfo/routes.php b/apps/files_trashbin/appinfo/routes.php index caa9f0864a1..f3b97d8687c 100644 --- a/apps/files_trashbin/appinfo/routes.php +++ b/apps/files_trashbin/appinfo/routes.php @@ -1,7 +1,7 @@ <?php /** * @author Lukas Reschke <lukas@owncloud.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Vincent Petry <pvince81@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. diff --git a/apps/files_trashbin/js/app.js b/apps/files_trashbin/js/app.js index 364b51697bd..1f46f568bf2 100644 --- a/apps/files_trashbin/js/app.js +++ b/apps/files_trashbin/js/app.js @@ -23,11 +23,13 @@ OCA.Trashbin.App = { return; } this._initialized = true; + var urlParams = OC.Util.History.parseUrlQuery(); this.fileList = new OCA.Trashbin.FileList( $('#app-content-trashbin'), { scrollContainer: $('#app-content'), fileActions: this._createFileActions(), - detailsViewEnabled: false + detailsViewEnabled: false, + scrollTo: urlParams.scrollto } ); }, diff --git a/apps/files_trashbin/l10n/ast.js b/apps/files_trashbin/l10n/ast.js index 804814b5892..b467f8b51a1 100644 --- a/apps/files_trashbin/l10n/ast.js +++ b/apps/files_trashbin/l10n/ast.js @@ -5,11 +5,15 @@ OC.L10N.register( "Couldn't restore %s" : "Nun pudo restaurase %s", "Deleted files" : "Ficheros desaniciaos", "Restore" : "Restaurar", + "Delete" : "Desaniciar", "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", - "Deleted" : "Desaniciáu", - "Delete" : "Desaniciar" + "Deleted" : "Desaniciáu" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_trashbin/l10n/ast.json b/apps/files_trashbin/l10n/ast.json index 47b21cdec4d..b568456279b 100644 --- a/apps/files_trashbin/l10n/ast.json +++ b/apps/files_trashbin/l10n/ast.json @@ -3,11 +3,15 @@ "Couldn't restore %s" : "Nun pudo restaurase %s", "Deleted files" : "Ficheros desaniciaos", "Restore" : "Restaurar", + "Delete" : "Desaniciar", "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", - "Deleted" : "Desaniciáu", - "Delete" : "Desaniciar" + "Deleted" : "Desaniciáu" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_trashbin/l10n/sv.js b/apps/files_trashbin/l10n/sv.js index 5a432945260..d21f1418073 100644 --- a/apps/files_trashbin/l10n/sv.js +++ b/apps/files_trashbin/l10n/sv.js @@ -5,14 +5,15 @@ OC.L10N.register( "Couldn't restore %s" : "Kunde inte återställa %s", "Deleted files" : "Raderade filer", "Restore" : "Återskapa", + "Delete" : "Radera", "Delete permanently" : "Radera permanent", "Error" : "Fel", "restored" : "återställd", "No deleted files" : "Inga borttagna filer", "You will be able to recover deleted files from here" : "Du kommer kunna återfå raderade filer härifrån", + "No entries found in this folder" : "nga Filer hittades i denna mapp", "Select all" : "Välj allt", "Name" : "Namn", - "Deleted" : "Raderad", - "Delete" : "Radera" + "Deleted" : "Raderad" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files_trashbin/l10n/sv.json b/apps/files_trashbin/l10n/sv.json index f1fd0cdf5de..0b9052ea713 100644 --- a/apps/files_trashbin/l10n/sv.json +++ b/apps/files_trashbin/l10n/sv.json @@ -3,14 +3,15 @@ "Couldn't restore %s" : "Kunde inte återställa %s", "Deleted files" : "Raderade filer", "Restore" : "Återskapa", + "Delete" : "Radera", "Delete permanently" : "Radera permanent", "Error" : "Fel", "restored" : "återställd", "No deleted files" : "Inga borttagna filer", "You will be able to recover deleted files from here" : "Du kommer kunna återfå raderade filer härifrån", + "No entries found in this folder" : "nga Filer hittades i denna mapp", "Select all" : "Välj allt", "Name" : "Namn", - "Deleted" : "Raderad", - "Delete" : "Radera" + "Deleted" : "Raderad" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_trashbin/l10n/zh_TW.js b/apps/files_trashbin/l10n/zh_TW.js index 85d0873eddf..e0ad6dbd723 100644 --- a/apps/files_trashbin/l10n/zh_TW.js +++ b/apps/files_trashbin/l10n/zh_TW.js @@ -5,13 +5,15 @@ OC.L10N.register( "Couldn't restore %s" : "無法還原 %s", "Deleted files" : "回收桶", "Restore" : "還原", + "Delete" : "刪除", "Delete permanently" : "永久刪除", "Error" : "錯誤", "restored" : "已還原", + "No deleted files" : "沒有已刪除的檔案", + "You will be able to recover deleted files from here" : "您可以從這裡還原已刪除的檔案", "No entries found in this folder" : "在此資料夾中沒有任何項目", "Select all" : "全選", "Name" : "名稱", - "Deleted" : "已刪除", - "Delete" : "刪除" + "Deleted" : "已刪除" }, "nplurals=1; plural=0;"); diff --git a/apps/files_trashbin/l10n/zh_TW.json b/apps/files_trashbin/l10n/zh_TW.json index 5c744f828c9..6a313220b58 100644 --- a/apps/files_trashbin/l10n/zh_TW.json +++ b/apps/files_trashbin/l10n/zh_TW.json @@ -3,13 +3,15 @@ "Couldn't restore %s" : "無法還原 %s", "Deleted files" : "回收桶", "Restore" : "還原", + "Delete" : "刪除", "Delete permanently" : "永久刪除", "Error" : "錯誤", "restored" : "已還原", + "No deleted files" : "沒有已刪除的檔案", + "You will be able to recover deleted files from here" : "您可以從這裡還原已刪除的檔案", "No entries found in this folder" : "在此資料夾中沒有任何項目", "Select all" : "全選", "Name" : "名稱", - "Deleted" : "已刪除", - "Delete" : "刪除" + "Deleted" : "已刪除" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/apps/files_trashbin/lib/capabilities.php b/apps/files_trashbin/lib/capabilities.php index c991cc8be65..d903066e676 100644 --- a/apps/files_trashbin/lib/capabilities.php +++ b/apps/files_trashbin/lib/capabilities.php @@ -2,7 +2,7 @@ /** * @author Lukas Reschke <lukas@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 diff --git a/apps/files_trashbin/lib/helper.php b/apps/files_trashbin/lib/helper.php index 3d6a02c7776..d14e97285c5 100644 --- a/apps/files_trashbin/lib/helper.php +++ b/apps/files_trashbin/lib/helper.php @@ -5,7 +5,7 @@ * @author Jörn Friedrich Dreyer <jfd@butonic.de> * @author Robin Appelman <icewind@owncloud.com> * @author Robin McCorkell <rmccorkell@karoshi.org.uk> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Vincent Petry <pvince81@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. diff --git a/apps/files_trashbin/lib/trashbin.php b/apps/files_trashbin/lib/trashbin.php index 839a47a7bf2..8f0fe745a45 100644 --- a/apps/files_trashbin/lib/trashbin.php +++ b/apps/files_trashbin/lib/trashbin.php @@ -12,7 +12,7 @@ * @author Qingping Hou <dave2008713@gmail.com> * @author Robin Appelman <icewind@owncloud.com> * @author Robin McCorkell <rmccorkell@karoshi.org.uk> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Sjors van der Pluijm <sjors@desjors.nl> * @author Thomas Müller <thomas.mueller@tmit.eu> * @author Victor Dubiniuk <dubiniuk@owncloud.com> @@ -41,6 +41,7 @@ use OC\Files\Filesystem; use OC\Files\View; use OCA\Files_Trashbin\AppInfo\Application; use OCA\Files_Trashbin\Command\Expire; +use OCP\Files\NotFoundException; class Trashbin { @@ -64,15 +65,24 @@ class Trashbin { self::getUidAndFilename($params['path']); } + /** + * @param string $filename + * @return array + * @throws \OC\User\NoUserException + */ public static function getUidAndFilename($filename) { $uid = \OC\Files\Filesystem::getOwner($filename); \OC\Files\Filesystem::initMountPoints($uid); if ($uid != \OCP\User::getUser()) { $info = \OC\Files\Filesystem::getFileInfo($filename); $ownerView = new \OC\Files\View('/' . $uid . '/files'); - $filename = $ownerView->getPath($info['fileid']); + try { + $filename = $ownerView->getPath($info['fileid']); + } catch (NotFoundException $e) { + $filename = null; + } } - return array($uid, $filename); + return [$uid, $filename]; } /** diff --git a/apps/files_versions/ajax/preview.php b/apps/files_versions/ajax/preview.php index d7bc44f17a2..0da518f3eaa 100644 --- a/apps/files_versions/ajax/preview.php +++ b/apps/files_versions/ajax/preview.php @@ -1,7 +1,7 @@ <?php /** * @author Björn Schießle <schiessle@owncloud.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Thomas Müller <thomas.mueller@tmit.eu> * @author Vincent Petry <pvince81@owncloud.com> * diff --git a/apps/files_versions/appinfo/application.php b/apps/files_versions/appinfo/application.php index 00723e621ac..ba0a2ae74cb 100644 --- a/apps/files_versions/appinfo/application.php +++ b/apps/files_versions/appinfo/application.php @@ -1,6 +1,6 @@ <?php /** - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Victor Dubiniuk <dubiniuk@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. diff --git a/apps/files_versions/appinfo/routes.php b/apps/files_versions/appinfo/routes.php index 9bab86d9224..b2ed477de68 100644 --- a/apps/files_versions/appinfo/routes.php +++ b/apps/files_versions/appinfo/routes.php @@ -4,7 +4,7 @@ * @author Jörn Friedrich Dreyer <jfd@butonic.de> * @author Lukas Reschke <lukas@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Thomas Müller <thomas.mueller@tmit.eu> * @author Tom Needham <tom@owncloud.com> * diff --git a/apps/files_versions/lib/capabilities.php b/apps/files_versions/lib/capabilities.php index 11b98038f46..ba4de906c70 100644 --- a/apps/files_versions/lib/capabilities.php +++ b/apps/files_versions/lib/capabilities.php @@ -2,7 +2,7 @@ /** * @author Christopher Schäpers <kondou@ts.unde.re> * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Tom Needham <tom@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. diff --git a/apps/files_versions/lib/storage.php b/apps/files_versions/lib/storage.php index dd8af1b8d18..6737bf20f90 100644 --- a/apps/files_versions/lib/storage.php +++ b/apps/files_versions/lib/storage.php @@ -44,6 +44,7 @@ namespace OCA\Files_Versions; use OCA\Files_Versions\AppInfo\Application; use OCA\Files_Versions\Command\Expire; use OCP\Lock\ILockingProvider; +use OCP\Files\NotFoundException; class Storage { @@ -74,15 +75,24 @@ class Storage { /** @var \OCA\Files_Versions\AppInfo\Application */ private static $application; + /** + * @param string $filename + * @return array + * @throws \OC\User\NoUserException + */ public static function getUidAndFilename($filename) { $uid = \OC\Files\Filesystem::getOwner($filename); \OC\Files\Filesystem::initMountPoints($uid); if ( $uid != \OCP\User::getUser() ) { $info = \OC\Files\Filesystem::getFileInfo($filename); $ownerView = new \OC\Files\View('/'.$uid.'/files'); - $filename = $ownerView->getPath($info['fileid']); + try { + $filename = $ownerView->getPath($info['fileid']); + } catch (NotFoundException $e) { + $filename = null; + } } - return array($uid, $filename); + return [$uid, $filename]; } /** diff --git a/apps/files_versions/tests/command/expiretest.php b/apps/files_versions/tests/command/expiretest.php index eb622689c33..eccc1f4c2ad 100644 --- a/apps/files_versions/tests/command/expiretest.php +++ b/apps/files_versions/tests/command/expiretest.php @@ -1,6 +1,7 @@ <?php /** * @author Joas Schilling <nickvergessen@owncloud.com> + * @author Jörn Friedrich Dreyer <jfd@butonic.de> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 diff --git a/apps/files_versions/tests/versions.php b/apps/files_versions/tests/versions.php index 2979de2ac98..b9bc0932a84 100644 --- a/apps/files_versions/tests/versions.php +++ b/apps/files_versions/tests/versions.php @@ -759,7 +759,11 @@ class Test_Files_Versioning extends \Test\TestCase { ); } - private function createAndCheckVersions($view, $path) { + /** + * @param \OC\Files\View $view + * @param string $path + */ + private function createAndCheckVersions(\OC\Files\View $view, $path) { $view->file_put_contents($path, 'test file'); $view->file_put_contents($path, 'version 1'); $view->file_put_contents($path, 'version 2'); @@ -782,7 +786,6 @@ class Test_Files_Versioning extends \Test\TestCase { /** * @param string $user * @param bool $create - * @param bool $password */ public static function loginHelper($user, $create = false) { diff --git a/apps/provisioning_api/appinfo/app.php b/apps/provisioning_api/appinfo/app.php deleted file mode 100644 index 40d8d5d04d3..00000000000 --- a/apps/provisioning_api/appinfo/app.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php -/** - - * - * @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 <http://www.gnu.org/licenses/> - * - */ diff --git a/apps/provisioning_api/appinfo/routes.php b/apps/provisioning_api/appinfo/routes.php index 17cfea26572..22a923f5c20 100644 --- a/apps/provisioning_api/appinfo/routes.php +++ b/apps/provisioning_api/appinfo/routes.php @@ -1,8 +1,10 @@ <?php /** * @author Joas Schilling <nickvergessen@owncloud.com> + * @author Lukas Reschke <lukas@owncloud.com> + * @author michag86 <micha_g@arcor.de> * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Tom Needham <tom@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. @@ -31,10 +33,11 @@ $users = new \OCA\Provisioning_API\Users( \OC::$server->getUserManager(), \OC::$server->getConfig(), \OC::$server->getGroupManager(), - \OC::$server->getUserSession() + \OC::$server->getUserSession(), + \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); @@ -48,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/apps.php b/apps/provisioning_api/lib/apps.php index ba920c7a9c9..e0fa63cca34 100644 --- a/apps/provisioning_api/lib/apps.php +++ b/apps/provisioning_api/lib/apps.php @@ -3,7 +3,7 @@ * @author Joas Schilling <nickvergessen@owncloud.com> * @author Lukas Reschke <lukas@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Tom Needham <tom@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. diff --git a/apps/provisioning_api/lib/groups.php b/apps/provisioning_api/lib/groups.php index 7e7515bc709..7a6e6150782 100644 --- a/apps/provisioning_api/lib/groups.php +++ b/apps/provisioning_api/lib/groups.php @@ -3,7 +3,7 @@ * @author Joas Schilling <nickvergessen@owncloud.com> * @author Lukas Reschke <lukas@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Tom Needham <tom@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. @@ -26,7 +26,6 @@ namespace OCA\Provisioning_API; use \OC_OCS_Result; -use \OC_SubAdmin; use OCP\IGroup; use OCP\IUser; @@ -38,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; } /** @@ -55,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) { @@ -81,14 +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; + $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()) - || in_array($parameters['groupid'], \OC_SubAdmin::getSubAdminsGroups($user->getUID()))){ - $users = $this->groupManager->get($parameters['groupid'])->getUsers(); + || $isSubadminOfGroup) { + $users = $this->groupManager->get($groupId)->getUsers(); $users = array_map(function($user) { /** @var IUser $user */ return $user->getUID(); @@ -108,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'); @@ -144,15 +165,19 @@ class Groups{ public function getSubAdminsOfGroup($parameters) { $group = $parameters['groupid']; // Check group exists - if(!$this->groupManager->groupExists($group)) { + $targetGroup = $this->groupManager->get($group); + if($targetGroup === null) { return new OC_OCS_Result(null, 101, 'Group does not exist'); } - // Go - if(!$subadmins = OC_Subadmin::getGroupsSubAdmins($group)) { - return new OC_OCS_Result(null, 102, 'Unknown error occured'); - } else { - return new OC_OCS_Result($subadmins); + + $subadmins = $this->groupManager->getSubAdmin()->getGroupsSubAdmins($targetGroup); + // New class returns IUser[] so convert back + $uids = []; + foreach ($subadmins as $user) { + $uids[] = $user->getUID(); } + + return new OC_OCS_Result($uids); } } diff --git a/apps/provisioning_api/lib/users.php b/apps/provisioning_api/lib/users.php index 0b529bcea2c..a2568425d0f 100644 --- a/apps/provisioning_api/lib/users.php +++ b/apps/provisioning_api/lib/users.php @@ -2,8 +2,9 @@ /** * @author Joas Schilling <nickvergessen@owncloud.com> * @author Lukas Reschke <lukas@owncloud.com> + * @author michag86 <micha_g@arcor.de> * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Thomas Müller <thomas.mueller@tmit.eu> * @author Tom Needham <tom@owncloud.com> * @@ -27,39 +28,40 @@ namespace OCA\Provisioning_API; use \OC_OCS_Result; -use \OC_SubAdmin; use \OC_Helper; -use \OC_Group; use OCP\Files\NotFoundException; +use OCP\ILogger; class Users { /** @var \OCP\IUserManager */ private $userManager; - /** @var \OCP\IConfig */ private $config; - /** @var \OCP\IGroupManager */ private $groupManager; - /** @var \OCP\IUserSession */ private $userSession; + /** @var ILogger */ + private $logger; /** * @param \OCP\IUserManager $userManager * @param \OCP\IConfig $config * @param \OCP\IGroupManager $groupManager * @param \OCP\IUserSession $userSession + * @param ILogger $logger */ public function __construct(\OCP\IUserManager $userManager, \OCP\IConfig $config, \OCP\IGroupManager $groupManager, - \OCP\IUserSession $userSession) { + \OCP\IUserSession $userSession, + ILogger $logger) { $this->userManager = $userManager; $this->config = $config; $this->groupManager = $groupManager; $this->userSession = $userSession; + $this->logger = $logger; } /** @@ -79,10 +81,15 @@ class Users { } // Admin? Or SubAdmin? - if($this->groupManager->isAdmin($user->getUID())){ + $uid = $user->getUID(); + $subAdminManager = $this->groupManager->getSubAdmin(); + if($this->groupManager->isAdmin($uid)){ $users = $this->userManager->search($search, $limit, $offset); - } else if (\OC_SubAdmin::isSubAdmin($user->getUID())) { - $subAdminOfGroups = \OC_SubAdmin::getSubAdminsGroups($user->getUID()); + } else if ($subAdminManager->isSubAdmin($user)) { + $subAdminOfGroups = $subAdminManager->getSubAdminsGroups($user); + foreach ($subAdminOfGroups as $key => $group) { + $subAdminOfGroups[$key] = $group->getGID(); + } if($offset === null) { $offset = 0; @@ -110,18 +117,49 @@ 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()); + $subAdminManager = $this->groupManager->getSubAdmin(); + + if (!$isAdmin && !$subAdminManager->isSubAdmin($user)) { + return new OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED); + } + if($this->userManager->userExists($userId)) { - \OCP\Util::writeLog('ocs_api', 'Failed addUser attempt: User already exists.', \OCP\Util::ERROR); + $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 $group) { + if(!$this->groupManager->groupExists($group)){ + return new OC_OCS_Result(null, 104, 'group '.$group.' does not exist'); + } + if(!$isAdmin && !$subAdminManager->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); - \OCP\Util::writeLog('ocs_api', 'Successful addUser call with userid: '.$_POST['userid'], \OCP\Util::INFO); - return new OC_OCS_Result(null, 100); - } catch (\Exception $e) { - \OCP\Util::writeLog('ocs_api', 'Failed addUser attempt with exception: '.$e->getMessage(), \OCP\Util::ERROR); - 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 { + $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($newUser); + $this->logger->info('Added userid '.$userId.' 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'); } } @@ -131,35 +169,38 @@ class Users { * @param array $parameters * @return OC_OCS_Result */ - public function getUser($parameters){ + public function getUser($parameters) { $userId = $parameters['userid']; // Check if user is logged in - $user = $this->userSession->getUser(); - if ($user === null) { + $currentLoggedInUser = $this->userSession->getUser(); + if ($currentLoggedInUser === null) { return new OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED); } $data = []; + // Check if the target user exists + $targetUserObject = $this->userManager->get($userId); + if($targetUserObject === null) { + return new OC_OCS_Result(null, \OCP\API::RESPOND_NOT_FOUND, 'The requested user could not be found'); + } + // Admin? Or SubAdmin? - if($this->groupManager->isAdmin($user->getUID()) || OC_SubAdmin::isUserAccessible($user->getUID(), $userId)) { - // Check they exist - if(!$this->userManager->userExists($userId)) { - return new OC_OCS_Result(null, \OCP\API::RESPOND_NOT_FOUND, 'The requested user could not be found'); - } + if($this->groupManager->isAdmin($currentLoggedInUser->getUID()) + || $this->groupManager->getSubAdmin()->isUserAccessible($currentLoggedInUser, $targetUserObject)) { $data['enabled'] = $this->config->getUserValue($userId, 'core', 'enabled', 'true'); } else { // Check they are looking up themselves - if($user->getUID() !== $userId) { + if($currentLoggedInUser->getUID() !== $userId) { return new OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED); } } // Find the data - $data['quota'] = self::fillStorageInfo($userId); + $data['quota'] = $this->fillStorageInfo($userId); $data['email'] = $this->config->getUserValue($userId, 'settings', 'email'); - $data['displayname'] = $this->userManager->get($userId)->getDisplayName(); + $data['displayname'] = $targetUserObject->getDisplayName(); return new OC_OCS_Result($data); } @@ -171,27 +212,34 @@ class Users { * @return OC_OCS_Result */ public function editUser($parameters) { - $userId = $parameters['userid']; + /** @var string $targetUserId */ + $targetUserId = $parameters['userid']; // Check if user is logged in - $user = $this->userSession->getUser(); - if ($user === null) { + $currentLoggedInUser = $this->userSession->getUser(); + if ($currentLoggedInUser === null) { return new OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED); } - if($userId === $user->getUID()) { + $targetUser = $this->userManager->get($targetUserId); + if($targetUser === null) { + return new OC_OCS_Result(null, 997); + } + + if($targetUserId === $currentLoggedInUser->getUID()) { // Editing self (display, email) $permittedFields[] = 'display'; $permittedFields[] = 'email'; $permittedFields[] = 'password'; // If admin they can edit their own quota - if($this->groupManager->isAdmin($user->getUID())) { + if($this->groupManager->isAdmin($currentLoggedInUser->getUID())) { $permittedFields[] = 'quota'; } } else { // Check if admin / subadmin - if(OC_SubAdmin::isUserAccessible($user->getUID(), $userId) - || $this->groupManager->isAdmin($user->getUID())) { + $subAdminManager = $this->groupManager->getSubAdmin(); + if($subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser) + || $this->groupManager->isAdmin($currentLoggedInUser->getUID())) { // They have permissions over the user $permittedFields[] = 'display'; $permittedFields[] = 'quota'; @@ -207,9 +255,9 @@ class Users { return new OC_OCS_Result(null, 997); } // Process the edit - switch($parameters['_put']['key']){ + switch($parameters['_put']['key']) { case 'display': - $this->userManager->get($userId)->setDisplayName($parameters['_put']['value']); + $targetUser->setDisplayName($parameters['_put']['value']); break; case 'quota': $quota = $parameters['_put']['value']; @@ -224,20 +272,20 @@ class Users { } if($quota === 0) { $quota = 'default'; - }else if($quota === -1){ + }else if($quota === -1) { $quota = 'none'; } else { $quota = \OCP\Util::humanFileSize($quota); } } - $this->config->setUserValue($userId, 'files', 'quota', $quota); + $this->config->setUserValue($targetUserId, 'files', 'quota', $quota); break; case 'password': - $this->userManager->get($userId)->setPassword($parameters['_put']['value']); + $targetUser->setPassword($parameters['_put']['value']); break; case 'email': if(filter_var($parameters['_put']['value'], FILTER_VALIDATE_EMAIL)) { - $this->config->setUserValue($userId, 'settings', 'email', $parameters['_put']['value']); + $this->config->setUserValue($targetUserId, 'settings', 'email', $parameters['_put']['value']); } else { return new OC_OCS_Result(null, 102); } @@ -255,21 +303,25 @@ class Users { */ public function deleteUser($parameters) { // Check if user is logged in - $user = $this->userSession->getUser(); - if ($user === null) { + $currentLoggedInUser = $this->userSession->getUser(); + if ($currentLoggedInUser === null) { return new OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED); } - if(!$this->userManager->userExists($parameters['userid']) - || $parameters['userid'] === $user->getUID()) { + $targetUser = $this->userManager->get($parameters['userid']); + + if($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) { return new OC_OCS_Result(null, 101); } + // If not permitted - if(!$this->groupManager->isAdmin($user->getUID()) && !OC_SubAdmin::isUserAccessible($user->getUID(), $parameters['userid'])) { + $subAdminManager = $this->groupManager->getSubAdmin(); + if(!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) { return new OC_OCS_Result(null, 997); } + // Go ahead with the delete - if($this->userManager->get($parameters['userid'])->delete()) { + if($targetUser->delete()) { return new OC_OCS_Result(null, 100); } else { return new OC_OCS_Result(null, 101); @@ -282,27 +334,34 @@ class Users { */ public function getUsersGroups($parameters) { // Check if user is logged in - $user = $this->userSession->getUser(); - if ($user === null) { + $loggedInUser = $this->userSession->getUser(); + if ($loggedInUser === null) { return new OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED); } - if($parameters['userid'] === $user->getUID() || $this->groupManager->isAdmin($user->getUID())) { + $targetUser = $this->userManager->get($parameters['userid']); + if($targetUser === null) { + return new OC_OCS_Result(null, \OCP\API::RESPOND_NOT_FOUND); + } + + if($targetUser->getUID() === $loggedInUser->getUID() || $this->groupManager->isAdmin($loggedInUser->getUID())) { // Self lookup or admin lookup return new OC_OCS_Result([ - 'groups' => $this->groupManager->getUserGroupIds( - $this->userManager->get($parameters['userid']) - ) + 'groups' => $this->groupManager->getUserGroupIds($targetUser) ]); } else { + $subAdminManager = $this->groupManager->getSubAdmin(); + // Looking up someone else - if(OC_SubAdmin::isUserAccessible($user->getUID(), $parameters['userid'])) { + if($subAdminManager->isUserAccessible($loggedInUser, $targetUser)) { // Return the group that the method caller is subadmin of for the user in question + $getSubAdminsGroups = $subAdminManager->getSubAdminsGroups($loggedInUser); + foreach ($getSubAdminsGroups as $key => $group) { + $getSubAdminsGroups[$key] = $group->getGID(); + } $groups = array_intersect( - OC_SubAdmin::getSubAdminsGroups($user->getUID()), - $this->groupManager->getUserGroupIds( - $this->userManager->get($parameters['userid']) - ) + $getSubAdminsGroups, + $this->groupManager->getUserGroupIds($targetUser) ); return new OC_OCS_Result(array('groups' => $groups)); } else { @@ -324,27 +383,28 @@ class Users { return new OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED); } - $group = !empty($_POST['groupid']) ? $_POST['groupid'] : null; - if(is_null($group)){ - return new OC_OCS_Result(null, 101); - } // Check they're an admin - if(!$this->groupManager->isInGroup($user->getUID(), 'admin')){ + if(!$this->groupManager->isAdmin($user->getUID())) { // This user doesn't have rights to add a user to this group return new OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED); } - // Check if the group exists - if(!$this->groupManager->groupExists($group)){ + + $groupId = !empty($_POST['groupid']) ? $_POST['groupid'] : null; + if($groupId === null) { + return new OC_OCS_Result(null, 101); + } + + $group = $this->groupManager->get($groupId); + $targetUser = $this->userManager->get($parameters['userid']); + if($group === null) { return new OC_OCS_Result(null, 102); } - // Check if the user exists - if(!$this->userManager->userExists($parameters['userid'])){ + if($targetUser === null) { return new OC_OCS_Result(null, 103); } + // Add user to group - $this->groupManager->get($group)->addUser( - $this->userManager->get($parameters['userid']) - ); + $group->addUser($targetUser); return new OC_OCS_Result(null, 100); } @@ -354,44 +414,52 @@ class Users { */ public function removeFromGroup($parameters) { // Check if user is logged in - $user = $this->userSession->getUser(); - if ($user === null) { + $loggedInUser = $this->userSession->getUser(); + if ($loggedInUser === null) { return new OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED); } $group = !empty($parameters['_delete']['groupid']) ? $parameters['_delete']['groupid'] : null; - if(is_null($group)){ + if($group === null) { return new OC_OCS_Result(null, 101); } + + $group = $this->groupManager->get($group); + if($group === null) { + return new OC_OCS_Result(null, 102); + } + + $targetUser = $this->userManager->get($parameters['userid']); + if($targetUser === null) { + return new OC_OCS_Result(null, 103); + } + // If they're not an admin, check they are a subadmin of the group in question - if(!$this->groupManager->isInGroup($user->getUID(), 'admin') && !OC_SubAdmin::isSubAdminofGroup($user->getUID(), $group)){ + $subAdminManager = $this->groupManager->getSubAdmin(); + if(!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminofGroup($loggedInUser, $group)) { return new OC_OCS_Result(null, 104); } // Check they aren't removing themselves from 'admin' or their 'subadmin; group - if($parameters['userid'] === $user->getUID()){ - if($this->groupManager->isInGroup($user->getUID(), 'admin')){ - if($group === 'admin'){ + if($parameters['userid'] === $loggedInUser->getUID()) { + if($this->groupManager->isAdmin($loggedInUser->getUID())) { + if($group->getGID() === 'admin') { return new OC_OCS_Result(null, 105, 'Cannot remove yourself from the admin group'); } } else { // Not an admin, check they are not removing themself from their subadmin group - if(in_array($group, OC_SubAdmin::getSubAdminsGroups($user->getUID()))){ + $subAdminGroups = $subAdminManager->getSubAdminsGroups($loggedInUser); + foreach ($subAdminGroups as $key => $group) { + $subAdminGroups[$key] = $group->getGID(); + } + + if(in_array($group->getGID(), $subAdminGroups, true)) { return new OC_OCS_Result(null, 105, 'Cannot remove yourself from this group as you are a SubAdmin'); } } } - // Check if the group exists - if(!$this->groupManager->groupExists($group)){ - return new OC_OCS_Result(null, 102); - } - // Check if the user exists - if(!$this->userManager->userExists($parameters['userid'])){ - return new OC_OCS_Result(null, 103); - } + // Remove user from group - $this->groupManager->get($group)->removeUser( - $this->userManager->get($parameters['userid']) - ); + $group->removeUser($targetUser); return new OC_OCS_Result(null, 100); } @@ -402,31 +470,34 @@ class Users { * @return OC_OCS_Result */ public function addSubAdmin($parameters) { - $group = $_POST['groupid']; - $user = $parameters['userid']; + $group = $this->groupManager->get($_POST['groupid']); + $user = $this->userManager->get($parameters['userid']); + // Check if the user exists - if(!$this->userManager->userExists($user)) { + if($user === null) { return new OC_OCS_Result(null, 101, 'User does not exist'); } // Check if group exists - if(!$this->groupManager->groupExists($group)) { - return new OC_OCS_Result(null, 102, 'Group:'.$group.' does not exist'); + if($group === null) { + return new OC_OCS_Result(null, 102, 'Group:'.$_POST['groupid'].' does not exist'); } // Check if trying to make subadmin of admin group - if(strtolower($group) === 'admin') { + if(strtolower($_POST['groupid']) === 'admin') { return new OC_OCS_Result(null, 103, 'Cannot create subadmins for admin group'); } + + $subAdminManager = $this->groupManager->getSubAdmin(); + // We cannot be subadmin twice - if (OC_Subadmin::isSubAdminOfGroup($user, $group)) { + if ($subAdminManager->isSubAdminofGroup($user, $group)) { return new OC_OCS_Result(null, 100); } // Go - if(OC_Subadmin::createSubAdmin($user, $group)) { + if($subAdminManager->createSubAdmin($user, $group)) { return new OC_OCS_Result(null, 100); } else { - return new OC_OCS_Result(null, 103, 'Unknown error occured'); + return new OC_OCS_Result(null, 103, 'Unknown error occurred'); } - } /** @@ -436,18 +507,25 @@ class Users { * @return OC_OCS_Result */ public function removeSubAdmin($parameters) { - $group = $parameters['_delete']['groupid']; - $user = $parameters['userid']; + $group = $this->groupManager->get($parameters['_delete']['groupid']); + $user = $this->userManager->get($parameters['userid']); + $subAdminManager = $this->groupManager->getSubAdmin(); + // Check if the user exists - if(!$this->userManager->userExists($user)) { + if($user === null) { return new OC_OCS_Result(null, 101, 'User does not exist'); } + // Check if the group exists + if($group === null) { + return new OC_OCS_Result(null, 101, 'Group does not exist'); + } // Check if they are a subadmin of this said group - if(!OC_SubAdmin::isSubAdminofGroup($user, $group)) { + if(!$subAdminManager->isSubAdminofGroup($user, $group)) { return new OC_OCS_Result(null, 102, 'User is not a subadmin of this group'); } + // Go - if(OC_Subadmin::deleteSubAdmin($user, $group)) { + if($subAdminManager->deleteSubAdmin($user, $group)) { return new OC_OCS_Result(null, 100); } else { return new OC_OCS_Result(null, 103, 'Unknown error occurred'); @@ -461,13 +539,19 @@ class Users { * @return OC_OCS_Result */ public function getUserSubAdminGroups($parameters) { - $user = $parameters['userid']; + $user = $this->userManager->get($parameters['userid']); // Check if the user exists - if(!$this->userManager->userExists($user)) { + if($user === null) { return new OC_OCS_Result(null, 101, 'User does not exist'); } + // Get the subadmin groups - if(!$groups = OC_SubAdmin::getSubAdminsGroups($user)) { + $groups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($user); + foreach ($groups as $key => $group) { + $groups[$key] = $group->getGID(); + } + + if(!$groups) { return new OC_OCS_Result(null, 102, 'Unknown error occurred'); } else { return new OC_OCS_Result($groups); @@ -476,12 +560,10 @@ class Users { /** * @param string $userId - * @param array $data - * @return mixed + * @return array * @throws \OCP\Files\NotFoundException */ - private static function fillStorageInfo($userId) { - $data = []; + protected function fillStorageInfo($userId) { try { \OC_Util::tearDownFS(); \OC_Util::setupFS($userId); diff --git a/apps/provisioning_api/tests/appstest.php b/apps/provisioning_api/tests/appstest.php index 2baea5bbc8c..2e1a86025c2 100644 --- a/apps/provisioning_api/tests/appstest.php +++ b/apps/provisioning_api/tests/appstest.php @@ -2,7 +2,7 @@ /** * @author Joas Schilling <nickvergessen@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Tom Needham <tom@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. diff --git a/apps/provisioning_api/tests/groupstest.php b/apps/provisioning_api/tests/groupstest.php index 4afd246abcd..d37f4412e20 100644 --- a/apps/provisioning_api/tests/groupstest.php +++ b/apps/provisioning_api/tests/groupstest.php @@ -1,8 +1,9 @@ <?php /** * @author Joas Schilling <nickvergessen@owncloud.com> + * @author Lukas Reschke <lukas@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Tom Needham <tom@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. @@ -24,80 +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]); - - \OC_SubAdmin::createSubAdmin($users[0]->getUID(), $group->getGID()); + $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]); - - \OC_SubAdmin::createSubAdmin($users[0]->getUID(), $group2->getGID()); + $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,71 @@ 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()); - \OC_SubAdmin::createSubAdmin($user2->getUID(), $group1->getGID()); + $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->assertTrue($result->succeeded()); + $this->assertEquals([], $result->getData()); } public function testAddGroupEmptyGroup() { - $_POST = []; + $this->request + ->method('getParam') + ->with('groupid') + ->willReturn(''); + $result = $this->api->addGroup([]); $this->assertInstanceOf('OC_OCS_Result', $result); @@ -228,40 +327,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 +375,11 @@ class GroupsTest extends TestCase { } public function testDeleteAdminGroup() { + $this->groupManager + ->method('groupExists') + ->with('admin') + ->willReturn('true'); + $result = $this->api->deleteGroup([ 'groupid' => 'admin' ]); @@ -278,13 +389,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())); } } diff --git a/apps/provisioning_api/tests/testcase.php b/apps/provisioning_api/tests/testcase.php index cc8f5c1d16d..113bc512243 100644 --- a/apps/provisioning_api/tests/testcase.php +++ b/apps/provisioning_api/tests/testcase.php @@ -2,7 +2,7 @@ /** * @author Joas Schilling <nickvergessen@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 @@ -46,7 +46,7 @@ abstract class TestCase extends \Test\TestCase { /** * Generates a temp user * @param int $num number of users to generate - * @return array + * @return IUser[]|Iuser */ protected function generateUsers($num = 1) { $users = array(); diff --git a/apps/provisioning_api/tests/userstest.php b/apps/provisioning_api/tests/userstest.php index 3869af87e5a..63180eb3472 100644 --- a/apps/provisioning_api/tests/userstest.php +++ b/apps/provisioning_api/tests/userstest.php @@ -1,11 +1,11 @@ <?php /** * @author Joas Schilling <nickvergessen@owncloud.com> + * @author Lukas Reschke <lukas@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Roeland Jago Douma <rullzer@owncloud.com> * @author Thomas Müller <thomas.mueller@tmit.eu> * @author Tom Needham <tom@owncloud.com> - * @author Vincent Petry <pvince81@owncloud.com> * * @copyright Copyright (c) 2015, ownCloud, Inc. * @license AGPL-3.0 @@ -26,1235 +26,2277 @@ namespace OCA\Provisioning_API\Tests; +use OCA\Provisioning_API\Users; use OCP\IUserManager; use OCP\IConfig; use OCP\IGroupManager; use OCP\IUserSession; +use Test\TestCase as OriginalTest; +use OCP\ILogger; -class UsersTest extends TestCase { +class UsersTest extends OriginalTest { /** @var IUserManager */ protected $userManager; - /** @var IConfig */ protected $config; - - /** @var IGroupManager */ + /** @var \OC\Group\Manager */ protected $groupManager; - /** @var IUserSession */ protected $userSession; + /** @var ILogger */ + protected $logger; + /** @var Users */ + protected $api; - protected function resetParams() { + protected function tearDown() { $_GET = null; $_POST = null; + parent::tearDown(); } protected function setup() { parent::setup(); - $this->userManager = \OC::$server->getUserManager(); - $this->config = \OC::$server->getConfig(); - $this->groupManager = \OC::$server->getGroupManager(); - $this->userSession = \OC::$server->getUserSession(); - $this->api = new \OCA\Provisioning_Api\Users( - $this->userManager, - $this->config, - $this->groupManager, - $this->userSession - ); + $this->userManager = $this->getMock('\OCP\IUserManager'); + $this->config = $this->getMock('\OCP\IConfig'); + $this->groupManager = $this->getMockBuilder('\OC\Group\Manager') + ->disableOriginalConstructor()->getMock(); + $this->userSession = $this->getMock('\OCP\IUserSession'); + $this->logger = $this->getMock('\OCP\ILogger'); + $this->api = $this->getMockBuilder('\OCA\Provisioning_API\Users') + ->setConstructorArgs([ + $this->userManager, + $this->config, + $this->groupManager, + $this->userSession, + $this->logger, + ] + ) + ->setMethods(['fillStorageInfo']) + ->getMock(); + } + + public function testGetUsersNotLoggedIn() { + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue(null)); - $this->userSession->setUser(null); + $expected = new \OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED); + $this->assertEquals($expected, $this->api->getUsers()); } - // Test getting the list of users public function testGetUsersAsAdmin() { - $user = $this->generateUsers(); - $this->groupManager->get('admin')->addUser($user); - $this->userSession->setUser($user); - - $result = $this->api->getUsers(); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $count = $result->getData(); - $count = count($count['users']); - $this->assertEquals(count($this->userManager->search('', null, null)), $count); - - $user = $this->generateUsers(); - $_GET['search'] = $user->getUID(); - $result = $this->api->getUsers(); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $data = $result->getData(); - $this->assertEquals($user->getUID(), reset($data['users'])); - - // Add several users - $this->generateUsers(10); - $this->resetParams(); - $_GET['limit'] = 2; - $result = $this->api->getUsers(); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $count = $result->getData(); - $count = count($count['users']); - $this->assertEquals(2, $count); - - $this->resetParams(); - $_GET['limit'] = 1; - $_GET['offset'] = 1; - $result = $this->api->getUsers(array()); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $data = $result->getData(); - $this->assertEquals(array_keys($this->userManager->search('', 1, 1)), $data['users']); + $_GET['search'] = 'MyCustomSearch'; + + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('admin')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->will($this->returnValue(true)); + $this->userManager + ->expects($this->once()) + ->method('search') + ->with('MyCustomSearch', null, null) + ->will($this->returnValue(['Admin' => [], 'Foo' => [], 'Bar' => []])); + + $expected = new \OC_OCS_Result([ + 'users' => [ + 'Admin', + 'Foo', + 'Bar', + ], + ]); + $this->assertEquals($expected, $this->api->getUsers()); } public function testGetUsersAsSubAdmin() { - $user = $this->generateUsers(10); - $this->userSession->setUser($user[0]); - $group = $this->groupManager->createGroup($this->getUniqueID()); - \OC_SubAdmin::createSubAdmin($user[0]->getUID(), $group->getGID()); - - //Empty list - $result = $this->api->getUsers([]); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $this->assertEquals(['users' => []], $result->getData()); - - //Some users in group - $group->addUser($user[1]); - $group->addUser($user[2]); - $group->addUser($user[3]); - $group->addUser($user[4]); - - $result = $this->api->getUsers([]); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $this->assertArrayHasKey('users', $result->getData()); - - $this->assertContains($user[1]->getUID(), $result->getData()['users']); - $this->assertContains($user[2]->getUID(), $result->getData()['users']); - $this->assertContains($user[3]->getUID(), $result->getData()['users']); - $this->assertContains($user[4]->getUID(), $result->getData()['users']); - - $uids = [ - $user[1]->getUID(), - $user[2]->getUID(), - $user[3]->getUID(), - $user[4]->getUID() - ]; - sort($uids); - - $_GET['limit'] = 2; - $_GET['offset'] = 1; - $result = $this->api->getUsers([]); - - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $this->assertEquals(['users' => array_slice($uids, 1, 2)], $result->getData()); - } - - public function testGetUsersNoUser() { - $result = $this->api->getUsers([]); - - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertEquals(\OCP\API::RESPOND_UNAUTHORISED, $result->getStatusCode()); - } - - public function testGetUsersAsUser() { - $user = $this->generateUsers(); - $this->userSession->setUser($user); - - $result = $this->api->getUsers(); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertEquals(\OCP\API::RESPOND_UNAUTHORISED, $result->getStatusCode()); - - } - - public function testAddUser() { - $this->resetParams(); - $_POST['userid'] = $this->getUniqueID(); - $_POST['password'] = 'password'; - $result = $this->api->addUser(); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $this->assertTrue($this->userManager->userExists($_POST['userid'])); - $this->assertEquals($_POST['userid'], $this->userManager->checkPassword($_POST['userid'], $_POST['password'])->getUID()); - $this->users[] = $this->userManager->get($_POST['userid']); - } - - public function testAddUserTwice() { - $this->resetParams(); - $_POST['userid'] = $this->getUniqueID(); - $_POST['password'] = 'password'; - $this->api->addUser(); - $result = $this->api->addUser(); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertEquals(102, $result->getStatusCode()); - $this->assertEquals('User already exists', $result->getMeta()['message']); - } - - public function testAddUserFails() { - $uid = $this->getUniqueID(); - - $userManager = $this->getMockBuilder('\OCP\IUserManager') - ->disableOriginalConstructor() - ->getMock(); + $_GET['search'] = 'MyCustomSearch'; + + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('subadmin')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->will($this->returnValue(false)); + $firstGroup = $this->getMock('\OCP\IGroup'); + $firstGroup + ->expects($this->once()) + ->method('getGID') + ->will($this->returnValue('FirstGroup')); + $secondGroup = $this->getMock('\OCP\IGroup'); + $secondGroup + ->expects($this->once()) + ->method('getGID') + ->will($this->returnValue('SecondGroup')); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') + ->disableOriginalConstructor()->getMock(); + $subAdminManager + ->expects($this->once()) + ->method('isSubAdmin') + ->with($loggedInUser) + ->will($this->returnValue(true)); + $subAdminManager + ->expects($this->once()) + ->method('getSubAdminsGroups') + ->with($loggedInUser) + ->will($this->returnValue([$firstGroup, $secondGroup])); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + $this->groupManager + ->expects($this->any()) + ->method('displayNamesInGroup') + ->will($this->onConsecutiveCalls(['AnotherUserInTheFirstGroup' => []], ['UserInTheSecondGroup' => []])); + + $expected = new \OC_OCS_Result([ + 'users' => [ + 'AnotherUserInTheFirstGroup', + 'UserInTheSecondGroup', + ], + ]); + $this->assertEquals($expected, $this->api->getUsers()); + } + + public function testGetUsersAsRegularUser() { + $_GET['search'] = 'MyCustomSearch'; + + $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') + ->will($this->returnValue(false)); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') + ->disableOriginalConstructor()->getMock(); + $subAdminManager + ->expects($this->once()) + ->method('isSubAdmin') + ->with($loggedInUser) + ->will($this->returnValue(false)); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + + $expected = new \OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED); + $this->assertEquals($expected, $this->api->getUsers()); + } + + public function testAddUserAlreadyExisting() { + $_POST['userid'] = 'AlreadyExistingUser'; + $this->userManager + ->expects($this->once()) + ->method('userExists') + ->with('AlreadyExistingUser') + ->will($this->returnValue(true)); + $this->logger + ->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()); + } + + 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); - $userManager->expects($this->once()) + $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($uid) + ->with('NewUser') ->willReturn(false); - $userManager->expects($this->once()) + $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'; + $this->userManager + ->expects($this->once()) + ->method('userExists') + ->with('NewUser') + ->will($this->returnValue(false)); + $this->userManager + ->expects($this->once()) ->method('createUser') - ->with($uid, 'password') - ->will($this->throwException(new \Exception)); - - $api = new \OCA\Provisioning_Api\Users( - $userManager, - $this->config, - $this->groupManager, - $this->userSession - ); + ->with('NewUser', 'PasswordOfTheNewUser'); + $this->logger + ->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()); + } - $this->resetParams(); - $_POST['userid'] = $uid; - $_POST['password'] = 'password'; - $result = $api->addUser(); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertEquals(101, $result->getStatusCode()); - $this->assertEquals('Bad request', $result->getMeta()['message']); - } - - public function testGetUserOnSelf() { - $user = $this->generateUsers(); - $user->setDisplayName('foobar'); - $this->userSession->setUser($user); - $params['userid'] = $user->getUID(); - $result = $this->api->getUser($params); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $data = $result->getData(); - - $this->assertEquals('foobar', $data['displayname']); - } - - public function testGetUserOnNonExistingUser() { - $user = $this->generateUsers(); - $this->groupManager->get('admin')->addUser($user); - $this->userSession->setUser($user); - $params = array(); - $params['userid'] = $this->getUniqueID(); - while($this->userManager->userExists($params['userid'])) { - $params['userid'] = $this->getUniqueID(); - } - $result = $this->api->getUser($params); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertEquals(\OCP\API::RESPOND_NOT_FOUND, $result->getStatusCode()); - - } - - public function testGetUserOnOtherUser() { - $users = $this->generateUsers(2); - $params['userid'] = $users[0]; - $this->userSession->setUser($users[1]); - $result = $this->api->getUser($params); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - - // Now as as admin - $users = $this->generateUsers(2); - $params['userid'] = $users[0]->getUID(); - // login to generate home - $this->userSession->setUser($users[0]); - $this->groupManager->get('admin')->addUser($users[1]); - $this->userSession->setUser($users[1]); - $result = $this->api->getUser($params); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $data = $result->getData(); - $this->assertEquals(\OC::$server->getConfig()->getUserValue($users[0]->getUID(), 'core', 'enabled', 'true'), $data['enabled']); - } - - public function testEditOwnDisplayName() { - // Test editing own name - $user = $this->generateUsers(); - $this->userSession->setUser($user); - $result = $this->api->editUser( - array( - 'userid' => $user->getUID(), - '_put' => array( - 'key' => 'display', - 'value' => 'newname', - ), - ) + 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']] ); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $this->assertEquals('newname', $user->getDisplayName()); + $expected = new \OC_OCS_Result(null, 100); + $this->assertEquals($expected, $this->api->addUser()); } - public function testAdminEditDisplayNameOfUser() { - // Test admin editing users name - $user = $this->generateUsers(); - $this->groupManager->get('admin')->addUser($user); - $this->userSession->setUser($user); - $user2 = $this->generateUsers(); - $result = $this->api->editUser( - [ - 'userid' => $user2->getUID(), - '_put' => [ - 'key' => 'display', - 'value' => 'newname', - ], - ] - ); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $this->assertEquals('newname', $user2->getDisplayName()); - - } - - public function testUserEditOtherUserDisplayName() { - // Test editing other users name - $user = $this->generateUsers(); - $this->userSession->setUser($user); - $user2 = $this->generateUsers(); - $result = $this->api->editUser( - array( - 'userid' => $user2->getUID(), - '_put' => array( - 'key' => 'display', - 'value' => 'newname', - ), - ) + public function testAddUserUnsuccessful() { + $_POST['userid'] = 'NewUser'; + $_POST['password'] = 'PasswordOfTheNewUser'; + $this->userManager + ->expects($this->once()) + ->method('userExists') + ->with('NewUser') + ->will($this->returnValue(false)); + $this->userManager + ->expects($this->once()) + ->method('createUser') + ->with('NewUser', 'PasswordOfTheNewUser') + ->will($this->throwException(new \Exception('User backend not found.'))); + $this->logger + ->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()); + } + + 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']] ); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); + $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()) + ->method('getUser') + ->will($this->returnValue(null)); + + $expected = new \OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED); + $this->assertEquals($expected, $this->api->getUser(['userid' => 'UserToGet'])); + } + + public function testGetUserTargetDoesNotExist() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToGet') + ->will($this->returnValue(null)); + + $expected = new \OC_OCS_Result(null, \OCP\API::RESPOND_NOT_FOUND, 'The requested user could not be found'); + $this->assertEquals($expected, $this->api->getUser(['userid' => 'UserToGet'])); } - /** - * @dataProvider providesQuotas - * @param $expected - * @param $quota - */ - public function testEditOwnQuota($expected, $quota) { - $user = $this->generateUsers(); - $this->userSession->setUser($user); - $result = $this->api->editUser( + public function testGetUserAsAdmin() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('admin')); + $targetUser = $this->getMock('\OCP\IUser'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToGet') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('admin') + ->will($this->returnValue(true)); + $this->config + ->expects($this->at(0)) + ->method('getUserValue') + ->with('UserToGet', 'core', 'enabled', 'true') + ->will($this->returnValue('true')); + $this->api + ->expects($this->once()) + ->method('fillStorageInfo') + ->with('UserToGet') + ->will($this->returnValue(['DummyValue'])); + $this->config + ->expects($this->at(1)) + ->method('getUserValue') + ->with('UserToGet', 'settings', 'email') + ->will($this->returnValue('demo@owncloud.org')); + $targetUser + ->expects($this->once()) + ->method('getDisplayName') + ->will($this->returnValue('Demo User')); + + $expected = new \OC_OCS_Result( [ - 'userid' => $user->getUID(), - '_put' => [ - 'key' => 'quota', - 'value' => $quota, - ], + 'enabled' => 'true', + 'quota' => ['DummyValue'], + 'email' => 'demo@owncloud.org', + 'displayname' => 'Demo User', ] - ); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertEquals(997, $result->getStatusCode()); - } - - /** - * @dataProvider providesQuotas - * @param $expected - * @param $quota - */ - public function testEditOwnQuotaAsAdmin($expected, $quota) { - $user = $this->generateUsers(); - $this->groupManager->get('admin')->addUser($user); - $this->userSession->setUser($user); - $result = $this->api->editUser( + ); + $this->assertEquals($expected, $this->api->getUser(['userid' => 'UserToGet'])); + } + + public function testGetUserAsSubAdminAndUserIsAccessible() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('subadmin')); + $targetUser = $this->getMock('\OCP\IUser'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToGet') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('subadmin') + ->will($this->returnValue(false)); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') + ->disableOriginalConstructor() + ->getMock(); + $subAdminManager + ->expects($this->once()) + ->method('isUserAccessible') + ->with($loggedInUser, $targetUser) + ->will($this->returnValue(true)); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + $this->config + ->expects($this->at(0)) + ->method('getUserValue') + ->with('UserToGet', 'core', 'enabled', 'true') + ->will($this->returnValue('true')); + $this->api + ->expects($this->once()) + ->method('fillStorageInfo') + ->with('UserToGet') + ->will($this->returnValue(['DummyValue'])); + $this->config + ->expects($this->at(1)) + ->method('getUserValue') + ->with('UserToGet', 'settings', 'email') + ->will($this->returnValue('demo@owncloud.org')); + $targetUser + ->expects($this->once()) + ->method('getDisplayName') + ->will($this->returnValue('Demo User')); + + $expected = new \OC_OCS_Result( [ - 'userid' => $user->getUID(), - '_put' => [ - 'key' => 'quota', - 'value' => $quota, - ], + 'enabled' => 'true', + 'quota' => ['DummyValue'], + 'email' => 'demo@owncloud.org', + 'displayname' => 'Demo User', ] - ); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertEquals($expected, $result->succeeded()); - } - - public function providesQuotas() { - return [ - [true, '20G'], - [true, '1234567'], - [true, 'none'], - [true, 'default'], - [false, 'qwertzu'], - [true, 0], - [true, -1] - ]; - } - - public function testAdminEditOwnQuota() { - $user = $this->generateUsers(); - $this->groupManager->get('admin')->addUser($user); - $this->userSession->setUser($user); - $result = $this->api->editUser( - array( - 'userid' => $user->getUID(), - '_put' => array( - 'key' => 'quota', - 'value' => '20G', - ), - ) - ); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - } - - public function testAdminEditOtherUserQuota() { - $user = $this->generateUsers(); - $this->groupManager->get('admin')->addUser($user); - $this->userSession->setUser($user); - $user2 = $this->generateUsers(); - $result = $this->api->editUser( - array( - 'userid' => $user2->getUID(), - '_put' => array( - 'key' => 'quota', - 'value' => '20G', - ), - ) - ); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - } - - public function testUserEditOtherUserQuota() { - $user = $this->generateUsers(); - $this->userSession->setUser($user); - $user2 = $this->generateUsers(); - $result = $this->api->editUser( - array( - 'userid' => $user2->getUID(), - '_put' => array( - 'key' => 'quota', - 'value' => '20G', - ), - ) - ); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - } - - public function testUserEditOwnEmail() { - $user = $this->generateUsers(); - $email = 'test@example.com'; - $this->userSession->setUser($user); - $result = $this->api->editUser( - array( - 'userid' => $user->getUID(), - '_put' => array( - 'key' => 'email', - 'value' => $email, - ), - ) - ); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $this->assertEquals($email, \OC::$server->getConfig()->getUserValue($user->getUID(), 'settings', 'email', null)); - } - - public function testUserEditOwnEmailInvalid() { - $user = $this->generateUsers(); - $email = 'test@example'; - $this->userSession->setUser($user); - $result = $this->api->editUser([ - 'userid' => $user->getUID(), - '_put' => [ - 'key' => 'email', - 'value' => $email, - ], - ]); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertEquals(102, $result->getStatusCode()); - } - - public function testUserEditOtherUserEmailAsUser() { - $users = $this->generateUsers(2); - $email = 'test@example.com'; - $this->userSession->setUser($users[0]); - $result = $this->api->editUser( - array( - 'userid' => $users[1]->getUID(), - '_put' => array( - 'key' => 'email', - 'value' => $email, - ), - ) - ); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - } - - public function testUserEditOtherUserEmailAsAdmin() { - $users = $this->generateUsers(2); - $email = 'test@example.com'; - $this->userSession->setUser($users[0]); - $this->groupManager->get('admin')->addUser($users[0]); - $result = $this->api->editUser( - array( - 'userid' => $users[1]->getUID(), - '_put' => array( - 'key' => 'email', - 'value' => $email, - ), - ) - ); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $this->assertEquals($email, \OC::$server->getConfig()->getUserValue($users[1]->getUID(), 'settings', 'email', null)); - } - - public function testUserEditOwnPassword() { - $user = $this->generateUsers(); - $password = 'foo'; - $this->userSession->setUser($user); - $result = $this->api->editUser([ - 'userid' => $user->getUID(), - '_put' => [ - 'key' => 'password', - 'value' => $password, - ], - ]); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - } - - public function testUserEditOtherUserPasswordAsUser() { - $users = $this->generateUsers(2); - $password = 'foo'; - $this->userSession->setUser($users[0]); - $result = $this->api->editUser([ - 'userid' => $users[1]->getUID(), - '_put' => [ - 'key' => 'password', - 'value' => $password, - ], - ]); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - } - - public function testUserEditOtherUserPasswordAsAdmin() { - $users = $this->generateUsers(2); - $password = 'foo'; - $this->userSession->setUser($users[0]); - $this->groupManager->get('admin')->addUser($users[0]); - $result = $this->api->editUser([ - 'userid' => $users[1]->getUID(), - '_put' => [ - 'key' => 'password', - 'value' => $password, - ], - ]); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - } - - public function testDeleteSelf() { - $user = $this->generateUsers(); - $this->userSession->setUser($user); - $result = $this->api->deleteUser(array( - 'userid' => $user->getUID(), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - } - - public function testDeleteOtherAsUser() { - $user = $this->generateUsers(); - $this->userSession->setUser($user); - $user2 = $this->generateUsers(); - $result = $this->api->deleteUser(array( - 'userid' => $user2->getUID(), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - } - - public function testDeleteOtherAsSubAdmin() { - $user = $this->generateUsers(); - $this->userSession->setUser($user); - $user2 = $this->generateUsers(); - $group = $this->groupManager->createGroup($this->getUniqueID()); - $group->addUser($user); - $group->addUser($user2); - \OC_SubAdmin::createSubAdmin($user->getUID(), $group->getGID()); - $result = $this->api->deleteUser(array( - 'userid' => $user2->getUID(), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $group->delete(); - } - - public function testDeleteOtherAsIrelevantSubAdmin() { - $user = $this->generateUsers(); - $this->userSession->setUser($user); - $user2 = $this->generateUsers(); - $group = $this->groupManager->createGroup($this->getUniqueID()); - $group2 = $this->groupManager->createGroup($this->getUniqueID()); - $group->addUser($user); - $group2->addUser($user2); - \OC_SubAdmin::createSubAdmin($user->getUID(), $group->getGID()); - $result = $this->api->deleteUser(array( - 'userid' => $user2->getUID(), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $group->delete(); - $group2->delete(); - } - - public function testDeleteOtherAsAdmin() { - $user = $this->generateUsers(); - $this->groupManager->get('admin')->addUser($user); - $this->userSession->setUser($user); - $user2 = $this->generateUsers(); - $result = $this->api->deleteUser(array( - 'userid' => $user2->getUID(), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - } - - public function testDeleteSelfAsAdmin() { - $user = $this->generateUsers(); - $this->groupManager->get('admin')->addUser($user); - $this->userSession->setUser($user); - $result = $this->api->deleteUser(array( - 'userid' => $user->getUID(), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - } - - public function testDeleteFails() { - $user = $this->getMockBuilder('\OCP\IUser') + ); + $this->assertEquals($expected, $this->api->getUser(['userid' => 'UserToGet'])); + } + + public function testGetUserAsSubAdminAndUserIsNotAccessible() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->exactly(2)) + ->method('getUID') + ->will($this->returnValue('subadmin')); + $targetUser = $this->getMock('\OCP\IUser'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToGet') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('subadmin') + ->will($this->returnValue(false)); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') ->disableOriginalConstructor() ->getMock(); - $user->expects($this->once()) - ->method('delete') - ->willReturn(false); + $subAdminManager + ->expects($this->once()) + ->method('isUserAccessible') + ->with($loggedInUser, $targetUser) + ->will($this->returnValue(false)); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + + $expected = new \OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED); + $this->assertEquals($expected, $this->api->getUser(['userid' => 'UserToGet'])); + } - $user2 = $this->getMockBuilder('\OCP\IUser') + public function testGetUserAsSubAdminSelfLookup() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->exactly(2)) + ->method('getUID') + ->will($this->returnValue('subadmin')); + $targetUser = $this->getMock('\OCP\IUser'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('subadmin') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('subadmin') + ->will($this->returnValue(false)); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') ->disableOriginalConstructor() ->getMock(); - $user2->expects($this->any()) + $subAdminManager + ->expects($this->once()) + ->method('isUserAccessible') + ->with($loggedInUser, $targetUser) + ->will($this->returnValue(false)); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + $this->api + ->expects($this->once()) + ->method('fillStorageInfo') + ->with('subadmin') + ->will($this->returnValue(['DummyValue'])); + $this->config + ->expects($this->once()) + ->method('getUserValue') + ->with('subadmin', 'settings', 'email') + ->will($this->returnValue('subadmin@owncloud.org')); + $targetUser + ->expects($this->once()) + ->method('getDisplayName') + ->will($this->returnValue('Subadmin User')); + + $expected = new \OC_OCS_Result([ + 'quota' => ['DummyValue'], + 'email' => 'subadmin@owncloud.org', + 'displayname' => 'Subadmin User', + ]); + $this->assertEquals($expected, $this->api->getUser(['userid' => 'subadmin'])); + } + + public function testEditUserNotLoggedIn() { + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue(null)); + + $expected = new \OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED); + $this->assertEquals($expected, $this->api->editUser(['userid' => 'UserToEdit'])); + } + + public function testEditUserRegularUserSelfEditChangeDisplayName() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->any()) ->method('getUID') - ->willReturn('user2'); + ->will($this->returnValue('UserToEdit')); + $targetUser = $this->getMock('\OCP\IUser'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToEdit') + ->will($this->returnValue($targetUser)); + $targetUser + ->expects($this->once()) + ->method('setDisplayName') + ->with('NewDisplayName'); + + $expected = new \OC_OCS_Result(null, 100); + $this->assertEquals($expected, $this->api->editUser(['userid' => 'UserToEdit', '_put' => ['key' => 'display', 'value' => 'NewDisplayName']])); + } - $userManager = $this->getMockBuilder('\OCP\IUserManager') + public function testEditUserRegularUserSelfEditChangeEmailValid() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('UserToEdit')); + $targetUser = $this->getMock('\OCP\IUser'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToEdit') + ->will($this->returnValue($targetUser)); + $this->config + ->expects($this->once()) + ->method('setUserValue') + ->with('UserToEdit', 'settings', 'email', 'demo@owncloud.org'); + + $expected = new \OC_OCS_Result(null, 100); + $this->assertEquals($expected, $this->api->editUser(['userid' => 'UserToEdit', '_put' => ['key' => 'email', 'value' => 'demo@owncloud.org']])); + } + + public function testEditUserRegularUserSelfEditChangeEmailInvalid() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('UserToEdit')); + $targetUser = $this->getMock('\OCP\IUser'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToEdit') + ->will($this->returnValue($targetUser)); + + $expected = new \OC_OCS_Result(null, 102); + $this->assertEquals($expected, $this->api->editUser(['userid' => 'UserToEdit', '_put' => ['key' => 'email', 'value' => 'demo.org']])); + } + + public function testEditUserRegularUserSelfEditChangePassword() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('UserToEdit')); + $targetUser = $this->getMock('\OCP\IUser'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToEdit') + ->will($this->returnValue($targetUser)); + $targetUser + ->expects($this->once()) + ->method('setPassword') + ->with('NewPassword'); + + $expected = new \OC_OCS_Result(null, 100); + $this->assertEquals($expected, $this->api->editUser(['userid' => 'UserToEdit', '_put' => ['key' => 'password', 'value' => 'NewPassword']])); + } + + public function testEditUserRegularUserSelfEditChangeQuota() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('UserToEdit')); + $targetUser = $this->getMock('\OCP\IUser'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToEdit') + ->will($this->returnValue($targetUser)); + + $expected = new \OC_OCS_Result(null, 997); + $this->assertEquals($expected, $this->api->editUser(['userid' => 'UserToEdit', '_put' => ['key' => 'quota', 'value' => 'NewQuota']])); + } + + public function testEditUserAdminUserSelfEditChangeValidQuota() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('UserToEdit')); + $targetUser = $this->getMock('\OCP\IUser'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToEdit') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('UserToEdit') + ->will($this->returnValue(true)); + $this->config + ->expects($this->once()) + ->method('setUserValue') + ->with('UserToEdit', 'files', 'quota', '2.9 MB'); + + $expected = new \OC_OCS_Result(null, 100); + $this->assertEquals($expected, $this->api->editUser(['userid' => 'UserToEdit', '_put' => ['key' => 'quota', 'value' => '3042824']])); + } + + public function testEditUserAdminUserSelfEditChangeInvalidQuota() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('UserToEdit')); + $targetUser = $this->getMock('\OCP\IUser'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToEdit') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('UserToEdit') + ->will($this->returnValue(true)); + + $expected = new \OC_OCS_Result(null, 103, 'Invalid quota value ABC'); + $this->assertEquals($expected, $this->api->editUser(['userid' => 'UserToEdit', '_put' => ['key' => 'quota', 'value' => 'ABC']])); + } + + public function testEditUserAdminUserEditChangeValidQuota() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('admin')); + $targetUser = $this->getMock('\OCP\IUser'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToEdit') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('admin') + ->will($this->returnValue(true)); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') ->disableOriginalConstructor() ->getMock(); - $userManager->expects($this->once()) - ->method('userExists') - ->with('user') - ->willReturn(true); - $userManager->expects($this->once()) - ->method('get') - ->with('user') - ->willReturn($user); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + $this->config + ->expects($this->once()) + ->method('setUserValue') + ->with('UserToEdit', 'files', 'quota', '2.9 MB'); + + $expected = new \OC_OCS_Result(null, 100); + $this->assertEquals($expected, $this->api->editUser(['userid' => 'UserToEdit', '_put' => ['key' => 'quota', 'value' => '3042824']])); + } - $userSession = $this->getMockBuilder('\OCP\IUserSession') + public function testEditUserSubadminUserAccessible() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('subadmin')); + $targetUser = $this->getMock('\OCP\IUser'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToEdit') + ->will($this->returnValue($targetUser)); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') ->disableOriginalConstructor() ->getMock(); - $userSession->expects($this->once()) + $subAdminManager + ->expects($this->once()) + ->method('isUserAccessible') + ->with($loggedInUser, $targetUser) + ->will($this->returnValue(true)); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + $this->config + ->expects($this->once()) + ->method('setUserValue') + ->with('UserToEdit', 'files', 'quota', '2.9 MB'); + + $expected = new \OC_OCS_Result(null, 100); + $this->assertEquals($expected, $this->api->editUser(['userid' => 'UserToEdit', '_put' => ['key' => 'quota', 'value' => '3042824']])); + } + + public function testEditUserSubadminUserInaccessible() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('subadmin')); + $targetUser = $this->getMock('\OCP\IUser'); + $this->userSession + ->expects($this->once()) ->method('getUser') - ->willReturn($user2); - - $groupManager = $this->getMockBuilder('\OCP\IGroupManager') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToEdit') + ->will($this->returnValue($targetUser)); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') ->disableOriginalConstructor() ->getMock(); - $groupManager->expects($this->once()) + $subAdminManager + ->expects($this->once()) + ->method('isUserAccessible') + ->with($loggedInUser, $targetUser) + ->will($this->returnValue(false)); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + + $expected = new \OC_OCS_Result(null, 997); + $this->assertEquals($expected, $this->api->editUser(['userid' => 'UserToEdit', '_put' => ['key' => 'quota', 'value' => '3042824']])); + } + + public function testDeleteUserNotLoggedIn() { + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue(null)); + + $expected = new \OC_OCS_Result(null, 997); + $this->assertEquals($expected, $this->api->deleteUser(['userid' => 'UserToDelete'])); + } + + public function testDeleteUserNotExistingUser() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('UserToEdit')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToDelete') + ->will($this->returnValue(null)); + + $expected = new \OC_OCS_Result(null, 101); + $this->assertEquals($expected, $this->api->deleteUser(['userid' => 'UserToDelete'])); + } + + public function testDeleteUserSelf() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('UserToDelete')); + $targetUser = $this->getMock('\OCP\IUser'); + $targetUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('UserToDelete')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToDelete') + ->will($this->returnValue($targetUser)); + + $expected = new \OC_OCS_Result(null, 101); + $this->assertEquals($expected, $this->api->deleteUser(['userid' => 'UserToDelete'])); + } + + public function testDeleteSuccessfulUserAsAdmin() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('admin')); + $targetUser = $this->getMock('\OCP\IUser'); + $targetUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('UserToDelete')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToDelete') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) ->method('isAdmin') - ->with('user2') - ->willReturn(true); + ->with('admin') + ->will($this->returnValue(true)); + $targetUser + ->expects($this->once()) + ->method('delete') + ->will($this->returnValue(true)); - $api = new \OCA\Provisioning_Api\Users( - $userManager, - $this->config, - $groupManager, - $userSession - ); + $expected = new \OC_OCS_Result(null, 100); + $this->assertEquals($expected, $this->api->deleteUser(['userid' => 'UserToDelete'])); + } - $result = $api->deleteUser([ - 'userid' => 'user', - ]); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertEquals(101, $result->getStatusCode()); - } - - public function testGetUsersGroupsOnSelf() { - $user = $this->generateUsers(); - $this->userSession->setUser($user); - $group = $this->getUniqueID(); - $group = $this->groupManager->createGroup($group); - $group->addUser($user); - $result = $this->api->getUsersGroups(array( - 'userid' => $user->getUID(), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $data = $result->getData(); - $this->assertEquals($group->getGID(), reset($data['groups'])); - $this->assertEquals(1, count($data['groups'])); - $group->delete(); - } - - public function testGetUsersGroupOnOther() { - $user1 = $this->generateUsers(); - $user2 = $this->generateUsers(); - $this->userSession->setUser($user1); - $group = $this->getUniqueID(); - $group = $this->groupManager->createGroup($group); - $group->addUser($user2); - $result = $this->api->getUsersGroups(array( - 'userid' => $user2->getUID(), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $group->delete(); - } - - public function testGetUsersGroupOnOtherAsAdmin() { - $user1 = $this->generateUsers(); - $this->groupManager->get('admin')->addUser($user1); - $user2 = $this->generateUsers(); - $this->userSession->setUser($user1); - $group = $this->getUniqueID(); - $group = $this->groupManager->createGroup($group); - $group->addUser($user2); - $result = $this->api->getUsersGroups(array( - 'userid' => $user2->getUID(), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $data = $result->getData(); - $this->assertEquals($group->getGID(), reset($data['groups'])); - $this->assertEquals(1, count($data['groups'])); - $group->delete(); - } - - public function testGetUsersGroupsOnOtherAsSubAdmin() { - $user1 = $this->generateUsers(); - $user2 = $this->generateUsers(); - $this->userSession->setUser($user1); - $group1 = $this->getUniqueID(); - $group2 = $this->getUniqueID(); - $group1 = $this->groupManager->createGroup($group1); - $group2 = $this->groupManager->createGroup($group2); - $group1->addUser($user2); - $group2->addUser($user2); - $group1->addUser($user1); - \OC_SubAdmin::createSubAdmin($user1->getUID(), $group1->getGID()); - $result = $this->api->getUsersGroups(array( - 'userid' => $user2->getUID(), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $data = $result->getData(); - $this->assertEquals($group1->getGID(), reset($data['groups'])); - $this->assertEquals(1, count($data['groups'])); - $group1->delete(); - $group2->delete(); - } - - public function testGetUsersGroupsOnOtherAsIrelevantSubAdmin() { - $user1 = $this->generateUsers(); - $user2 = $this->generateUsers(); - $this->userSession->setUser($user1); - $group1 = $this->getUniqueID(); - $group2 = $this->getUniqueID(); - $group1 = $this->groupManager->createGroup($group1); - $group2 = $this->groupManager->createGroup($group2); - $group2->addUser($user2); - $group1->addUser($user1); - \OC_SubAdmin::createSubAdmin($user1->getUID(), $group1->getGID()); - $result = $this->api->getUsersGroups(array( - 'userid' => $user2->getUID(), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $group1->delete(); - $group2->delete(); - } - - public function testAddToGroup() { - $user = $this->generateUsers(); - $group = $this->getUniqueID(); - $group = $this->groupManager->createGroup($group); - $this->userSession->setUser($user); - $_POST['groupid'] = $group->getGID(); - $result = $this->api->addToGroup(array( - 'userid' => $user->getUID(), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertFalse($group->inGroup($user)); - $group->delete(); - } - - public function testAddToGroupAsAdmin() { - $user = $this->generateUsers(); - $this->groupManager->get('admin')->addUser($user); - $group = $this->getUniqueID(); - $group = $this->groupManager->createGroup($group); - $user2 = $this->generateUsers(); - $this->userSession->setUser($user); - $_POST['groupid'] = $group->getGID(); - $result = $this->api->addToGroup(array( - 'userid' => $user2->getUID(), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $this->assertTrue($group->inGroup($user2)); - $group->delete(); - } - - public function testAddToGroupAsSubAdmin() { - $user1 = $this->generateUsers(); - $user2 = $this->generateUsers(); - $this->userSession->setUser($user1); - $group1 = $this->getUniqueID(); - $group1 = $this->groupManager->createGroup($group1); - \OC_SubAdmin::createSubAdmin($user1->getUID(), $group1->getGID()); - $_POST['groupid'] = $group1->getGID(); - $result = $this->api->addToGroup(array( - 'userid' => $user2->getUID(), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertFalse($group1->inGroup($user2)); - $group1->delete(); - } - - public function testAddToGroupAsIrelevantSubAdmin() { - $user1 = $this->generateUsers(); - $user2 = $this->generateUsers(); - $this->userSession->setUser($user1); - $group1 = $this->getUniqueID(); - $group2 = $this->getUniqueID(); - $group1 = $this->groupManager->createGroup($group1); - $group2 = $this->groupManager->createGroup($group2); - \OC_SubAdmin::createSubAdmin($user1->getUID(), $group1->getGID()); - $_POST['groupid'] = $group2->getGID(); - $result = $this->api->addToGroup(array( - 'userid' => $user2->getUID(), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertFalse($group2->inGroup($user2)); - $group1->delete(); - $group2->delete(); - } - - public function testAddToGroupNoGroupId() { - $user = $this->generateUsers(); - $this->userSession->setUser($user); - - $_POST['groupid'] = ''; - $result = $this->api->addToGroup([ - 'userid' => $this->getUniqueID(), - ]); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertEquals(101, $result->getStatusCode()); + public function testDeleteUnsuccessfulUserAsAdmin() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('admin')); + $targetUser = $this->getMock('\OCP\IUser'); + $targetUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('UserToDelete')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToDelete') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('admin') + ->will($this->returnValue(true)); + $targetUser + ->expects($this->once()) + ->method('delete') + ->will($this->returnValue(false)); + + $expected = new \OC_OCS_Result(null, 101); + $this->assertEquals($expected, $this->api->deleteUser(['userid' => 'UserToDelete'])); } - public function testAddToNonExistingGroup() { - $user = $this->generateUsers(); - $this->groupManager->get('admin')->addUser($user); - $this->userSession->setUser($user); + public function testDeleteSuccessfulUserAsSubadmin() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('subadmin')); + $targetUser = $this->getMock('\OCP\IUser'); + $targetUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('UserToDelete')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToDelete') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('subadmin') + ->will($this->returnValue(false)); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') + ->disableOriginalConstructor()->getMock(); + $subAdminManager + ->expects($this->once()) + ->method('isUserAccessible') + ->with($loggedInUser, $targetUser) + ->will($this->returnValue(true)); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + $targetUser + ->expects($this->once()) + ->method('delete') + ->will($this->returnValue(true)); - $group = $this->groupManager->createGroup($this->getUniqueID()); - $_POST['groupid'] = $group->getGID(); - $result = $this->api->addToGroup([ - 'userid' => $this->getUniqueID(), - ]); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertEquals(103, $result->getStatusCode()); + $expected = new \OC_OCS_Result(null, 100); + $this->assertEquals($expected, $this->api->deleteUser(['userid' => 'UserToDelete'])); } - public function testAddNonExistingUserToGroup() { - $user = $this->generateUsers(); - $this->groupManager->get('admin')->addUser($user); - $this->userSession->setUser($user); + public function testDeleteUnsuccessfulUserAsSubadmin() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('subadmin')); + $targetUser = $this->getMock('\OCP\IUser'); + $targetUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('UserToDelete')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToDelete') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('subadmin') + ->will($this->returnValue(false)); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') + ->disableOriginalConstructor()->getMock(); + $subAdminManager + ->expects($this->once()) + ->method('isUserAccessible') + ->with($loggedInUser, $targetUser) + ->will($this->returnValue(true)); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + $targetUser + ->expects($this->once()) + ->method('delete') + ->will($this->returnValue(false)); - $_POST['groupid'] = $this->getUniqueID(); - $result = $this->api->addToGroup([ - 'userid' => $this->getUniqueID(), - ]); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertEquals(102, $result->getStatusCode()); - } - - // test delete /cloud/users/{userid}/groups - public function testRemoveFromGroupAsSelf() { - $user1 = $this->generateUsers(); - $this->userSession->setUser($user1); - $group1 = $this->getUniqueID(); - $group1 = $this->groupManager->createGroup($group1); - $group1->addUser($user1); - $result = $this->api->removeFromGroup(array( - 'userid' => $user1->getUID(), - '_delete' => array( - 'groupid' => $group1->getGID(), - ), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertTrue($group1->inGroup($user1)); - $group1->delete(); - } - - public function testRemoveFromGroupAsAdmin() { - $user1 = $this->generateUsers(); - $user2 = $this->generateUsers(); - $this->userSession->setUser($user1); - $group1 = $this->getUniqueID(); - $group1 = $this->groupManager->createGroup($group1); - $group1->addUser($user2); - $this->groupManager->get('admin')->addUser($user1); - $result = $this->api->removeFromGroup(array( - 'userid' => $user2->getUID(), - '_delete' => array( - 'groupid' => $group1->getGID(), - ), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $this->assertFalse($group1->inGroup($user2)); - $group1->delete(); - } - - public function testRemoveSelfFromGroupAsAdmin() { - $user1 = $this->generateUsers(); - $this->userSession->setUser($user1); - $group1 = $this->groupManager->createGroup($this->getUniqueID()); - $group1->addUser($user1); - $this->groupManager->get('admin')->addUser($user1); - $result = $this->api->removeFromGroup([ - 'userid' => $user1->getUID(), - '_delete' => [ - 'groupid' => $group1->getGID(), - ], - ]); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $this->assertFalse($group1->inGroup($user1)); - $group1->delete(); - } - - public function testRemoveFromGroupAsSubAdmin() { - $user1 = $this->generateUsers(); - $this->userSession->setUser($user1); - $user2 = $this->generateUsers(); - $group1 = $this->getUniqueID(); - $group1 = $this->groupManager->createGroup($group1); - $group1->addUser($user1); - $group1->addUser($user2); - \OC_SubAdmin::createSubAdmin($user1->getUID(), $group1->getGID()); - $result = $this->api->removeFromGroup(array( - 'userid' => $user2->getUID(), - '_delete' => array( - 'groupid' => $group1->getGID(), - ), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $this->assertFalse($group1->inGroup($user2)); - $group1->delete(); - } - - public function testRemoveFromGroupAsIrelevantSubAdmin() { - $user1 = $this->generateUsers(); - $this->userSession->setUser($user1); - $user2 = $this->generateUsers(); - $group1 = $this->getUniqueID(); - $group2 = $this->getUniqueID(); - $group1 = $this->groupManager->createGroup($group1); - $group2 = $this->groupManager->createGroup($group2); - $group1->addUser($user1); - $group2->addUser($user2); - \OC_SubAdmin::createSubAdmin($user1->getUID(), $group1->getGID()); - $result = $this->api->removeFromGroup(array( - 'userid' => $user2->getUID(), - '_delete' => array( - 'groupid' => $group2->getGID(), - ), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertTrue($group2->inGroup($user2)); - $group1->delete(); - $group2->delete(); - } - - public function testRemoveFromGroupNoGroupId() { - $user = $this->generateUsers(); - $this->userSession->setUser($user); - - $result = $this->api->removeFromGroup([ - '_delete' => [ - 'groupid' => '' - ], - ]); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertEquals(101, $result->getStatusCode()); + $expected = new \OC_OCS_Result(null, 101); + $this->assertEquals($expected, $this->api->deleteUser(['userid' => 'UserToDelete'])); } - public function testRemoveSelfFromAdminAsAdmin() { - $user = $this->generateUsers(); - $this->userSession->setUser($user); - $this->groupManager->get('admin')->addUser($user); + public function testDeleteUserAsSubAdminAndUserIsNotAccessible() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('subadmin')); + $targetUser = $this->getMock('\OCP\IUser'); + $targetUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('UserToDelete')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToDelete') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('subadmin') + ->will($this->returnValue(false)); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') + ->disableOriginalConstructor()->getMock(); + $subAdminManager + ->expects($this->once()) + ->method('isUserAccessible') + ->with($loggedInUser, $targetUser) + ->will($this->returnValue(false)); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + + $expected = new \OC_OCS_Result(null, 997); + $this->assertEquals($expected, $this->api->deleteUser(['userid' => 'UserToDelete'])); + } - $result = $this->api->removeFromGroup([ - 'userid' => $user->getUID(), - '_delete' => [ - 'groupid' => 'admin' - ], - ]); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertEquals(105, $result->getStatusCode()); - $this->assertEquals('Cannot remove yourself from the admin group', $result->getMeta()['message']); - } - - public function testRemoveSelfFromSubAdminGroupAsSubAdmin() { - $user = $this->generateUsers(); - $this->userSession->setUser($user); - $group = $this->groupManager->createGroup($this->getUniqueID()); - \OC_SubAdmin::createSubAdmin($user->getUID(), $group->getGID()); - - $result = $this->api->removeFromGroup([ - 'userid' => $user->getUID(), - '_delete' => [ - 'groupid' => $group->getGID() - ], - ]); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertEquals(105, $result->getStatusCode()); - $this->assertEquals('Cannot remove yourself from this group as you are a SubAdmin', $result->getMeta()['message']); - $group->delete(); - } - - public function testRemoveFromNonExistingGroup() { - $user1 = $this->generateUsers(); - $this->userSession->setUser($user1); - $this->groupManager->get('admin')->addUser($user1); - - $user2 = $this->generateUsers(); - $result = $this->api->removeFromGroup([ - 'userid' => $user2->getUID(), - '_delete' => [ - 'groupid' => $this->getUniqueID() - ], - ]); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertEquals(102, $result->getStatusCode()); + public function testGetUsersGroupsNotLoggedIn() { + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue(null)); + + $expected = new \OC_OCS_Result(null, 997); + $this->assertEquals($expected, $this->api->getUsersGroups(['userid' => 'UserToLookup'])); } - public function testRemoveFromNonGroupNonExistingUser() { - $user = $this->generateUsers(); - $this->userSession->setUser($user); - $this->groupManager->get('admin')->addUser($user); + public function testGetUsersGroupsTargetUserNotExisting() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); - $group = $this->groupManager->createGroup($this->getUniqueID()); + $expected = new \OC_OCS_Result(null, 998); + $this->assertEquals($expected, $this->api->getUsersGroups(['userid' => 'UserToLookup'])); + } - $result = $this->api->removeFromGroup([ - 'userid' => $this->getUniqueID(), - '_delete' => [ - 'groupid' => $group->getGID() - ], - ]); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertEquals(103, $result->getStatusCode()); - } - - - public function testCreateSubAdmin() { - $user1 = $this->generateUsers(); - $user2 = $this->generateUsers(); - $this->userSession->setUser($user1); - $this->groupManager->get('admin')->addUser($user1); - $group1 = $this->getUniqueID(); - $group1 = $this->groupManager->createGroup($group1); - $_POST['groupid'] = $group1->getGID(); - $result = $this->api->addSubAdmin(array( - 'userid' => $user2->getUID(), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $this->assertTrue(\OC_SubAdmin::isSubAdminofGroup($user2->getUID(), $group1->getGID())); - $group1->delete(); - - $this->resetParams(); - - $user1 = $this->generateUsers(); - $user2 = $this->generateUsers(); - $this->userSession->setUser($user1); - $this->groupManager->get('admin')->addUser($user1); - $_POST['groupid'] = 'admin'; - $result = $this->api->addSubAdmin(array( - 'userid' => $user2->getUID(), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertEquals(103, $result->getStatusCode()); - $this->assertFalse($result->succeeded()); - - $this->resetParams(); - - $user1 = $this->generateUsers(); - $this->userSession->setUser($user1); - $this->groupManager->get('admin')->addUser($user1); - $group1 = $this->getUniqueID(); - $group1 = $this->groupManager->createGroup($group1); - $_POST['groupid'] = $group1->getGID(); - $result = $this->api->addSubAdmin(array( - 'userid' => $this->getUniqueID(), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertEquals(101, $result->getStatusCode()); - $group1->delete(); - - $user1 = $this->generateUsers(); - $this->userSession->setUser($user1); - $group = $this->getUniqueID(); - $_POST['groupid'] = $group; - $result = $this->api->addSubAdmin([ - 'userid' => $user1->getUID() - ]); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertEquals(102, $result->getStatusCode()); - $this->assertEquals('Group:'.$group.' does not exist', $result->getMeta()['message']); - } - - public function testRemoveSubAdmin() { - $user1 = $this->generateUsers(); - $user2 = $this->generateUsers(); - $this->userSession->setUser($user1); - $this->groupManager->get('admin')->addUser($user1); - $group1 = $this->getUniqueID(); - $group1 = $this->groupManager->createGroup($group1); - \OC_SubAdmin::createSubAdmin($user2->getUID(), $group1->getGID()); - $result = $this->api->removeSubAdmin(array( - 'userid' => $user2->getUID(), - '_delete' => array( - 'groupid' => $group1->getGID(), - ), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $this->assertTrue(!\OC_SubAdmin::isSubAdminofGroup($user2->getUID(), $group1->getGID())); - $group1->delete(); - - $user1 = $this->generateUsers(); - $this->userSession->setUser($user1); - $this->groupManager->get('admin')->addUser($user1); - $result = $this->api->removeSubAdmin(array( - 'userid' => $this->getUniqueID(), - '_delete' => array( - 'groupid' => $group1->getGID(), - ), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertEquals(101, $result->getStatusCode()); - $this->assertFalse($result->succeeded()); - - $this->resetParams(); - - $user1 = $this->generateUsers(); - $user2 = $this->generateUsers(); - $this->userSession->setUser($user1); - $this->groupManager->get('admin')->addUser($user1); - $group1 = $this->getUniqueID(); - $group1 = $this->groupManager->createGroup($group1); - $_POST['groupid'] = $group1->getGID(); - $result = $this->api->removeSubAdmin(array( - 'userid' => $user2->getUID(), - '_delete' => array( - 'groupid' => $group1->getGID(), - ), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertEquals(102, $result->getStatusCode()); - $group1->delete(); - } - - public function testGetSubAdminGroups() { - $user1 = $this->generateUsers(); - $user2 = $this->generateUsers(); - $this->userSession->setUser($user1); - $this->groupManager->get('admin')->addUser($user1); - $group1 = $this->getUniqueID(); - $group1 = $this->groupManager->createGroup($group1); - \OC_SubAdmin::createSubAdmin($user2->getUID(), $group1->getGID()); - $result = $this->api->getUserSubAdminGroups(array( - 'userid' => $user2->getUID(), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $data = $result->getData(); - $this->assertEquals($group1->getGID(), reset($data)); - $group1->delete(); - - $user1 = $this->generateUsers(); - $this->userSession->setUser($user1); - $this->groupManager->get('admin')->addUser($user1); - $result = $this->api->getUserSubAdminGroups(array( - 'userid' => $this->getUniqueID(), - )); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertFalse($result->succeeded()); - $this->assertEquals(101, $result->getStatusCode()); - } - - public function testSubAdminOfGroupAlreadySubAdmin() { - $user1 = $this->generateUsers(); - $user2 = $this->generateUsers(); - $this->userSession->setUser($user1); - $this->groupManager->get('admin')->addUser($user1); - $group1 = $this->groupManager->createGroup($this->getUniqueID()); - - //Make user2 subadmin of group1 - $_POST['groupid'] = $group1->getGID(); - $result = $this->api->addSubAdmin([ - 'userid' => $user2->getUID(), - ]); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); + public function testGetUsersGroupsSelfTargetted() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('UserToLookup')); + $targetUser = $this->getMock('\OCP\IUser'); + $targetUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('UserToLookup')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToLookup') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) + ->method('getUserGroupIds') + ->with($targetUser) + ->will($this->returnValue(['DummyValue'])); + + $expected = new \OC_OCS_Result(['groups' => ['DummyValue']]); + $this->assertEquals($expected, $this->api->getUsersGroups(['userid' => 'UserToLookup'])); + } - //Make user2 subadmin of group1 again - $_POST['groupid'] = $group1->getGID(); - $result = $this->api->addSubAdmin([ - 'userid' => $user2->getUID(), - ]); - $this->assertInstanceOf('OC_OCS_Result', $result); - $this->assertTrue($result->succeeded()); - $group1->delete(); + public function testGetUsersGroupsForAdminUser() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->exactly(2)) + ->method('getUID') + ->will($this->returnValue('admin')); + $targetUser = $this->getMock('\OCP\IUser'); + $targetUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('UserToLookup')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToLookup') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) + ->method('getUserGroupIds') + ->with($targetUser) + ->will($this->returnValue(['DummyValue'])); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('admin') + ->will($this->returnValue(true)); + + $expected = new \OC_OCS_Result(['groups' => ['DummyValue']]); + $this->assertEquals($expected, $this->api->getUsersGroups(['userid' => 'UserToLookup'])); + } + + public function testGetUsersGroupsForSubAdminUserAndUserIsAccessible() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->exactly(2)) + ->method('getUID') + ->will($this->returnValue('subadmin')); + $targetUser = $this->getMock('\OCP\IUser'); + $targetUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('UserToLookup')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToLookup') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('subadmin') + ->will($this->returnValue(false)); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') + ->disableOriginalConstructor()->getMock(); + $subAdminManager + ->expects($this->once()) + ->method('isUserAccessible') + ->with($loggedInUser, $targetUser) + ->will($this->returnValue(true)); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + $group1 = $this->getMock('\OCP\IGroup'); + $group1 + ->expects($this->any()) + ->method('getGID') + ->will($this->returnValue('Group1')); + $group2 = $this->getMock('\OCP\IGroup'); + $group2 + ->expects($this->any()) + ->method('getGID') + ->will($this->returnValue('Group2')); + $subAdminManager + ->expects($this->once()) + ->method('getSubAdminsGroups') + ->with($loggedInUser) + ->will($this->returnValue([$group1, $group2])); + $this->groupManager + ->expects($this->any()) + ->method('getUserGroupIds') + ->with($targetUser) + ->will($this->returnValue(['Group1'])); + + $expected = new \OC_OCS_Result(['groups' => ['Group1']]); + $this->assertEquals($expected, $this->api->getUsersGroups(['userid' => 'UserToLookup'])); + } + + + public function testGetUsersGroupsForSubAdminUserAndUserIsInaccessible() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->exactly(2)) + ->method('getUID') + ->will($this->returnValue('subadmin')); + $targetUser = $this->getMock('\OCP\IUser'); + $targetUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('UserToLookup')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('UserToLookup') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('subadmin') + ->will($this->returnValue(false)); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') + ->disableOriginalConstructor()->getMock(); + $subAdminManager + ->expects($this->once()) + ->method('isUserAccessible') + ->with($loggedInUser, $targetUser) + ->will($this->returnValue(false)); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + $this->groupManager + ->expects($this->any()) + ->method('getUserGroupIds') + ->with($targetUser) + ->will($this->returnValue(['Group1'])); + + $expected = new \OC_OCS_Result(null, 997); + $this->assertEquals($expected, $this->api->getUsersGroups(['userid' => 'UserToLookup'])); + } + + public function testAddToGroupNotLoggedIn() { + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue(null)); + + $expected = new \OC_OCS_Result(null, 997); + $this->assertEquals($expected, $this->api->addToGroup([])); + } + + public function testAddToGroupWithTargetGroupNotExisting() { + $_POST['groupid'] = 'GroupToAddTo'; + + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('admin')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('get') + ->with('GroupToAddTo') + ->will($this->returnValue(null)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('admin') + ->will($this->returnValue(true)); + + $expected = new \OC_OCS_Result(null, 102); + $this->assertEquals($expected, $this->api->addToGroup(['userid' => 'TargetUser'])); + } + + public function testAddToGroupWithNoGroupSpecified() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('admin')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('admin') + ->will($this->returnValue(true)); + + $expected = new \OC_OCS_Result(null, 101); + $this->assertEquals($expected, $this->api->addToGroup(['userid' => 'TargetUser'])); + } + + public function testAddToGroupWithTargetUserNotExisting() { + $_POST['groupid'] = 'GroupToAddTo'; + + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('admin')); + $targetGroup = $this->getMock('\OCP\IGroup'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('get') + ->with('GroupToAddTo') + ->will($this->returnValue($targetGroup)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('admin') + ->will($this->returnValue(true)); + + $expected = new \OC_OCS_Result(null, 103); + $this->assertEquals($expected, $this->api->addToGroup(['userid' => 'TargetUser'])); + } + + public function testAddToGroupWithoutPermission() { + $_POST['groupid'] = 'GroupToAddTo'; + + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('admin')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('admin') + ->will($this->returnValue(false)); + + $expected = new \OC_OCS_Result(null, 997); + $this->assertEquals($expected, $this->api->addToGroup(['userid' => 'TargetUser'])); + } + + public function testRemoveFromGroupWithoutLogIn() { + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue(null)); + + $expected = new \OC_OCS_Result(null, 997); + $this->assertEquals($expected, $this->api->removeFromGroup(['userid' => 'TargetUser', '_delete' => ['groupid' => 'TargetGroup']])); + } + + public function testRemoveFromGroupWithNoTargetGroup() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $expected = new \OC_OCS_Result(null, 101); + $this->assertEquals($expected, $this->api->removeFromGroup(['userid' => 'TargetUser', '_delete' => []])); + } + + public function testRemoveFromGroupWithNotExistingTargetGroup() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('get') + ->with('TargetGroup') + ->will($this->returnValue(null)); + + $expected = new \OC_OCS_Result(null, 102); + $this->assertEquals($expected, $this->api->removeFromGroup(['userid' => 'TargetUser', '_delete' => ['groupid' => 'TargetGroup']])); + } + + public function testRemoveFromGroupWithNotExistingTargetUser() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $targetGroup = $this->getMock('\OCP\IGroup'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('get') + ->with('TargetGroup') + ->will($this->returnValue($targetGroup)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('TargetUser') + ->will($this->returnValue(null)); + + $expected = new \OC_OCS_Result(null, 103); + $this->assertEquals($expected, $this->api->removeFromGroup(['userid' => 'TargetUser', '_delete' => ['groupid' => 'TargetGroup']])); + } + + public function testRemoveFromGroupWithoutPermission() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('unauthorizedUser')); + $targetUser = $this->getMock('\OCP\IUser'); + $targetGroup = $this->getMock('\OCP\IGroup'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('get') + ->with('TargetGroup') + ->will($this->returnValue($targetGroup)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('TargetUser') + ->will($this->returnValue($targetUser)); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') + ->disableOriginalConstructor()->getMock(); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + $this->groupManager + ->expects($this->once()) + ->method('isAdmin') + ->with('unauthorizedUser') + ->will($this->returnValue(false)); + + $expected = new \OC_OCS_Result(null, 104); + $this->assertEquals($expected, $this->api->removeFromGroup(['userid' => 'TargetUser', '_delete' => ['groupid' => 'TargetGroup']])); + } + + public function testRemoveFromGroupAsAdminFromAdmin() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('admin')); + $targetUser = $this->getMock('\OCP\IUser'); + $targetGroup = $this->getMock('\OCP\IGroup'); + $targetGroup + ->expects($this->once()) + ->method('getGID') + ->will($this->returnValue('admin')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('get') + ->with('admin') + ->will($this->returnValue($targetGroup)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('admin') + ->will($this->returnValue($targetUser)); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') + ->disableOriginalConstructor()->getMock(); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + $this->groupManager + ->expects($this->any()) + ->method('isAdmin') + ->with('admin') + ->will($this->returnValue(true)); + + $expected = new \OC_OCS_Result(null, 105, 'Cannot remove yourself from the admin group'); + $this->assertEquals($expected, $this->api->removeFromGroup(['userid' => 'admin', '_delete' => ['groupid' => 'admin']])); + } + + public function testRemoveFromGroupAsSubAdminFromSubAdmin() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('subadmin')); + $targetUser = $this->getMock('\OCP\IUser'); + $targetGroup = $this->getMock('\OCP\IGroup'); + $targetGroup + ->expects($this->any()) + ->method('getGID') + ->will($this->returnValue('subadmin')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('get') + ->with('subadmin') + ->will($this->returnValue($targetGroup)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('subadmin') + ->will($this->returnValue($targetUser)); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') + ->disableOriginalConstructor()->getMock(); + $subAdminManager + ->expects($this->once()) + ->method('isSubAdminofGroup') + ->with($loggedInUser, $targetGroup) + ->will($this->returnValue(true)); + $subAdminManager + ->expects($this->once()) + ->method('getSubAdminsGroups') + ->with($loggedInUser) + ->will($this->returnValue([$targetGroup])); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + $this->groupManager + ->expects($this->any()) + ->method('isAdmin') + ->with('subadmin') + ->will($this->returnValue(false)); + + $expected = new \OC_OCS_Result(null, 105, 'Cannot remove yourself from this group as you are a SubAdmin'); + $this->assertEquals($expected, $this->api->removeFromGroup(['userid' => 'subadmin', '_delete' => ['groupid' => 'subadmin']])); + } + + public function testRemoveFromGroupSuccessful() { + $loggedInUser = $this->getMock('\OCP\IUser'); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('admin')); + $targetUser = $this->getMock('\OCP\IUser'); + $targetGroup = $this->getMock('\OCP\IGroup'); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('get') + ->with('admin') + ->will($this->returnValue($targetGroup)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('AnotherUser') + ->will($this->returnValue($targetUser)); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') + ->disableOriginalConstructor()->getMock(); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + $this->groupManager + ->expects($this->any()) + ->method('isAdmin') + ->with('admin') + ->will($this->returnValue(true)); + $targetGroup + ->expects($this->once()) + ->method('removeUser') + ->with($targetUser); + + $expected = new \OC_OCS_Result(null, 100); + $this->assertEquals($expected, $this->api->removeFromGroup(['userid' => 'AnotherUser', '_delete' => ['groupid' => 'admin']])); + } + + public function testAddSubAdminWithNotExistingTargetUser() { + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('NotExistingUser') + ->will($this->returnValue(null)); + + $expected = new \OC_OCS_Result(null, 101, 'User does not exist'); + $this->assertEquals($expected, $this->api->addSubAdmin(['userid' => 'NotExistingUser'])); + } + + public function testAddSubAdminWithNotExistingTargetGroup() { + $_POST['groupid'] = 'NotExistingGroup'; + + $targetUser = $this->getMock('\OCP\IUser'); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('ExistingUser') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) + ->method('get') + ->with('NotExistingGroup') + ->will($this->returnValue(null)); + + $expected = new \OC_OCS_Result(null, 102, 'Group:NotExistingGroup does not exist'); + $this->assertEquals($expected, $this->api->addSubAdmin(['userid' => 'ExistingUser'])); + } + + public function testAddSubAdminToAdminGroup() { + $_POST['groupid'] = 'ADmiN'; + + $targetUser = $this->getMock('\OCP\IUser'); + $targetGroup = $this->getMock('\OCP\IGroup'); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('ExistingUser') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) + ->method('get') + ->with('ADmiN') + ->will($this->returnValue($targetGroup)); + + $expected = new \OC_OCS_Result(null, 103, 'Cannot create subadmins for admin group'); + $this->assertEquals($expected, $this->api->addSubAdmin(['userid' => 'ExistingUser'])); + } + + public function testAddSubAdminTwice() { + $_POST['groupid'] = 'TargetGroup'; + + $targetUser = $this->getMock('\OCP\IUser'); + $targetGroup = $this->getMock('\OCP\IGroup'); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('ExistingUser') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) + ->method('get') + ->with('TargetGroup') + ->will($this->returnValue($targetGroup)); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') + ->disableOriginalConstructor()->getMock(); + $subAdminManager + ->expects($this->once()) + ->method('isSubAdminOfGroup') + ->with($targetUser, $targetGroup) + ->will($this->returnValue(true)); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + + $expected = new \OC_OCS_Result(null, 100); + $this->assertEquals($expected, $this->api->addSubAdmin(['userid' => 'ExistingUser'])); + } + + public function testAddSubAdminSuccessful() { + $_POST['groupid'] = 'TargetGroup'; + + $targetUser = $this->getMock('\OCP\IUser'); + $targetGroup = $this->getMock('\OCP\IGroup'); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('ExistingUser') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) + ->method('get') + ->with('TargetGroup') + ->will($this->returnValue($targetGroup)); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') + ->disableOriginalConstructor()->getMock(); + $subAdminManager + ->expects($this->once()) + ->method('isSubAdminOfGroup') + ->with($targetUser, $targetGroup) + ->will($this->returnValue(false)); + $subAdminManager + ->expects($this->once()) + ->method('createSubAdmin') + ->with($targetUser, $targetGroup) + ->will($this->returnValue(true)); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + + $expected = new \OC_OCS_Result(null, 100); + $this->assertEquals($expected, $this->api->addSubAdmin(['userid' => 'ExistingUser'])); + } + + public function testAddSubAdminUnsuccessful() { + $_POST['groupid'] = 'TargetGroup'; + + $targetUser = $this->getMock('\OCP\IUser'); + $targetGroup = $this->getMock('\OCP\IGroup'); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('ExistingUser') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) + ->method('get') + ->with('TargetGroup') + ->will($this->returnValue($targetGroup)); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') + ->disableOriginalConstructor()->getMock(); + $subAdminManager + ->expects($this->once()) + ->method('isSubAdminOfGroup') + ->with($targetUser, $targetGroup) + ->will($this->returnValue(false)); + $subAdminManager + ->expects($this->once()) + ->method('createSubAdmin') + ->with($targetUser, $targetGroup) + ->will($this->returnValue(false)); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + + $expected = new \OC_OCS_Result(null, 103, 'Unknown error occurred'); + $this->assertEquals($expected, $this->api->addSubAdmin(['userid' => 'ExistingUser'])); + } + + public function testRemoveSubAdminNotExistingTargetUser() { + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('NotExistingUser') + ->will($this->returnValue(null)); + + $expected = new \OC_OCS_Result(null, 101, 'User does not exist'); + $this->assertEquals($expected, $this->api->removeSubAdmin(['userid' => 'NotExistingUser', '_delete' => ['groupid' => 'GroupToDeleteFrom']])); + } + + public function testRemoveSubAdminNotExistingTargetGroup() { + $targetUser = $this->getMock('\OCP\IUser'); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('ExistingUser') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) + ->method('get') + ->with('GroupToDeleteFrom') + ->will($this->returnValue(null)); + + $expected = new \OC_OCS_Result(null, 101, 'Group does not exist'); + $this->assertEquals($expected, $this->api->removeSubAdmin(['userid' => 'ExistingUser', '_delete' => ['groupid' => 'GroupToDeleteFrom']])); + } + + public function testRemoveSubAdminFromNotASubadmin() { + $targetUser = $this->getMock('\OCP\IUser'); + $targetGroup = $this->getMock('\OCP\IGroup'); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('ExistingUser') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) + ->method('get') + ->with('GroupToDeleteFrom') + ->will($this->returnValue($targetGroup)); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') + ->disableOriginalConstructor()->getMock(); + $subAdminManager + ->expects($this->once()) + ->method('isSubAdminOfGroup') + ->with($targetUser, $targetGroup) + ->will($this->returnValue(false)); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + + $expected = new \OC_OCS_Result(null, 102, 'User is not a subadmin of this group'); + $this->assertEquals($expected, $this->api->removeSubAdmin(['userid' => 'ExistingUser', '_delete' => ['groupid' => 'GroupToDeleteFrom']])); + } + + public function testRemoveSubAdminSuccessful() { + $targetUser = $this->getMock('\OCP\IUser'); + $targetGroup = $this->getMock('\OCP\IGroup'); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('ExistingUser') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) + ->method('get') + ->with('GroupToDeleteFrom') + ->will($this->returnValue($targetGroup)); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') + ->disableOriginalConstructor()->getMock(); + $subAdminManager + ->expects($this->once()) + ->method('isSubAdminOfGroup') + ->with($targetUser, $targetGroup) + ->will($this->returnValue(true)); + $subAdminManager + ->expects($this->once()) + ->method('deleteSubAdmin') + ->with($targetUser, $targetGroup) + ->will($this->returnValue(true)); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + + $expected = new \OC_OCS_Result(null, 100); + $this->assertEquals($expected, $this->api->removeSubAdmin(['userid' => 'ExistingUser', '_delete' => ['groupid' => 'GroupToDeleteFrom']])); + } + + public function testRemoveSubAdminUnsuccessful() { + $targetUser = $this->getMock('\OCP\IUser'); + $targetGroup = $this->getMock('\OCP\IGroup'); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('ExistingUser') + ->will($this->returnValue($targetUser)); + $this->groupManager + ->expects($this->once()) + ->method('get') + ->with('GroupToDeleteFrom') + ->will($this->returnValue($targetGroup)); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') + ->disableOriginalConstructor()->getMock(); + $subAdminManager + ->expects($this->once()) + ->method('isSubAdminOfGroup') + ->with($targetUser, $targetGroup) + ->will($this->returnValue(true)); + $subAdminManager + ->expects($this->once()) + ->method('deleteSubAdmin') + ->with($targetUser, $targetGroup) + ->will($this->returnValue(false)); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + + $expected = new \OC_OCS_Result(null, 103, 'Unknown error occurred'); + $this->assertEquals($expected, $this->api->removeSubAdmin(['userid' => 'ExistingUser', '_delete' => ['groupid' => 'GroupToDeleteFrom']])); + } + + public function testGetUserSubAdminGroupsNotExistingTargetUser() { + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('RequestedUser') + ->will($this->returnValue(null)); + + $expected = new \OC_OCS_Result(null, 101, 'User does not exist'); + $this->assertEquals($expected, $this->api->getUserSubAdminGroups(['userid' => 'RequestedUser'])); + } + + public function testGetUserSubAdminGroupsWithGroups() { + $targetUser = $this->getMock('\OCP\IUser'); + $targetGroup = $this->getMock('\OCP\IGroup'); + $targetGroup + ->expects($this->once()) + ->method('getGID') + ->will($this->returnValue('TargetGroup')); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('RequestedUser') + ->will($this->returnValue($targetUser)); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') + ->disableOriginalConstructor()->getMock(); + $subAdminManager + ->expects($this->once()) + ->method('getSubAdminsGroups') + ->with($targetUser) + ->will($this->returnValue([$targetGroup])); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + + $expected = new \OC_OCS_Result(['TargetGroup'], 100); + $this->assertEquals($expected, $this->api->getUserSubAdminGroups(['userid' => 'RequestedUser'])); + } + + public function testGetUserSubAdminGroupsWithoutGroups() { + $targetUser = $this->getMock('\OCP\IUser'); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('RequestedUser') + ->will($this->returnValue($targetUser)); + $subAdminManager = $this->getMockBuilder('\OC\Subadmin') + ->disableOriginalConstructor()->getMock(); + $subAdminManager + ->expects($this->once()) + ->method('getSubAdminsGroups') + ->with($targetUser) + ->will($this->returnValue([])); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + + $expected = new \OC_OCS_Result(null, 102, 'Unknown error occurred'); + $this->assertEquals($expected, $this->api->getUserSubAdminGroups(['userid' => 'RequestedUser'])); } } diff --git a/apps/user_ldap/css/settings.css b/apps/user_ldap/css/settings.css index 8648246247d..db24588f761 100644 --- a/apps/user_ldap/css/settings.css +++ b/apps/user_ldap/css/settings.css @@ -56,7 +56,7 @@ display: table; } -#ldapWizard1 .hostPortCombinator div span { +#ldapWizard1 .hostPortCombinatorSpan { width: 14.5%; display: inline-block; text-align: right; @@ -114,13 +114,13 @@ width: auto; } -.ldapManyGroupsSupport span { +.ldapManyGroupsSupport .buttonSpan { display: inline-block; vertical-align: top; height: 150px; } -.ldapManyGroupsSupport span button { +.ldapManyGroupsSupport .buttonSpan button { margin-top: 35px; } diff --git a/apps/user_ldap/group_ldap.php b/apps/user_ldap/group_ldap.php index 4fd029c74da..7c06e24293e 100644 --- a/apps/user_ldap/group_ldap.php +++ b/apps/user_ldap/group_ldap.php @@ -6,6 +6,7 @@ * @author Bart Visscher <bartv@thisnet.nl> * @author Christopher Schäpers <kondou@ts.unde.re> * @author Frédéric Fortier <frederic.fortier@oronospolytechnique.com> + * @author Lukas Reschke <lukas@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> * @author Nicolas Grekas <nicolas.grekas@gmail.com> * @author Robin McCorkell <rmccorkell@karoshi.org.uk> @@ -552,6 +553,7 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface { $groupUsers = array(); $isMemberUid = (strtolower($this->access->connection->ldapGroupMemberAssocAttr) === 'memberuid'); + $attrs = $this->access->userManager->getAttributes(true); foreach($members as $member) { if($isMemberUid) { //we got uids, need to get their DNs to 'translate' them to user names @@ -559,11 +561,11 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface { str_replace('%uid', $member, $this->access->connection->ldapLoginFilter), $this->access->getFilterPartForUserSearch($search) )); - $ldap_users = $this->access->fetchListOfUsers($filter, 'dn'); + $ldap_users = $this->access->fetchListOfUsers($filter, $attrs, 1); if(count($ldap_users) < 1) { continue; } - $groupUsers[] = $this->access->dn2username($ldap_users[0]); + $groupUsers[] = $this->access->dn2username($ldap_users[0]['dn'][0]); } else { //we got DNs, check if we need to filter by search or we can give back all of them if(!empty($search)) { diff --git a/apps/user_ldap/js/wizard/view.js b/apps/user_ldap/js/wizard/view.js index 7dedfab75f0..39133554121 100644 --- a/apps/user_ldap/js/wizard/view.js +++ b/apps/user_ldap/js/wizard/view.js @@ -349,9 +349,9 @@ OCA = OCA || {}; render: function () { $('#ldapAdvancedAccordion').accordion({ heightStyle: 'content', animate: 'easeInOutCirc'}); this.$settings.tabs({}); - $('.ldap_submit').button(); - $('.ldap_action_test_connection').button(); + $('#ldapSettings button:not(.icon-default-style):not(.ui-multiselect)').button(); $('#ldapSettings').tabs({ beforeActivate: this.onTabChange }); + $('#ldapSettings :input').tooltip({placement: "right", container: "body", trigger: "hover"}); this.initControls(); this.disableTabs(); 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'); } diff --git a/apps/user_ldap/js/wizard/wizardTabGeneric.js b/apps/user_ldap/js/wizard/wizardTabGeneric.js index b755f3ca060..60e7cd2ad9e 100644 --- a/apps/user_ldap/js/wizard/wizardTabGeneric.js +++ b/apps/user_ldap/js/wizard/wizardTabGeneric.js @@ -22,6 +22,12 @@ OCA = OCA || {}; */ multiSelectPluginClass: 'multiSelectPlugin', + /** + * @property {string} - class that identifies a multiselect-plugin + * control. + */ + bjQuiButtonClass: 'ui-button', + /** @inheritdoc */ init: function(tabIndex, tabID) { this.tabIndex = tabIndex; @@ -233,7 +239,10 @@ OCA = OCA || {}; if($element.hasClass(this.multiSelectPluginClass) && hasOptions) { $element.multiselect("enable"); - } else if(!isMS || (isMS && hasOptions)) { + } else if ($element.hasClass(this.bjQuiButtonClass)) { + $element.button("enable"); + } + else if(!isMS || (isMS && hasOptions)) { $element.prop('disabled', false); } }, @@ -246,6 +255,8 @@ OCA = OCA || {}; disableElement: function($element) { if($element.hasClass(this.multiSelectPluginClass)) { $element.multiselect("disable"); + } else if ($element.hasClass(this.bjQuiButtonClass)) { + $element.button("disable"); } else { $element.prop('disabled', 'disabled'); } diff --git a/apps/user_ldap/js/wizard/wizardTabLoginFilter.js b/apps/user_ldap/js/wizard/wizardTabLoginFilter.js index 0316db5b61c..691ddb5ac9a 100644 --- a/apps/user_ldap/js/wizard/wizardTabLoginFilter.js +++ b/apps/user_ldap/js/wizard/wizardTabLoginFilter.js @@ -241,7 +241,11 @@ OCA = OCA || {}; onTestLoginnameChange: function() { var loginName = this.managedItems.ldap_test_loginname.$element.val(); var beDisabled = !_.isString(loginName) || !loginName.trim(); - this.managedItems.ldap_test_loginname.$relatedElements.prop('disabled', beDisabled); + if(beDisabled) { + this.disableElement(this.managedItems.ldap_test_loginname.$relatedElements); + } else { + this.enableElement(this.managedItems.ldap_test_loginname.$relatedElements); + } } }); diff --git a/apps/user_ldap/l10n/cs_CZ.js b/apps/user_ldap/l10n/cs_CZ.js index 77fef537f0a..e78755719b7 100644 --- a/apps/user_ldap/l10n/cs_CZ.js +++ b/apps/user_ldap/l10n/cs_CZ.js @@ -24,7 +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ářů.", + "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..37e56cda1a7 100644 --- a/apps/user_ldap/l10n/cs_CZ.json +++ b/apps/user_ldap/l10n/cs_CZ.json @@ -22,7 +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ářů.", + "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 375b78b4526..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?", @@ -110,9 +109,9 @@ OC.L10N.register( "Connection Settings" : "Verbindungseinstellungen", "Configuration Active" : "Konfiguration aktiv", "When unchecked, this configuration will be skipped." : "Konfiguration wird übersprungen wenn deaktiviert", - "Backup (Replica) Host" : "Backup von Host (Kopie) anlegen", - "Give an optional backup host. It must be a replica of the main LDAP/AD server." : "Gib einen optionalen Backup Host an. Es muss sich um eine Kopie des Haupt LDAP/AD Servers handeln.", - "Backup (Replica) Port" : "Backup Port", + "Backup (Replica) Host" : "Backup-Host (Kopie)", + "Give an optional backup host. It must be a replica of the main LDAP/AD server." : "Gib einen optionalen Backup-Host an. Es muss sich um eine Kopie des Haupt-LDAP/AD-Servers handeln.", + "Backup (Replica) Port" : "Port des Backup-Hosts (Kopie)", "Disable Main Server" : "Hauptserver deaktivieren", "Only connect to the replica server." : "Nur zum Replikat-Server verbinden.", "Turn off SSL certificate validation." : "Schalte die SSL-Zertifikatsprüfung aus.", diff --git a/apps/user_ldap/l10n/de.json b/apps/user_ldap/l10n/de.json index 17c0bf02c2d..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?", @@ -108,9 +107,9 @@ "Connection Settings" : "Verbindungseinstellungen", "Configuration Active" : "Konfiguration aktiv", "When unchecked, this configuration will be skipped." : "Konfiguration wird übersprungen wenn deaktiviert", - "Backup (Replica) Host" : "Backup von Host (Kopie) anlegen", - "Give an optional backup host. It must be a replica of the main LDAP/AD server." : "Gib einen optionalen Backup Host an. Es muss sich um eine Kopie des Haupt LDAP/AD Servers handeln.", - "Backup (Replica) Port" : "Backup Port", + "Backup (Replica) Host" : "Backup-Host (Kopie)", + "Give an optional backup host. It must be a replica of the main LDAP/AD server." : "Gib einen optionalen Backup-Host an. Es muss sich um eine Kopie des Haupt-LDAP/AD-Servers handeln.", + "Backup (Replica) Port" : "Port des Backup-Hosts (Kopie)", "Disable Main Server" : "Hauptserver deaktivieren", "Only connect to the replica server." : "Nur zum Replikat-Server verbinden.", "Turn off SSL certificate validation." : "Schalte die SSL-Zertifikatsprüfung aus.", diff --git a/apps/user_ldap/l10n/de_DE.js b/apps/user_ldap/l10n/de_DE.js index 49fcd8c8c69..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?", @@ -110,9 +109,9 @@ OC.L10N.register( "Connection Settings" : "Verbindungseinstellungen", "Configuration Active" : "Konfiguration aktiv", "When unchecked, this configuration will be skipped." : "Wenn nicht angehakt, wird diese Konfiguration übersprungen.", - "Backup (Replica) Host" : "Backup von Host (Kopie) anlegen", - "Give an optional backup host. It must be a replica of the main LDAP/AD server." : "Geben Sie einen optionalen Backup Host an. Es muss sich um eine Kopie des Haupt LDAP/AD Servers handeln.", - "Backup (Replica) Port" : "Backup Port", + "Backup (Replica) Host" : "Backup-Host (Kopie)", + "Give an optional backup host. It must be a replica of the main LDAP/AD server." : "Geben Sie einen optionalen Backup-Host an. Es muss sich um eine Kopie des Haupt-LDAP/AD-Servers handeln.", + "Backup (Replica) Port" : "Port des Backup-Hosts (Kopie)", "Disable Main Server" : "Hauptserver deaktivieren", "Only connect to the replica server." : "Nur zum Replikat-Server verbinden.", "Turn off SSL certificate validation." : "Schalten Sie die SSL-Zertifikatsprüfung aus.", diff --git a/apps/user_ldap/l10n/de_DE.json b/apps/user_ldap/l10n/de_DE.json index 61792d3704e..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?", @@ -108,9 +107,9 @@ "Connection Settings" : "Verbindungseinstellungen", "Configuration Active" : "Konfiguration aktiv", "When unchecked, this configuration will be skipped." : "Wenn nicht angehakt, wird diese Konfiguration übersprungen.", - "Backup (Replica) Host" : "Backup von Host (Kopie) anlegen", - "Give an optional backup host. It must be a replica of the main LDAP/AD server." : "Geben Sie einen optionalen Backup Host an. Es muss sich um eine Kopie des Haupt LDAP/AD Servers handeln.", - "Backup (Replica) Port" : "Backup Port", + "Backup (Replica) Host" : "Backup-Host (Kopie)", + "Give an optional backup host. It must be a replica of the main LDAP/AD server." : "Geben Sie einen optionalen Backup-Host an. Es muss sich um eine Kopie des Haupt-LDAP/AD-Servers handeln.", + "Backup (Replica) Port" : "Port des Backup-Hosts (Kopie)", "Disable Main Server" : "Hauptserver deaktivieren", "Only connect to the replica server." : "Nur zum Replikat-Server verbinden.", "Turn off SSL certificate validation." : "Schalten Sie die SSL-Zertifikatsprüfung aus.", diff --git a/apps/user_ldap/l10n/el.js b/apps/user_ldap/l10n/el.js index fc9d96aa61a..7ea629e673d 100644 --- a/apps/user_ldap/l10n/el.js +++ b/apps/user_ldap/l10n/el.js @@ -24,7 +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 εγγραφές καταλόγων διαθέσιμες.", + "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..338b0b8bad9 100644 --- a/apps/user_ldap/l10n/el.json +++ b/apps/user_ldap/l10n/el.json @@ -22,7 +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 εγγραφές καταλόγων διαθέσιμες.", + "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/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/fr.js b/apps/user_ldap/l10n/fr.js index 3bf26f0e3ea..a013589cff2 100644 --- a/apps/user_ldap/l10n/fr.js +++ b/apps/user_ldap/l10n/fr.js @@ -24,7 +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 1000 entrées de répertoire disponibles.", + "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 ?", @@ -39,7 +39,7 @@ OC.L10N.register( "Select attributes" : "Sélectionner les attributs", "User not found. Please check your login attributes and username. Effective filter (to copy-and-paste for command line validation): <br/>" : "Utilisateur introuvable. Veuillez vérifier les attributs de login et le nom d'utilisateur. Filtre effectif (à copier-coller pour valider en ligne de commande):<br/>", "User found and settings verified." : "Utilisateur trouvé et paramètres vérifiés.", - "Settings verified, but one user found. Only the first will be able to login. Consider a more narrow filter." : "Paramètres vérifiés, mais seul le premier utilisateur pourra se connecter. Utilisez plutôt un filtre moins restrictif.", + "Settings verified, but one user found. Only the first will be able to login. Consider a more narrow filter." : "Settings verified, but one user found. Only the first will be able to login. Consider a more narrow filter.", "An unspecified error occurred. Please check the settings and the log." : "Une erreur inconnue s'est produite. Veuillez vérifier les paramètres et le log.", "The search filter is invalid, probably due to syntax issues like uneven number of opened and closed brackets. Please revise." : "Le filtre de recherche n'est pas valide, probablement à cause de problèmes de syntaxe tels que des parenthèses manquantes. Veuillez le corriger.", "A connection error to LDAP / AD occurred, please check host, port and credentials." : "Une erreur s'est produite lors de la connexion au LDAP / AD. Veuillez vérifier l'hôte, le port et les informations d'identification.", diff --git a/apps/user_ldap/l10n/fr.json b/apps/user_ldap/l10n/fr.json index 87cf780e825..0b6c076f0d3 100644 --- a/apps/user_ldap/l10n/fr.json +++ b/apps/user_ldap/l10n/fr.json @@ -22,7 +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 1000 entrées de répertoire disponibles.", + "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 ?", @@ -37,7 +37,7 @@ "Select attributes" : "Sélectionner les attributs", "User not found. Please check your login attributes and username. Effective filter (to copy-and-paste for command line validation): <br/>" : "Utilisateur introuvable. Veuillez vérifier les attributs de login et le nom d'utilisateur. Filtre effectif (à copier-coller pour valider en ligne de commande):<br/>", "User found and settings verified." : "Utilisateur trouvé et paramètres vérifiés.", - "Settings verified, but one user found. Only the first will be able to login. Consider a more narrow filter." : "Paramètres vérifiés, mais seul le premier utilisateur pourra se connecter. Utilisez plutôt un filtre moins restrictif.", + "Settings verified, but one user found. Only the first will be able to login. Consider a more narrow filter." : "Settings verified, but one user found. Only the first will be able to login. Consider a more narrow filter.", "An unspecified error occurred. Please check the settings and the log." : "Une erreur inconnue s'est produite. Veuillez vérifier les paramètres et le log.", "The search filter is invalid, probably due to syntax issues like uneven number of opened and closed brackets. Please revise." : "Le filtre de recherche n'est pas valide, probablement à cause de problèmes de syntaxe tels que des parenthèses manquantes. Veuillez le corriger.", "A connection error to LDAP / AD occurred, please check host, port and credentials." : "Une erreur s'est produite lors de la connexion au LDAP / AD. Veuillez vérifier l'hôte, le port et les informations d'identification.", 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/hu_HU.js b/apps/user_ldap/l10n/hu_HU.js index 25035fb32cf..36fdcad3806 100644 --- a/apps/user_ldap/l10n/hu_HU.js +++ b/apps/user_ldap/l10n/hu_HU.js @@ -64,7 +64,7 @@ OC.L10N.register( "Turn off SSL certificate validation." : "Ne ellenőrizzük az SSL-tanúsítvány érvényességét", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." : "Használata nem javasolt (kivéve tesztelési céllal). Ha a kapcsolat csak ezzel a beállítással működik, akkor importálja az LDAP-kiszolgáló SSL tanúsítványát a(z) %s kiszolgálóra!", "Cache Time-To-Live" : "A gyorsítótár tárolási időtartama", - "in seconds. A change empties the cache." : "másodpercben. A változtatás törli a cache tartalmát.", + "in seconds. A change empties the cache." : "másodpercen belül. A változtatás törli a gyorsítótár tartalmát.", "Directory Settings" : "Címtár beállítások", "User Display Name Field" : "A felhasználónév mezője", "The LDAP attribute to use to generate the user's display name." : "Ebből az LDAP attribútumból képződik a felhasználó megjelenítendő neve.", diff --git a/apps/user_ldap/l10n/hu_HU.json b/apps/user_ldap/l10n/hu_HU.json index 0778e627e2c..14f16217ee3 100644 --- a/apps/user_ldap/l10n/hu_HU.json +++ b/apps/user_ldap/l10n/hu_HU.json @@ -62,7 +62,7 @@ "Turn off SSL certificate validation." : "Ne ellenőrizzük az SSL-tanúsítvány érvényességét", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." : "Használata nem javasolt (kivéve tesztelési céllal). Ha a kapcsolat csak ezzel a beállítással működik, akkor importálja az LDAP-kiszolgáló SSL tanúsítványát a(z) %s kiszolgálóra!", "Cache Time-To-Live" : "A gyorsítótár tárolási időtartama", - "in seconds. A change empties the cache." : "másodpercben. A változtatás törli a cache tartalmát.", + "in seconds. A change empties the cache." : "másodpercen belül. A változtatás törli a gyorsítótár tartalmát.", "Directory Settings" : "Címtár beállítások", "User Display Name Field" : "A felhasználónév mezője", "The LDAP attribute to use to generate the user's display name." : "Ebből az LDAP attribútumból képződik a felhasználó megjelenítendő neve.", 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..8bb42e1a72a 100644 --- a/apps/user_ldap/l10n/it.js +++ b/apps/user_ldap/l10n/it.js @@ -24,7 +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.", + "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..73234261016 100644 --- a/apps/user_ldap/l10n/it.json +++ b/apps/user_ldap/l10n/it.json @@ -22,7 +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.", + "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 344896e480d..e138c46e08e 100644 --- a/apps/user_ldap/l10n/ja.js +++ b/apps/user_ldap/l10n/ja.js @@ -24,7 +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." : "1000 以上のディレクトリエントリが利用可能です。", + "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?" : "現在のサーバー設定を本当に削除してもよろしいですか?", @@ -98,7 +98,7 @@ OC.L10N.register( "Limit %s access to users meeting these criteria:" : "以下のフィルターに適合するユーザーのみ %s へアクセスを許可:", "The most common object classes for users are organizationalPerson, person, user, and inetOrgPerson. If you are not sure which object class to select, please consult your directory admin." : "ユーザーの最も一般的なオブジェクトクラスは、organizationalPerson, person, user と inetOrgPerson です。もし、どのオブジェクトを選択すれば良いか分からない場合は、ディレクトリ管理者に相談してください。", "The filter specifies which LDAP users shall have access to the %s instance." : "フィルターは、どのLDAPユーザーが %s にアクセスするかを指定します。", - "Verify settings and count users" : "設定を検証し、ユーザを数える", + "Verify settings and count users" : "設定を検証し、ユーザーを数える", "Saving" : "保存中", "Back" : "戻る", "Continue" : "続ける", diff --git a/apps/user_ldap/l10n/ja.json b/apps/user_ldap/l10n/ja.json index 74550f07e2a..ef69c48adcc 100644 --- a/apps/user_ldap/l10n/ja.json +++ b/apps/user_ldap/l10n/ja.json @@ -22,7 +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." : "1000 以上のディレクトリエントリが利用可能です。", + "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?" : "現在のサーバー設定を本当に削除してもよろしいですか?", @@ -96,7 +96,7 @@ "Limit %s access to users meeting these criteria:" : "以下のフィルターに適合するユーザーのみ %s へアクセスを許可:", "The most common object classes for users are organizationalPerson, person, user, and inetOrgPerson. If you are not sure which object class to select, please consult your directory admin." : "ユーザーの最も一般的なオブジェクトクラスは、organizationalPerson, person, user と inetOrgPerson です。もし、どのオブジェクトを選択すれば良いか分からない場合は、ディレクトリ管理者に相談してください。", "The filter specifies which LDAP users shall have access to the %s instance." : "フィルターは、どのLDAPユーザーが %s にアクセスするかを指定します。", - "Verify settings and count users" : "設定を検証し、ユーザを数える", + "Verify settings and count users" : "設定を検証し、ユーザーを数える", "Saving" : "保存中", "Back" : "戻る", "Continue" : "続ける", 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..27f6dd9ffc7 100644 --- a/apps/user_ldap/l10n/nl.js +++ b/apps/user_ldap/l10n/nl.js @@ -24,7 +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.", + "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..c98d7aa64dc 100644 --- a/apps/user_ldap/l10n/nl.json +++ b/apps/user_ldap/l10n/nl.json @@ -22,7 +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.", + "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..e027c930ceb 100644 --- a/apps/user_ldap/l10n/pt_BR.js +++ b/apps/user_ldap/l10n/pt_BR.js @@ -24,7 +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 de diretórios disponíveis.", + "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 752fd653884..8251fa082a6 100644 --- a/apps/user_ldap/l10n/pt_BR.json +++ b/apps/user_ldap/l10n/pt_BR.json @@ -22,7 +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 de diretórios disponíveis.", + "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_PT.js b/apps/user_ldap/l10n/pt_PT.js index 459fe817603..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?", @@ -38,6 +37,8 @@ OC.L10N.register( "Mode switch" : "Trocar de modo", "Select attributes" : "Selecionar atributos", "User found and settings verified." : "Utilizador encontrado e as definilções verificadas", + "An unspecified error occurred. Please check the settings and the log." : "ocorreu um erro não especificado. Por favor, verifique as configurações e o registo.", + "Please provide a login name to test against" : "Por favor, indique um nome de sessão para testar", "_%s group found_::_%s groups found_" : ["%s grupo encontrado","%s grupos encontrados"], "_%s user found_::_%s users found_" : ["%s utilizador encontrado","%s utilizadores encontrados"], "Could not detect user display name attribute. Please specify it yourself in advanced ldap settings." : "Não foi possível detetar o atributo do nome do utilizador. Por favor especifique-o nas configurações ldap avançadas.", @@ -45,20 +46,26 @@ OC.L10N.register( "Invalid Host" : "Hospedeiro Inválido", "Server" : "Servidor", "Users" : "Utilizadores", + "Login Attributes" : "Atributos de Sessão", "Groups" : "Grupos", "Test Configuration" : "Testar a configuração", "Help" : "Ajuda", "Groups meeting these criteria are available in %s:" : "Grupos que satisfazerem estes critérios estão disponíveis em %s:", + "Only these object classes:" : "Apenas estas classes de objetos:", + "Only from these groups:" : "Apenas destes grupos:", + "Search groups" : "Procurar grupos", "Available groups" : "Grupos disponiveis", "Selected groups" : "Grupos seleccionados", "LDAP Filter:" : "Filtro LDAP:", "The filter specifies which LDAP groups shall have access to the %s instance." : "O filtro especifica quais grupos LDAP devem ter acesso à instância %s.", "LDAP / AD Username:" : "Nome de Utilizador LDAP / AD:", + "LDAP / AD Email Address:" : "Endereço de Correio Eletrónico LDPA / AD", "Other Attributes:" : "Outros Atributos:", "Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action. Example: \"uid=%%uid\"" : "Define o filtro a aplicar, quando se tenta uma sessão. %%uid substitui o nome de utilizador na ação de início de sessão. Exemplo: \"uid=%%uid\"", "Verify settings" : "Verificar definições", "1. Server" : "1. Servidor", "%s. Server:" : "%s. Servvidor", + "Add a new and blank configuration" : "Adicione uma nova configuração em branco", "Delete the current configuration" : "Apagar a configuração actual", "Host" : "Anfitrião", "You can omit the protocol, except you require SSL. Then start with ldaps://" : "Pode omitir o protocolo, excepto se necessitar de SSL. Neste caso, comece com ldaps://", diff --git a/apps/user_ldap/l10n/pt_PT.json b/apps/user_ldap/l10n/pt_PT.json index c7358f61bd5..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?", @@ -36,6 +35,8 @@ "Mode switch" : "Trocar de modo", "Select attributes" : "Selecionar atributos", "User found and settings verified." : "Utilizador encontrado e as definilções verificadas", + "An unspecified error occurred. Please check the settings and the log." : "ocorreu um erro não especificado. Por favor, verifique as configurações e o registo.", + "Please provide a login name to test against" : "Por favor, indique um nome de sessão para testar", "_%s group found_::_%s groups found_" : ["%s grupo encontrado","%s grupos encontrados"], "_%s user found_::_%s users found_" : ["%s utilizador encontrado","%s utilizadores encontrados"], "Could not detect user display name attribute. Please specify it yourself in advanced ldap settings." : "Não foi possível detetar o atributo do nome do utilizador. Por favor especifique-o nas configurações ldap avançadas.", @@ -43,20 +44,26 @@ "Invalid Host" : "Hospedeiro Inválido", "Server" : "Servidor", "Users" : "Utilizadores", + "Login Attributes" : "Atributos de Sessão", "Groups" : "Grupos", "Test Configuration" : "Testar a configuração", "Help" : "Ajuda", "Groups meeting these criteria are available in %s:" : "Grupos que satisfazerem estes critérios estão disponíveis em %s:", + "Only these object classes:" : "Apenas estas classes de objetos:", + "Only from these groups:" : "Apenas destes grupos:", + "Search groups" : "Procurar grupos", "Available groups" : "Grupos disponiveis", "Selected groups" : "Grupos seleccionados", "LDAP Filter:" : "Filtro LDAP:", "The filter specifies which LDAP groups shall have access to the %s instance." : "O filtro especifica quais grupos LDAP devem ter acesso à instância %s.", "LDAP / AD Username:" : "Nome de Utilizador LDAP / AD:", + "LDAP / AD Email Address:" : "Endereço de Correio Eletrónico LDPA / AD", "Other Attributes:" : "Outros Atributos:", "Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action. Example: \"uid=%%uid\"" : "Define o filtro a aplicar, quando se tenta uma sessão. %%uid substitui o nome de utilizador na ação de início de sessão. Exemplo: \"uid=%%uid\"", "Verify settings" : "Verificar definições", "1. Server" : "1. Servidor", "%s. Server:" : "%s. Servvidor", + "Add a new and blank configuration" : "Adicione uma nova configuração em branco", "Delete the current configuration" : "Apagar a configuração actual", "Host" : "Anfitrião", "You can omit the protocol, except you require SSL. Then start with ldaps://" : "Pode omitir o protocolo, excepto se necessitar de SSL. Neste caso, comece com ldaps://", 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 bf5c3a13d46..4f0d1d3697c 100644 --- a/apps/user_ldap/l10n/sq.js +++ b/apps/user_ldap/l10n/sq.js @@ -10,6 +10,7 @@ OC.L10N.register( "No action specified" : "S’është treguar veprim", "No configuration specified" : "S’u dha formësim", "No data specified" : "S’u treguan të dhëna", + " Could not set configuration %s" : "S’vuri dot në punë formësimin %s", "Action does not exist" : "Veprimi s’ekziston", "The Base DN appears to be wrong" : "DN-ja Bazë duket se është e gabuar", "Configuration incorrect" : "Formësim i pasaktë", @@ -23,7 +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ë tepër se 1.000 zëra drejtorie gati.", + "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?", @@ -65,6 +66,7 @@ OC.L10N.register( "Edit LDAP Query" : "Përpunoni Kërkesë LDAP", "LDAP Filter:" : "Filtër LDAP:", "The filter specifies which LDAP groups shall have access to the %s instance." : "Filtri përcakton se cilët grupe LDAP do të kenë hyrje te instanca %s.", + "Verify settings and count groups" : "Verifiko rregullimet dhe numëro grupet", "When logging in, %s will find the user based on the following attributes:" : "Kur hyhet, %s do ta gjejë përdoruesin duke u bazuar në atributet vijues:", "LDAP / AD Username:" : "Emër përdoruesi LDAP / AD:", "Allows login against the LDAP / AD username, which is either uid or samaccountname and will be detected." : "Lejon hyrje kundrejt emrin të përdoruesit LDAP / AD, që është ose uid, ose samaccountname, dhe do të zbulohet.", @@ -96,6 +98,7 @@ OC.L10N.register( "Limit %s access to users meeting these criteria:" : "Kufizo hyrje %s vetëm për përdorues që plotësojnë këtë kusht:", "The most common object classes for users are organizationalPerson, person, user, and inetOrgPerson. If you are not sure which object class to select, please consult your directory admin." : "Klasat më të rëndomta objektesht për përdoruesit janë organizationalPerson, person, user, dhe inetOrgPerson. Nëse s’jeni i sigurt cilën klasë objekti të përzgjidhniI, ju lutemi, lidhuni me përgjegjësin e drejtorisë suaj.", "The filter specifies which LDAP users shall have access to the %s instance." : "Filtri përcakton se cilët përdorues LDAP do të kenë hyrje te instanca %s.", + "Verify settings and count users" : "Verifiko rregullimet dhe numëro përdoruesit", "Saving" : "Po ruhet", "Back" : "Mbrapsht", "Continue" : "Vazhdo", diff --git a/apps/user_ldap/l10n/sq.json b/apps/user_ldap/l10n/sq.json index 05ce68fa5b2..6045b61f57d 100644 --- a/apps/user_ldap/l10n/sq.json +++ b/apps/user_ldap/l10n/sq.json @@ -8,6 +8,7 @@ "No action specified" : "S’është treguar veprim", "No configuration specified" : "S’u dha formësim", "No data specified" : "S’u treguan të dhëna", + " Could not set configuration %s" : "S’vuri dot në punë formësimin %s", "Action does not exist" : "Veprimi s’ekziston", "The Base DN appears to be wrong" : "DN-ja Bazë duket se është e gabuar", "Configuration incorrect" : "Formësim i pasaktë", @@ -21,7 +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ë tepër se 1.000 zëra drejtorie gati.", + "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?", @@ -63,6 +64,7 @@ "Edit LDAP Query" : "Përpunoni Kërkesë LDAP", "LDAP Filter:" : "Filtër LDAP:", "The filter specifies which LDAP groups shall have access to the %s instance." : "Filtri përcakton se cilët grupe LDAP do të kenë hyrje te instanca %s.", + "Verify settings and count groups" : "Verifiko rregullimet dhe numëro grupet", "When logging in, %s will find the user based on the following attributes:" : "Kur hyhet, %s do ta gjejë përdoruesin duke u bazuar në atributet vijues:", "LDAP / AD Username:" : "Emër përdoruesi LDAP / AD:", "Allows login against the LDAP / AD username, which is either uid or samaccountname and will be detected." : "Lejon hyrje kundrejt emrin të përdoruesit LDAP / AD, që është ose uid, ose samaccountname, dhe do të zbulohet.", @@ -94,6 +96,7 @@ "Limit %s access to users meeting these criteria:" : "Kufizo hyrje %s vetëm për përdorues që plotësojnë këtë kusht:", "The most common object classes for users are organizationalPerson, person, user, and inetOrgPerson. If you are not sure which object class to select, please consult your directory admin." : "Klasat më të rëndomta objektesht për përdoruesit janë organizationalPerson, person, user, dhe inetOrgPerson. Nëse s’jeni i sigurt cilën klasë objekti të përzgjidhniI, ju lutemi, lidhuni me përgjegjësin e drejtorisë suaj.", "The filter specifies which LDAP users shall have access to the %s instance." : "Filtri përcakton se cilët përdorues LDAP do të kenë hyrje te instanca %s.", + "Verify settings and count users" : "Verifiko rregullimet dhe numëro përdoruesit", "Saving" : "Po ruhet", "Back" : "Mbrapsht", "Continue" : "Vazhdo", 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..8b155dcfe23 100644 --- a/apps/user_ldap/l10n/th_TH.js +++ b/apps/user_ldap/l10n/th_TH.js @@ -24,7 +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 รายการ", + "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..9787ba10037 100644 --- a/apps/user_ldap/l10n/th_TH.json +++ b/apps/user_ldap/l10n/th_TH.json @@ -22,7 +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 รายการ", + "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..c9798c5382d 100644 --- a/apps/user_ldap/l10n/tr.js +++ b/apps/user_ldap/l10n/tr.js @@ -24,7 +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." : "1.000'den fazla dizin girdisi mevcut.", + "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 553dfe6cdbd..c60842078a7 100644 --- a/apps/user_ldap/l10n/tr.json +++ b/apps/user_ldap/l10n/tr.json @@ -22,7 +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." : "1.000'den fazla dizin girdisi mevcut.", + "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/zh_TW.js b/apps/user_ldap/l10n/zh_TW.js index 5eeddd06ccf..244206927ba 100644 --- a/apps/user_ldap/l10n/zh_TW.js +++ b/apps/user_ldap/l10n/zh_TW.js @@ -3,28 +3,96 @@ OC.L10N.register( { "Failed to clear the mappings." : "清除映射失敗", "Failed to delete the server configuration" : "刪除伺服器設定時失敗", + "The configuration is invalid: anonymous bind is not allowed." : "設定檔無效: 不允許匿名使者", "The configuration is valid and the connection could be established!" : "設定有效且連線可建立", "The configuration is valid, but the Bind failed. Please check the server settings and credentials." : "設定有效但連線無法建立,請檢查伺服器設定與認證資料。", + "The configuration is invalid. Please have a look at the logs for further details." : "設定無效,更多細節請參閱 ownCloud 的記錄檔。", + "No action specified" : "沒有指定操作", + "No configuration specified" : "沒有指定設定", + "No data specified" : "沒有指定資料", + " Could not set configuration %s" : "無法設定 %s 為設定值", + "Action does not exist" : "操作不存在", + "The Base DN appears to be wrong" : "Base DN 出現問題", + "Configuration incorrect" : "設定不正確", + "Configuration incomplete" : "設定未完成", + "Configuration OK" : "設定完成", "Select groups" : "選擇群組", + "Select object classes" : "選擇物件", + "Please check the credentials, they seem to be wrong." : "請檢查您的憑證,似乎出了點問題", + "Please specify the port, it could not be auto-detected." : "請您指定您的連接阜,無法自動偵測", + "Base DN could not be auto-detected, please revise credentials, host and port." : "Base DN 無法被自動偵測,請重新設定主機,連接阜以及認證", + "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中找不到物件,請重新修改", + "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" : "確認刪除", + "Mappings cleared successfully!" : "Mappings清除成功", + "Error while clearing the mappings." : "清除Mappings發生錯誤", + "Anonymous bind is not allowed. Please provide a User DN and Password." : "匿名是不允許的,請提供使用者DN和密碼", + "LDAP Operations error. Anonymous bind might not be allowed." : "LDAP 錯誤,不允許匿名榜定", + "Saving failed. Please make sure the database is in Operation. Reload before continuing." : "存檔失敗,請確認資料庫運作中,請重新讀取一次然後再試一次", + "Switching the mode will enable automatic LDAP queries. Depending on your LDAP size they may take a while. Do you still want to switch the mode?" : "切換模式會使LDAP自動抓取資訊,抓取資訊的時間依您的LDAP大小而定,可能會花一點時間,您確定要切換模式?", + "Mode switch" : "模式切換", + "Select attributes" : "選擇屬性", + "User not found. Please check your login attributes and username. Effective filter (to copy-and-paste for command line validation): <br/>" : "找不到使用者,請檢查您的登入資料以及使用者名稱。驗證(複製貼上到命令提示位元做認證):<br/>", + "User found and settings verified." : "使用者存在,設定值正確", + "An unspecified error occurred. Please check the settings and the log." : "發生預期之外的錯誤,請檢查設定和記錄檔", + "A connection error to LDAP / AD occurred, please check host, port and credentials." : "連線到 LDAP/AD出現錯誤,請檢查主機,連接阜和驗證資訊", + "Please provide a login name to test against" : "請提供登入姓名以便再次測試", + "The group box was disabled, because the LDAP / AD server does not support memberOf." : "群組盒已經停用,LDAP/AD 伺服器並不支援", + "_%s group found_::_%s groups found_" : ["找到 %s 群組"], + "_%s user found_::_%s users found_" : ["找到 %s 使用者"], + "Could not detect user display name attribute. Please specify it yourself in advanced ldap settings." : "無法偵測使用者的顯示名稱,請您自行在ldap設定中指定", + "Could not find the desired feature" : "無法找到所需的功能", + "Invalid Host" : "無效的Host", "Server" : "伺服器", "Users" : "使用者", + "Login Attributes" : "登入的設定", "Groups" : "群組", "Test Configuration" : "測試此設定", "Help" : "說明", + "Only from these groups:" : "只從這些群組:", + "Search groups" : "搜尋群組", + "Available groups" : "可用的群組", + "Selected groups" : "已選擇的群組", + "Edit LDAP Query" : "編輯LDAP Query", + "LDAP Filter:" : "LDAP 過慮器:", + "Verify settings and count groups" : "驗證設定並計算群組數", + "When logging in, %s will find the user based on the following attributes:" : "當登入%s時,將會根據以下屬性找到使用者 :", + "LDAP / AD Username:" : "LDAP / AD 使用者名稱:", + "LDAP / AD Email Address:" : "LDAP / AD 電子郵件:", + "Other Attributes:" : "其他屬性:", + "Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action. Example: \"uid=%%uid\"" : "試圖登入時會定義要套用的篩選器。登入過程中%%uid會取代使用者名稱。例如:\"uid=%%uid\"", + "Test Loginname" : "測試登入姓名", + "Verify settings" : "驗證設定", + "1. Server" : "1. 伺服器", + "%s. Server:" : "%s. 伺服器:", + "Add a new and blank configuration" : "新增一個空白的設定檔", + "Copy current configuration into new directory binding" : "複製目前的設定檔到新目錄", + "Delete the current configuration" : "刪除目前的設定檔", "Host" : "主機", "You can omit the protocol, except you require SSL. Then start with ldaps://" : "若您不需要 SSL 加密連線則不需輸入通訊協定,反之請輸入 ldaps://", "Port" : "連接埠", + "Detect Port" : "偵測連接阜", "User DN" : "User DN", "The DN of the client user with which the bind shall be done, e.g. uid=agent,dc=example,dc=com. For anonymous access, leave DN and Password empty." : "客戶端使用者的DN與特定字詞的連結需要完善,例如:uid=agent,dc=example,dc=com。若是匿名連接,則將DN與密碼欄位留白。", "Password" : "密碼", "For anonymous access, leave DN and Password empty." : "匿名連接時請將 DN 與密碼欄位留白", "One Base DN per line" : "一行一個 Base DN", "You can specify Base DN for users and groups in the Advanced tab" : "您可以在進階標籤頁裡面指定使用者及群組的 Base DN", + "Detect Base DN" : "偵測 Base DN", + "Test Base DN" : "測試 Base DN", + "Manually enter LDAP filters (recommended for large directories)" : "手動輸入 LDAP篩選器 (建議在大型的資料環境)", + "Limit %s access to users meeting these criteria:" : "當遇到以下標準時,限制%s存取使用者:", + "The filter specifies which LDAP users shall have access to the %s instance." : "篩選起指定哪些LDAP的使用者應該擁有存取%s的權限", + "Verify settings and count users" : "驗證設定並計算使用者數", + "Saving" : "儲存", "Back" : "返回", "Continue" : "繼續", + "LDAP" : "LDAP", "Advanced" : "進階", + "<b>Warning:</b> Apps user_ldap and user_webdavauth are incompatible. You may experience unexpected behavior. Please ask your system administrator to disable one of them." : "<b>警告:</b> 應用程式user_ldap和user_webdavauth互不相容。可能會造成無法預期的結果。請要求您的系統管理員將兩者其中之一停用。", "<b>Warning:</b> The PHP LDAP module is not installed, the backend will not work. Please ask your system administrator to install it." : "<b>警告:</b>沒有安裝 PHP LDAP 模組,後端系統將無法運作,請要求您的系統管理員安裝模組。", "Connection Settings" : "連線設定", "Configuration Active" : "設定使用中", @@ -34,15 +102,18 @@ OC.L10N.register( "Backup (Replica) Port" : "備用(複本)連接埠", "Disable Main Server" : "停用主伺服器", "Turn off SSL certificate validation." : "關閉 SSL 憑證檢查", + "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." : "不建議,請僅在測試時使用!如果連線只能在此設定下工作,請匯入LDAP伺服器的SSL認證到您的伺服器%s上", "Cache Time-To-Live" : "快取的存活時間", "in seconds. A change empties the cache." : "以秒為單位。變更後會清空快取。", "Directory Settings" : "目錄設定", "User Display Name Field" : "使用者顯示名稱欄位", + "The LDAP attribute to use to generate the user's display name." : "LDAP設定值,用於產生使用者的顯示名稱", "Base User Tree" : "Base User Tree", "One User Base DN per line" : "一行一個使用者 Base DN", "User Search Attributes" : "User Search Attributes", "Optional; one attribute per line" : "非必要,一行一項屬性", "Group Display Name Field" : "群組顯示名稱欄位", + "The LDAP attribute to use to generate the groups's display name." : "LDAP設定值,用於產生使用者群組的顯示名稱", "Base Group Tree" : "Base Group Tree", "One Group Base DN per line" : "一行一個 Group Base DN", "Group Search Attributes" : "Group Search Attributes", @@ -54,6 +125,10 @@ OC.L10N.register( "Email Field" : "電郵欄位", "User Home Folder Naming Rule" : "使用者家目錄的命名規則", "Leave empty for user name (default). Otherwise, specify an LDAP/AD attribute." : "使用者名稱請留白(預設)。若不留白請指定一個LDAP/AD屬性。", - "Internal Username" : "內部使用者名稱" + "Internal Username" : "內部使用者名稱", + "Internal Username Attribute:" : "內部使用者名稱屬性:", + "Override UUID detection" : "偵測覆寫UUID", + "UUID Attribute for Users:" : "使用者的UUID值:", + "UUID Attribute for Groups:" : "群組的UUID值:" }, "nplurals=1; plural=0;"); diff --git a/apps/user_ldap/l10n/zh_TW.json b/apps/user_ldap/l10n/zh_TW.json index 60403875d29..35b5b5bad27 100644 --- a/apps/user_ldap/l10n/zh_TW.json +++ b/apps/user_ldap/l10n/zh_TW.json @@ -1,28 +1,96 @@ { "translations": { "Failed to clear the mappings." : "清除映射失敗", "Failed to delete the server configuration" : "刪除伺服器設定時失敗", + "The configuration is invalid: anonymous bind is not allowed." : "設定檔無效: 不允許匿名使者", "The configuration is valid and the connection could be established!" : "設定有效且連線可建立", "The configuration is valid, but the Bind failed. Please check the server settings and credentials." : "設定有效但連線無法建立,請檢查伺服器設定與認證資料。", + "The configuration is invalid. Please have a look at the logs for further details." : "設定無效,更多細節請參閱 ownCloud 的記錄檔。", + "No action specified" : "沒有指定操作", + "No configuration specified" : "沒有指定設定", + "No data specified" : "沒有指定資料", + " Could not set configuration %s" : "無法設定 %s 為設定值", + "Action does not exist" : "操作不存在", + "The Base DN appears to be wrong" : "Base DN 出現問題", + "Configuration incorrect" : "設定不正確", + "Configuration incomplete" : "設定未完成", + "Configuration OK" : "設定完成", "Select groups" : "選擇群組", + "Select object classes" : "選擇物件", + "Please check the credentials, they seem to be wrong." : "請檢查您的憑證,似乎出了點問題", + "Please specify the port, it could not be auto-detected." : "請您指定您的連接阜,無法自動偵測", + "Base DN could not be auto-detected, please revise credentials, host and port." : "Base DN 無法被自動偵測,請重新設定主機,連接阜以及認證", + "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中找不到物件,請重新修改", + "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" : "確認刪除", + "Mappings cleared successfully!" : "Mappings清除成功", + "Error while clearing the mappings." : "清除Mappings發生錯誤", + "Anonymous bind is not allowed. Please provide a User DN and Password." : "匿名是不允許的,請提供使用者DN和密碼", + "LDAP Operations error. Anonymous bind might not be allowed." : "LDAP 錯誤,不允許匿名榜定", + "Saving failed. Please make sure the database is in Operation. Reload before continuing." : "存檔失敗,請確認資料庫運作中,請重新讀取一次然後再試一次", + "Switching the mode will enable automatic LDAP queries. Depending on your LDAP size they may take a while. Do you still want to switch the mode?" : "切換模式會使LDAP自動抓取資訊,抓取資訊的時間依您的LDAP大小而定,可能會花一點時間,您確定要切換模式?", + "Mode switch" : "模式切換", + "Select attributes" : "選擇屬性", + "User not found. Please check your login attributes and username. Effective filter (to copy-and-paste for command line validation): <br/>" : "找不到使用者,請檢查您的登入資料以及使用者名稱。驗證(複製貼上到命令提示位元做認證):<br/>", + "User found and settings verified." : "使用者存在,設定值正確", + "An unspecified error occurred. Please check the settings and the log." : "發生預期之外的錯誤,請檢查設定和記錄檔", + "A connection error to LDAP / AD occurred, please check host, port and credentials." : "連線到 LDAP/AD出現錯誤,請檢查主機,連接阜和驗證資訊", + "Please provide a login name to test against" : "請提供登入姓名以便再次測試", + "The group box was disabled, because the LDAP / AD server does not support memberOf." : "群組盒已經停用,LDAP/AD 伺服器並不支援", + "_%s group found_::_%s groups found_" : ["找到 %s 群組"], + "_%s user found_::_%s users found_" : ["找到 %s 使用者"], + "Could not detect user display name attribute. Please specify it yourself in advanced ldap settings." : "無法偵測使用者的顯示名稱,請您自行在ldap設定中指定", + "Could not find the desired feature" : "無法找到所需的功能", + "Invalid Host" : "無效的Host", "Server" : "伺服器", "Users" : "使用者", + "Login Attributes" : "登入的設定", "Groups" : "群組", "Test Configuration" : "測試此設定", "Help" : "說明", + "Only from these groups:" : "只從這些群組:", + "Search groups" : "搜尋群組", + "Available groups" : "可用的群組", + "Selected groups" : "已選擇的群組", + "Edit LDAP Query" : "編輯LDAP Query", + "LDAP Filter:" : "LDAP 過慮器:", + "Verify settings and count groups" : "驗證設定並計算群組數", + "When logging in, %s will find the user based on the following attributes:" : "當登入%s時,將會根據以下屬性找到使用者 :", + "LDAP / AD Username:" : "LDAP / AD 使用者名稱:", + "LDAP / AD Email Address:" : "LDAP / AD 電子郵件:", + "Other Attributes:" : "其他屬性:", + "Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action. Example: \"uid=%%uid\"" : "試圖登入時會定義要套用的篩選器。登入過程中%%uid會取代使用者名稱。例如:\"uid=%%uid\"", + "Test Loginname" : "測試登入姓名", + "Verify settings" : "驗證設定", + "1. Server" : "1. 伺服器", + "%s. Server:" : "%s. 伺服器:", + "Add a new and blank configuration" : "新增一個空白的設定檔", + "Copy current configuration into new directory binding" : "複製目前的設定檔到新目錄", + "Delete the current configuration" : "刪除目前的設定檔", "Host" : "主機", "You can omit the protocol, except you require SSL. Then start with ldaps://" : "若您不需要 SSL 加密連線則不需輸入通訊協定,反之請輸入 ldaps://", "Port" : "連接埠", + "Detect Port" : "偵測連接阜", "User DN" : "User DN", "The DN of the client user with which the bind shall be done, e.g. uid=agent,dc=example,dc=com. For anonymous access, leave DN and Password empty." : "客戶端使用者的DN與特定字詞的連結需要完善,例如:uid=agent,dc=example,dc=com。若是匿名連接,則將DN與密碼欄位留白。", "Password" : "密碼", "For anonymous access, leave DN and Password empty." : "匿名連接時請將 DN 與密碼欄位留白", "One Base DN per line" : "一行一個 Base DN", "You can specify Base DN for users and groups in the Advanced tab" : "您可以在進階標籤頁裡面指定使用者及群組的 Base DN", + "Detect Base DN" : "偵測 Base DN", + "Test Base DN" : "測試 Base DN", + "Manually enter LDAP filters (recommended for large directories)" : "手動輸入 LDAP篩選器 (建議在大型的資料環境)", + "Limit %s access to users meeting these criteria:" : "當遇到以下標準時,限制%s存取使用者:", + "The filter specifies which LDAP users shall have access to the %s instance." : "篩選起指定哪些LDAP的使用者應該擁有存取%s的權限", + "Verify settings and count users" : "驗證設定並計算使用者數", + "Saving" : "儲存", "Back" : "返回", "Continue" : "繼續", + "LDAP" : "LDAP", "Advanced" : "進階", + "<b>Warning:</b> Apps user_ldap and user_webdavauth are incompatible. You may experience unexpected behavior. Please ask your system administrator to disable one of them." : "<b>警告:</b> 應用程式user_ldap和user_webdavauth互不相容。可能會造成無法預期的結果。請要求您的系統管理員將兩者其中之一停用。", "<b>Warning:</b> The PHP LDAP module is not installed, the backend will not work. Please ask your system administrator to install it." : "<b>警告:</b>沒有安裝 PHP LDAP 模組,後端系統將無法運作,請要求您的系統管理員安裝模組。", "Connection Settings" : "連線設定", "Configuration Active" : "設定使用中", @@ -32,15 +100,18 @@ "Backup (Replica) Port" : "備用(複本)連接埠", "Disable Main Server" : "停用主伺服器", "Turn off SSL certificate validation." : "關閉 SSL 憑證檢查", + "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." : "不建議,請僅在測試時使用!如果連線只能在此設定下工作,請匯入LDAP伺服器的SSL認證到您的伺服器%s上", "Cache Time-To-Live" : "快取的存活時間", "in seconds. A change empties the cache." : "以秒為單位。變更後會清空快取。", "Directory Settings" : "目錄設定", "User Display Name Field" : "使用者顯示名稱欄位", + "The LDAP attribute to use to generate the user's display name." : "LDAP設定值,用於產生使用者的顯示名稱", "Base User Tree" : "Base User Tree", "One User Base DN per line" : "一行一個使用者 Base DN", "User Search Attributes" : "User Search Attributes", "Optional; one attribute per line" : "非必要,一行一項屬性", "Group Display Name Field" : "群組顯示名稱欄位", + "The LDAP attribute to use to generate the groups's display name." : "LDAP設定值,用於產生使用者群組的顯示名稱", "Base Group Tree" : "Base Group Tree", "One Group Base DN per line" : "一行一個 Group Base DN", "Group Search Attributes" : "Group Search Attributes", @@ -52,6 +123,10 @@ "Email Field" : "電郵欄位", "User Home Folder Naming Rule" : "使用者家目錄的命名規則", "Leave empty for user name (default). Otherwise, specify an LDAP/AD attribute." : "使用者名稱請留白(預設)。若不留白請指定一個LDAP/AD屬性。", - "Internal Username" : "內部使用者名稱" + "Internal Username" : "內部使用者名稱", + "Internal Username Attribute:" : "內部使用者名稱屬性:", + "Override UUID detection" : "偵測覆寫UUID", + "UUID Attribute for Users:" : "使用者的UUID值:", + "UUID Attribute for Groups:" : "群組的UUID值:" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php index 32472c13b03..7be91186c16 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -35,6 +35,7 @@ namespace OCA\user_ldap\lib; +use OCA\user_ldap\lib\user\OfflineUser; use OCA\User_LDAP\Mapping\AbstractMapping; /** @@ -672,6 +673,20 @@ class Access extends LDAPUtility implements user\IUserTools { } /** + * counts the number of users according to a provided loginName and + * utilizing the login filter. + * + * @param string $loginName + * @return array + */ + public function countUsersByLoginName($loginName) { + $loginName = $this->escapeFilterPart($loginName); + $filter = str_replace('%uid', $loginName, $this->connection->ldapLoginFilter); + $users = $this->countUsers($filter); + return $users; + } + + /** * @param string $filter * @param string|string[] $attr * @param int $limit @@ -692,9 +707,13 @@ class Access extends LDAPUtility implements user\IUserTools { */ public function batchApplyUserAttributes(array $ldapRecords){ foreach($ldapRecords as $userRecord) { - $ocName = $this->dn2ocname($userRecord['dn'][0], $userRecord[$this->connection->ldapUserDisplayName]); + $ocName = $this->dn2ocname($userRecord['dn'][0]); $this->cacheUserExists($ocName); $user = $this->userManager->get($ocName); + if($user instanceof OfflineUser) { + $user->unmark(); + $user = $this->userManager->get($ocName); + } $user->processAttributes($userRecord); } } diff --git a/apps/user_ldap/lib/configuration.php b/apps/user_ldap/lib/configuration.php index 4a6263de9aa..e1ca624af95 100644 --- a/apps/user_ldap/lib/configuration.php +++ b/apps/user_ldap/lib/configuration.php @@ -3,6 +3,7 @@ * @author Alexander Bergolth <leo@strike.wu.ac.at> * @author Arthur Schiwon <blizzz@owncloud.com> * @author Jörn Friedrich Dreyer <jfd@butonic.de> + * @author Lennart Rosam <hello@takuto.de> * @author Lukas Reschke <lukas@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> * @author Robin McCorkell <rmccorkell@karoshi.org.uk> diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index f6b123babd0..3f3953bb28b 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -526,30 +526,41 @@ class Connection extends LDAPUtility { \OCP\Util::WARN); } } - if(!$this->configuration->ldapOverrideMainServer - && !$this->getFromCache('overrideMainServer')) { - $this->doConnect($this->configuration->ldapHost, - $this->configuration->ldapPort); - $bindStatus = $this->bind(); - $error = $this->ldap->isResource($this->ldapConnectionRes) ? - $this->ldap->errno($this->ldapConnectionRes) : -1; - } else { - $bindStatus = false; - $error = null; + + $bindStatus = false; + $error = null; + try { + if (!$this->configuration->ldapOverrideMainServer + && !$this->getFromCache('overrideMainServer') + ) { + $this->doConnect($this->configuration->ldapHost, + $this->configuration->ldapPort); + $bindStatus = $this->bind(); + $error = $this->ldap->isResource($this->ldapConnectionRes) ? + $this->ldap->errno($this->ldapConnectionRes) : -1; + } + if($bindStatus === true) { + return $bindStatus; + } + } catch (\OC\ServerNotAvailableException $e) { + if(trim($this->configuration->ldapBackupHost) === "") { + throw $e; + } } //if LDAP server is not reachable, try the Backup (Replica!) Server - if((!$bindStatus && ($error !== 0)) + if( $error !== 0 || $this->configuration->ldapOverrideMainServer - || $this->getFromCache('overrideMainServer')) { - $this->doConnect($this->configuration->ldapBackupHost, - $this->configuration->ldapBackupPort); - $bindStatus = $this->bind(); - if(!$bindStatus && $error === -1) { - //when bind to backup server succeeded and failed to main server, - //skip contacting him until next cache refresh - $this->writeToCache('overrideMainServer', true); - } + || $this->getFromCache('overrideMainServer')) + { + $this->doConnect($this->configuration->ldapBackupHost, + $this->configuration->ldapBackupPort); + $bindStatus = $this->bind(); + if($bindStatus && $error === -1) { + //when bind to backup server succeeded and failed to main server, + //skip contacting him until next cache refresh + $this->writeToCache('overrideMainServer', true); + } } return $bindStatus; } diff --git a/apps/user_ldap/lib/filesystemhelper.php b/apps/user_ldap/lib/filesystemhelper.php index 6d431f6cb43..ee8c26d2f59 100644 --- a/apps/user_ldap/lib/filesystemhelper.php +++ b/apps/user_ldap/lib/filesystemhelper.php @@ -1,6 +1,7 @@ <?php /** * @author Arthur Schiwon <blizzz@owncloud.com> + * @author Joas Schilling <nickvergessen@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> * * @copyright Copyright (c) 2015, ownCloud, Inc. diff --git a/apps/user_ldap/lib/user/deletedusersindex.php b/apps/user_ldap/lib/user/deletedusersindex.php index f8c1406d77e..6b58595cce6 100644 --- a/apps/user_ldap/lib/user/deletedusersindex.php +++ b/apps/user_ldap/lib/user/deletedusersindex.php @@ -1,6 +1,7 @@ <?php /** * @author Arthur Schiwon <blizzz@owncloud.com> + * @author Joas Schilling <nickvergessen@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> * * @copyright Copyright (c) 2015, ownCloud, Inc. diff --git a/apps/user_ldap/lib/user/manager.php b/apps/user_ldap/lib/user/manager.php index 89bbc849887..4a687c0832a 100644 --- a/apps/user_ldap/lib/user/manager.php +++ b/apps/user_ldap/lib/user/manager.php @@ -1,6 +1,7 @@ <?php /** * @author Arthur Schiwon <blizzz@owncloud.com> + * @author Joas Schilling <nickvergessen@owncloud.com> * @author Jörn Friedrich Dreyer <jfd@butonic.de> * @author Morris Jobke <hey@morrisjobke.de> * diff --git a/apps/user_ldap/lib/user/offlineuser.php b/apps/user_ldap/lib/user/offlineuser.php index 8177e84346f..3456a27b412 100644 --- a/apps/user_ldap/lib/user/offlineuser.php +++ b/apps/user_ldap/lib/user/offlineuser.php @@ -1,6 +1,7 @@ <?php /** * @author Arthur Schiwon <blizzz@owncloud.com> + * @author Joas Schilling <nickvergessen@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> * * @copyright Copyright (c) 2015, ownCloud, Inc. @@ -85,6 +86,13 @@ class OfflineUser { } /** + * remove the Delete-flag from the user. + */ + public function unmark() { + $this->config->setUserValue($this->ocName, 'user_ldap', 'isDeleted', '0'); + } + + /** * exports the user details in an assoc array * @return array */ diff --git a/apps/user_ldap/lib/user/user.php b/apps/user_ldap/lib/user/user.php index 756b923e7e5..0dc3c8c0c26 100644 --- a/apps/user_ldap/lib/user/user.php +++ b/apps/user_ldap/lib/user/user.php @@ -1,6 +1,7 @@ <?php /** * @author Arthur Schiwon <blizzz@owncloud.com> + * @author Joas Schilling <nickvergessen@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> * * @copyright Copyright (c) 2015, ownCloud, Inc. @@ -416,9 +417,9 @@ class User { } //can be null $quotaDefault = $this->connection->ldapQuotaDefault; - $quota = !is_null($valueFromLDAP) - ? $valueFromLDAP - : $quotaDefault !== '' ? $quotaDefault : null; + $quota = $quotaDefault !== '' ? $quotaDefault : null; + $quota = !is_null($valueFromLDAP) ? $valueFromLDAP : $quota; + if(is_null($valueFromLDAP)) { $quotaAttribute = $this->connection->ldapQuotaAttribute; if(!empty($quotaAttribute)) { diff --git a/apps/user_ldap/lib/wizard.php b/apps/user_ldap/lib/wizard.php index a819b2e0e46..e53ff35cfd6 100644 --- a/apps/user_ldap/lib/wizard.php +++ b/apps/user_ldap/lib/wizard.php @@ -631,12 +631,12 @@ class Wizard extends LDAPUtility { throw new \Exception('missing placeholder'); } - $users = $this->access->fetchUsersByLoginName($loginName); + $users = $this->access->countUsersByLoginName($loginName); if($this->ldap->errno($cr) !== 0) { throw new \Exception($this->ldap->error($cr)); } $filter = str_replace('%uid', $loginName, $this->access->connection->ldapLoginFilter); - $this->result->addChange('ldap_test_loginname', count($users)); + $this->result->addChange('ldap_test_loginname', $users); $this->result->addChange('ldap_test_effective_filter', $filter); return $this->result; } @@ -1290,9 +1290,13 @@ class Wizard extends LDAPUtility { if(!is_null($this->cr)) { return $this->cr; } - $cr = $this->ldap->connect( - $this->configuration->ldapHost.':'.$this->configuration->ldapPort, - $this->configuration->ldapPort); + + $host = $this->configuration->ldapHost; + if(strpos($host, '://') !== false) { + //ldap_connect ignores port parameter when URLs are passed + $host .= ':' . $this->configuration->ldapPort; + } + $cr = $this->ldap->connect($host, $this->configuration->ldapPort); $this->ldap->setOption($cr, LDAP_OPT_PROTOCOL_VERSION, 3); $this->ldap->setOption($cr, LDAP_OPT_REFERRALS, 0); diff --git a/apps/user_ldap/templates/part.wizard-groupfilter.php b/apps/user_ldap/templates/part.wizard-groupfilter.php index 2f663b858e2..5c406450f6f 100644 --- a/apps/user_ldap/templates/part.wizard-groupfilter.php +++ b/apps/user_ldap/templates/part.wizard-groupfilter.php @@ -28,7 +28,7 @@ <label></label> <select class="ldapGroupList ldapGroupListAvailable" multiple="multiple" title="<?php p($l->t('Available groups'));?>"></select> - <span> + <span class="buttonSpan"> <button class="ldapGroupListSelect" type="button">></button><br/> <button class="ldapGroupListDeselect" type="button"><</button> </span> diff --git a/apps/user_ldap/templates/part.wizard-server.php b/apps/user_ldap/templates/part.wizard-server.php index a16ac1f50dc..56d351eb10b 100644 --- a/apps/user_ldap/templates/part.wizard-server.php +++ b/apps/user_ldap/templates/part.wizard-server.php @@ -24,14 +24,14 @@ ?> </select> <button type="button" id="ldap_action_add_configuration" - name="ldap_action_add_configuration" class="icon-add" + name="ldap_action_add_configuration" class="icon-add icon-default-style" title="<?php p($l->t('Add a new and blank configuration'));?>"> </button> <button type="button" id="ldap_action_copy_configuration" name="ldap_action_copy_configuration" class="ldapIconCopy icon-default-style" title="<?php p($l->t('Copy current configuration into new directory binding'));?>"> </button> <button type="button" id="ldap_action_delete_configuration" - name="ldap_action_delete_configuration" class="icon-delete" + name="ldap_action_delete_configuration" class="icon-delete icon-default-style" title="<?php p($l->t('Delete the current configuration'));?>"> </button> </p> @@ -44,7 +44,7 @@ placeholder="<?php p($l->t('Host'));?>" title="<?php p($l->t('You can omit the protocol, except you require SSL. Then start with ldaps://'));?>" /> - <span> + <span class="hostPortCombinatorSpan"> <input type="number" id="ldap_port" name="ldap_port" placeholder="<?php p($l->t('Port'));?>" /> <button class="ldapDetectPort" name="ldapDetectPort" type="button"> diff --git a/apps/user_ldap/templates/part.wizard-userfilter.php b/apps/user_ldap/templates/part.wizard-userfilter.php index 691c41a66a6..4c04d4372f7 100644 --- a/apps/user_ldap/templates/part.wizard-userfilter.php +++ b/apps/user_ldap/templates/part.wizard-userfilter.php @@ -31,7 +31,7 @@ <label></label> <select class="ldapGroupList ldapGroupListAvailable" multiple="multiple" title="<?php p($l->t('Available groups'));?>"></select> - <span> + <span class="buttonSpan"> <button class="ldapGroupListSelect" type="button">></button><br/> <button class="ldapGroupListDeselect" type="button"><</button> </span> diff --git a/apps/user_ldap/tests/access.php b/apps/user_ldap/tests/access.php index cb6dbf0cd5d..25e871d9b3d 100644 --- a/apps/user_ldap/tests/access.php +++ b/apps/user_ldap/tests/access.php @@ -230,24 +230,34 @@ class Test_Access extends \Test\TestCase { $mapperMock = $this->getMockBuilder('\OCA\User_LDAP\Mapping\UserMapping') ->disableOriginalConstructor() ->getMock(); + + $mapperMock->expects($this->any()) + ->method('getNameByDN') + ->will($this->returnValue('a_username')); + $userMock = $this->getMockBuilder('\OCA\user_ldap\lib\user\User') ->disableOriginalConstructor() ->getMock(); + $access->connection->expects($this->any()) + ->method('__get') + ->will($this->returnValue('displayName')); + $access->setUserMapper($mapperMock); + $displayNameAttribute = strtolower($access->connection->ldapUserDisplayName); $data = array( array( 'dn' => 'foobar', - $con->ldapUserDisplayName => 'barfoo' + $displayNameAttribute => 'barfoo' ), array( 'dn' => 'foo', - $con->ldapUserDisplayName => 'bar' + $displayNameAttribute => 'bar' ), array( 'dn' => 'raboof', - $con->ldapUserDisplayName => 'oofrab' + $displayNameAttribute => 'oofrab' ) ); diff --git a/apps/user_ldap/tests/group_ldap.php b/apps/user_ldap/tests/group_ldap.php index 49af5e3fe34..6a6d5bc7ca1 100644 --- a/apps/user_ldap/tests/group_ldap.php +++ b/apps/user_ldap/tests/group_ldap.php @@ -3,6 +3,7 @@ * @author Arthur Schiwon <blizzz@owncloud.com> * @author Frédéric Fortier <frederic.fortier@oronospolytechnique.com> * @author Joas Schilling <nickvergessen@owncloud.com> + * @author Lukas Reschke <lukas@owncloud.com> * @author Morris Jobke <hey@morrisjobke.de> * * @copyright Copyright (c) 2015, ownCloud, Inc. diff --git a/apps/user_ldap/tests/integration/fakemanager.php b/apps/user_ldap/tests/integration/fakemanager.php index afc9c552a98..f47668aa15b 100644 --- a/apps/user_ldap/tests/integration/fakemanager.php +++ b/apps/user_ldap/tests/integration/fakemanager.php @@ -29,5 +29,8 @@ namespace OCA\user_ldap\tests\integration; * scope of these tests, we replace it with a mock. */ class FakeManager extends \OCA\user_ldap\lib\user\Manager { - public function __construct() {} + public function __construct() { + $this->ocConfig = \OC::$server->getConfig(); + $this->image = new \OCP\Image(); + } } diff --git a/apps/user_ldap/tests/integration/lib/integrationtestbackupserver.php b/apps/user_ldap/tests/integration/lib/integrationtestbackupserver.php new file mode 100644 index 00000000000..95cb4b8f270 --- /dev/null +++ b/apps/user_ldap/tests/integration/lib/integrationtestbackupserver.php @@ -0,0 +1,118 @@ +<?php +/** + * @author Arthur Schiwon <blizzz@owncloud.com> + * + * @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 <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\user_ldap\tests\integration\lib; + +use OCA\user_ldap\lib\user\Manager as LDAPUserManager; +use OCA\user_ldap\tests\integration\AbstractIntegrationTest; +use OCA\User_LDAP\Mapping\UserMapping; +use OCA\user_ldap\USER_LDAP; + +require_once __DIR__ . '/../../../../../lib/base.php'; + +class IntegrationBackupServer extends AbstractIntegrationTest { + /** @var UserMapping */ + protected $mapping; + + /** @var USER_LDAP */ + protected $backend; + + /** + * sets up the LDAP configuration to be used for the test + */ + protected function initConnection() { + parent::initConnection(); + $originalHost = $this->connection->ldapHost; + $originalPort = $this->connection->ldapPort; + $this->connection->setConfiguration([ + 'ldapHost' => 'qwertz.uiop', + 'ldapPort' => '32123', + 'ldap_backup_host' => $originalHost, + 'ldap_backup_port' => $originalPort, + ]); + } + + /** + * tests that a backup connection is being used when the main LDAP server + * is offline + * + * Beware: after starting docker, the LDAP host might not be ready yet, thus + * causing a false positive. Retry in that case… or increase the sleep time + * in run-test.sh + * + * @return bool + */ + protected function case1() { + try { + $this->connection->getConnectionResource(); + } catch (\OC\ServerNotAvailableException $e) { + return false; + } + return true; + } + + /** + * ensures that an exception is thrown if LDAP main server and LDAP backup + * server are not available + * + * @return bool + */ + protected function case2() { + // reset possible LDAP connection + $this->initConnection(); + try { + $this->connection->setConfiguration([ + 'ldap_backup_host' => 'qwertz.uiop', + 'ldap_backup_port' => '32123', + ]); + $this->connection->getConnectionResource(); + } catch (\OC\ServerNotAvailableException $e) { + return true; + } + return false; + } + + /** + * ensures that an exception is thrown if main LDAP server is down and a + * backup server is not given + * + * @return bool + */ + protected function case3() { + // reset possible LDAP connection + $this->initConnection(); + try { + $this->connection->setConfiguration([ + 'ldap_backup_host' => '', + 'ldap_backup_port' => '', + ]); + $this->connection->getConnectionResource(); + } catch (\OC\ServerNotAvailableException $e) { + return true; + } + return false; + } +} + +require_once(__DIR__ . '/../setup-scripts/config.php'); +$test = new IntegrationBackupServer($host, $port, $adn, $apwd, $bdn); +$test->init(); +$test->run(); diff --git a/apps/user_ldap/tests/integration/lib/integrationtestcountusersbyloginname.php b/apps/user_ldap/tests/integration/lib/integrationtestcountusersbyloginname.php new file mode 100644 index 00000000000..6e3908c558b --- /dev/null +++ b/apps/user_ldap/tests/integration/lib/integrationtestcountusersbyloginname.php @@ -0,0 +1,68 @@ +<?php +/** + * @author Arthur Schiwon <blizzz@owncloud.com> + * + * @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 <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\user_ldap\tests\integration\lib; + +use OCA\user_ldap\lib\user\Manager as LDAPUserManager; +use OCA\user_ldap\tests\integration\AbstractIntegrationTest; +use OCA\User_LDAP\Mapping\UserMapping; +use OCA\user_ldap\USER_LDAP; + +require_once __DIR__ . '/../../../../../lib/base.php'; + +class IntegrationTestUserHome extends AbstractIntegrationTest { + + /** + * prepares the LDAP environment and sets up a test configuration for + * the LDAP backend. + */ + public function init() { + require(__DIR__ . '/../setup-scripts/createExplicitUsers.php'); + parent::init(); + } + + /** + * tests countUsersByLoginName where it is expected that the login name does + * not match any LDAP user + * + * @return bool + */ + protected function case1() { + $result = $this->access->countUsersByLoginName('nothere'); + return $result === 0; + } + + /** + * tests countUsersByLoginName where it is expected that the login name does + * match one LDAP user + * + * @return bool + */ + protected function case2() { + $result = $this->access->countUsersByLoginName('alice'); + return $result === 1; + } +} + +require_once(__DIR__ . '/../setup-scripts/config.php'); +$test = new IntegrationTestUserHome($host, $port, $adn, $apwd, $bdn); +$test->init(); +$test->run(); diff --git a/apps/user_ldap/tests/integration/lib/integrationtestfetchusersbyloginname.php b/apps/user_ldap/tests/integration/lib/integrationtestfetchusersbyloginname.php new file mode 100644 index 00000000000..403c3a0c73c --- /dev/null +++ b/apps/user_ldap/tests/integration/lib/integrationtestfetchusersbyloginname.php @@ -0,0 +1,79 @@ +<?php +/** + * @author Arthur Schiwon <blizzz@owncloud.com> + * + * @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 <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\user_ldap\tests\integration\lib; + +use OCA\user_ldap\lib\user\Manager as LDAPUserManager; +use OCA\user_ldap\tests\integration\AbstractIntegrationTest; +use OCA\User_LDAP\Mapping\UserMapping; +use OCA\user_ldap\USER_LDAP; + +require_once __DIR__ . '/../../../../../lib/base.php'; + +class IntegrationTestUserHome extends AbstractIntegrationTest { + /** @var UserMapping */ + protected $mapping; + + /** @var USER_LDAP */ + protected $backend; + + /** + * prepares the LDAP environment and sets up a test configuration for + * the LDAP backend. + */ + public function init() { + require(__DIR__ . '/../setup-scripts/createExplicitUsers.php'); + parent::init(); + + $this->mapping = new UserMapping(\OC::$server->getDatabaseConnection()); + $this->mapping->clear(); + $this->access->setUserMapper($this->mapping); + $this->backend = new \OCA\user_ldap\USER_LDAP($this->access, \OC::$server->getConfig()); + } + + /** + * tests fetchUserByLoginName where it is expected that the login name does + * not match any LDAP user + * + * @return bool + */ + protected function case1() { + $result = $this->access->fetchUsersByLoginName('nothere'); + return $result === []; + } + + /** + * tests fetchUserByLoginName where it is expected that the login name does + * match one LDAP user + * + * @return bool + */ + protected function case2() { + $result = $this->access->fetchUsersByLoginName('alice'); + return count($result) === 1; + } + +} + +require_once(__DIR__ . '/../setup-scripts/config.php'); +$test = new IntegrationTestUserHome($host, $port, $adn, $apwd, $bdn); +$test->init(); +$test->run(); diff --git a/apps/user_ldap/tests/user/user.php b/apps/user_ldap/tests/user/user.php index 1c41eb71ec2..19581d835d1 100644 --- a/apps/user_ldap/tests/user/user.php +++ b/apps/user_ldap/tests/user/user.php @@ -370,6 +370,45 @@ class Test_User_User extends \Test\TestCase { $user->updateQuota(); } + public function testUpdateQuotaFromValue() { + list($access, $config, $filesys, $image, $log, $avaMgr, $dbc) = + $this->getTestInstances(); + + list($access, $connection) = + $this->getAdvancedMocks($config, $filesys, $log, $avaMgr, $dbc); + + $readQuota = '19 GB'; + + $connection->expects($this->at(0)) + ->method('__get') + ->with($this->equalTo('ldapQuotaDefault')) + ->will($this->returnValue('')); + + $connection->expects($this->once(1)) + ->method('__get') + ->with($this->equalTo('ldapQuotaDefault')) + ->will($this->returnValue(null)); + + $access->expects($this->never()) + ->method('readAttribute'); + + $config->expects($this->once()) + ->method('setUserValue') + ->with($this->equalTo('alice'), + $this->equalTo('files'), + $this->equalTo('quota'), + $this->equalTo($readQuota)) + ->will($this->returnValue(true)); + + $uid = 'alice'; + $dn = 'uid=alice,dc=foo,dc=bar'; + + $user = new User( + $uid, $dn, $access, $config, $filesys, $image, $log, $avaMgr); + + $user->updateQuota($readQuota); + } + //the testUpdateAvatar series also implicitely tests getAvatarImage public function testUpdateAvatarJpegPhotoProvided() { list($access, $config, $filesys, $image, $log, $avaMgr, $dbc) = |