diff options
96 files changed, 2077 insertions, 1407 deletions
diff --git a/.drone.yml b/.drone.yml index 7efea13dcaa..dd4ec404209 100644 --- a/.drone.yml +++ b/.drone.yml @@ -304,6 +304,15 @@ pipeline: when: matrix: TESTS: integration-sharing-v1 + integration-sharing-v1-part2: + image: nextcloudci/integration-php7.0:integration-php7.0-3 + commands: + - ./occ maintenance:install --admin-pass=admin + - cd build/integration + - ./run.sh features/sharing-v1-part2.feature + when: + matrix: + TESTS: integration-sharing-v1-part2 integration-checksums-v1: image: nextcloudci/integration-php7.0:integration-php7.0-3 commands: @@ -493,6 +502,7 @@ matrix: - TESTS: integration-dav-v2 - TESTS: integration-ocs-v1 - TESTS: integration-sharing-v1 + - TESTS: integration-sharing-v1-part2 - TESTS: integration-checksums - TESTS: integration-external-storage - TESTS: integration-provisioning-v1 diff --git a/apps/dav/appinfo/info.xml b/apps/dav/appinfo/info.xml index 4cd606007c3..0902c487247 100644 --- a/apps/dav/appinfo/info.xml +++ b/apps/dav/appinfo/info.xml @@ -23,7 +23,7 @@ <repair-steps> <post-migration> <step>OCA\DAV\Migration\FixBirthdayCalendarComponent</step> - <step>OCA\DAV\Migration\ValueFixInsert</step> + <step>OCA\DAV\Migration\CalDAVRemoveEmptyValue</step> </post-migration> </repair-steps> <commands> diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php index dbe86438238..7976c1490ff 100644 --- a/apps/dav/lib/CalDAV/CalDavBackend.php +++ b/apps/dav/lib/CalDAV/CalDavBackend.php @@ -279,6 +279,10 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription $readOnlyPropertyName = '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}read-only'; while($row = $result->fetch()) { + if ($row['principaluri'] === $principalUri) { + continue; + } + $readOnly = (int) $row['access'] === Backend::ACCESS_READ; if (isset($calendars[$row['id']])) { if ($readOnly) { diff --git a/apps/dav/lib/CardDAV/CardDavBackend.php b/apps/dav/lib/CardDAV/CardDavBackend.php index 6f9a73298ef..397a77c1d1b 100644 --- a/apps/dav/lib/CardDAV/CardDavBackend.php +++ b/apps/dav/lib/CardDAV/CardDavBackend.php @@ -174,6 +174,10 @@ class CardDavBackend implements BackendInterface, SyncSupport { $readOnlyPropertyName = '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}read-only'; while($row = $result->fetch()) { + if ($row['principaluri'] === $principalUri) { + continue; + } + $readOnly = (int) $row['access'] === Backend::ACCESS_READ; if (isset($addressBooks[$row['id']])) { if ($readOnly) { diff --git a/apps/dav/lib/Migration/CalDAVRemoveEmptyValue.php b/apps/dav/lib/Migration/CalDAVRemoveEmptyValue.php new file mode 100644 index 00000000000..ae921ce4743 --- /dev/null +++ b/apps/dav/lib/Migration/CalDAVRemoveEmptyValue.php @@ -0,0 +1,119 @@ +<?php +/** + * @copyright 2017 Joas Schilling <coding@schilljs.com> + * + * @author Joas Schilling <coding@schilljs.com> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\DAV\Migration; + +use OCA\DAV\CalDAV\CalDavBackend; +use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\IDBConnection; +use OCP\ILogger; +use OCP\Migration\IOutput; +use OCP\Migration\IRepairStep; +use Sabre\VObject\InvalidDataException; + +class CalDAVRemoveEmptyValue implements IRepairStep { + + /** @var IDBConnection */ + private $db; + + /** @var CalDavBackend */ + private $calDavBackend; + + /** @var ILogger */ + private $logger; + + /** + * @param IDBConnection $db + * @param CalDavBackend $calDavBackend + * @param ILogger $logger + */ + public function __construct(IDBConnection $db, CalDavBackend $calDavBackend, ILogger $logger) { + $this->db = $db; + $this->calDavBackend = $calDavBackend; + $this->logger = $logger; + } + + public function getName() { + return 'Fix broken values of calendar objects'; + } + + public function run(IOutput $output) { + $pattern = ';VALUE=:'; + $count = $warnings = 0; + + $objects = $this->getInvalidObjects($pattern); + + $output->startProgress(count($objects)); + foreach ($objects as $row) { + $calObject = $this->calDavBackend->getCalendarObject((int)$row['calendarid'], $row['uri']); + $data = preg_replace('/' . $pattern . '/', ':', $calObject['calendardata']); + + if ($data !== $calObject['calendardata']) { + $output->advance(); + + try { + $this->calDavBackend->getDenormalizedData($data); + } catch (InvalidDataException $e) { + $this->logger->info('Calendar object for calendar {cal} with uri {uri} still invalid', [ + 'app' => 'dav', + 'cal' => (int)$row['calendarid'], + 'uri' => $row['uri'], + ]); + $warnings++; + continue; + } + + $this->calDavBackend->updateCalendarObject((int)$row['calendarid'], $row['uri'], $data); + $count++; + } + } + $output->finishProgress(); + + if ($warnings > 0) { + $output->warning(sprintf('%d events could not be updated, see log file for more information', $warnings)); + } + if ($count > 0) { + $output->info(sprintf('Updated %d events', $count)); + } + } + + protected function getInvalidObjects($pattern) { + $query = $this->db->getQueryBuilder(); + $query->select(['calendarid', 'uri']) + ->from('calendarobjects') + ->where($query->expr()->like( + 'calendardata', + $query->createNamedParameter( + '%' . $this->db->escapeLikeParameter($pattern) . '%', + IQueryBuilder::PARAM_STR + ), + IQueryBuilder::PARAM_STR + )); + + $result = $query->execute(); + $rows = $result->fetchAll(); + $result->closeCursor(); + + return $rows; + } +} diff --git a/apps/dav/lib/Migration/ValueFix.php b/apps/dav/lib/Migration/ValueFix.php deleted file mode 100644 index 2ad043b409d..00000000000 --- a/apps/dav/lib/Migration/ValueFix.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php -/** - * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ -namespace OCA\DAV\Migration; - -use OC\BackgroundJob\QueuedJob; -use OCA\DAV\CalDAV\CalDavBackend; -use OCP\ILogger; -use Sabre\VObject\InvalidDataException; - -class ValueFix extends QueuedJob { - - /** @var CalDavBackend */ - private $calDavBackend; - - /** @var ILogger */ - private $logger; - - public function __construct(CalDavBackend $calDavBackend, ILogger $logger) { - $this->calDavBackend = $calDavBackend; - $this->logger = $logger; - } - - public function run($argument) { - $user = $argument['user']; - - $pattern = '/;VALUE=:/'; - $principal = 'principals/users/' . $user; - $calendars = $this->calDavBackend->getCalendarsForUser($principal); - foreach ($calendars as $calendar) { - $objects = $this->calDavBackend->getCalendarObjects($calendar['id']); - foreach ($objects as $object) { - $calObject = $this->calDavBackend->getCalendarObject($calendar['id'], $object['uri']); - $data = preg_replace($pattern, ':', $calObject['calendardata']); - if ($data !== $calObject['calendardata']) { - try { - $this->calDavBackend->getDenormalizedData($data); - } catch (InvalidDataException $e) { - $this->logger->info('Calendar object for calendar {cal} with uri {uri} still invalid', [ - 'app'=> 'dav', - 'cal' => $calendar['id'], - 'uri' => $object['uri'], - ]); - continue; - } - $this->calDavBackend->updateCalendarObject($calendar['id'], $object['uri'], $data); - } - } - } - } - -} diff --git a/apps/dav/lib/Migration/ValueFixInsert.php b/apps/dav/lib/Migration/ValueFixInsert.php deleted file mode 100644 index 25917691b20..00000000000 --- a/apps/dav/lib/Migration/ValueFixInsert.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php -/** - * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ -namespace OCA\DAV\Migration; - -use OCP\BackgroundJob\IJobList; -use OCP\IConfig; -use OCP\IUser; -use OCP\IUserManager; -use OCP\Migration\IOutput; -use OCP\Migration\IRepairStep; - -class ValueFixInsert implements IRepairStep { - - /** @var IUserManager */ - private $userManager; - - /** @var IJobList */ - private $jobList; - - /** @var IConfig */ - private $config; - - public function __construct(IUserManager $userManager, - IJobList $jobList, - IConfig $config) { - $this->userManager = $userManager; - $this->jobList = $jobList; - $this->config = $config; - } - - public function getName() { - return 'Insert ValueFix background job for each user'; - } - - public function run(IOutput $output) { - if ($this->config->getAppValue('dav', self::class . '_ran', 'false') !== 'true') { - $this->userManager->callForSeenUsers(function (IUser $user) { - $this->jobList->add(ValueFix::class, ['user' => $user->getUID()]); - }); - $this->config->setAppValue('dav', self::class . '_ran', 'true'); - } - } -} diff --git a/apps/dav/tests/unit/Migration/CalDAVRemoveEmptyValueTest.php b/apps/dav/tests/unit/Migration/CalDAVRemoveEmptyValueTest.php new file mode 100644 index 00000000000..bf1f708e69a --- /dev/null +++ b/apps/dav/tests/unit/Migration/CalDAVRemoveEmptyValueTest.php @@ -0,0 +1,251 @@ +<?php +/** + * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ +namespace OCA\DAV\Tests\Unit\DAV\Migration; + +use OCA\DAV\CalDAV\CalDavBackend; +use OCA\DAV\Migration\CalDAVRemoveEmptyValue; +use OCP\ILogger; +use OCP\Migration\IOutput; +use Sabre\VObject\InvalidDataException; +use Test\TestCase; + +/** + * Class CalDAVRemoveEmptyValueTest + * + * @package OCA\DAV\Tests\Unit\DAV\Migration + * @group DB + */ +class CalDAVRemoveEmptyValueTest extends TestCase { + + /** @var ILogger|\PHPUnit_Framework_MockObject_MockObject */ + private $logger; + + /** @var CalDavBackend|\PHPUnit_Framework_MockObject_MockObject */ + private $backend; + + /** @var IOutput|\PHPUnit_Framework_MockObject_MockObject */ + private $output; + + /** @var string */ + private $invalid = 'BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Apple Inc.//Mac OS X 10.11.2//EN +CALSCALE:GREGORIAN +BEGIN:VEVENT +TRANSP:OPAQUE +DTEND;VALUE=:20151223T223000Z +LAST-MODIFIED:20151214T091032Z +ORGANIZER;CN="User 1":mailto:user1@example.com +UID:1234567890@example.com +DTSTAMP:20151214T091032Z +STATUS:CONFIRMED +SEQUENCE:0 +SUMMARY:Ein Geburtstag +DTSTART;VALUE=:20151223T173000Z +X-APPLE-TRAVEL-ADVISORY-BEHAVIOR:AUTOMATIC +CREATED;VALUE=:20151214T091032Z +END:VEVENT +END:VCALENDAR'; + + /** @var string */ + private $valid = 'BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Apple Inc.//Mac OS X 10.11.2//EN +CALSCALE:GREGORIAN +BEGIN:VEVENT +TRANSP:OPAQUE +DTEND:20151223T223000Z +LAST-MODIFIED:20151214T091032Z +ORGANIZER;CN="User 1":mailto:user1@example.com +UID:1234567890@example.com +DTSTAMP:20151214T091032Z +STATUS:CONFIRMED +SEQUENCE:0 +SUMMARY:Ein Geburtstag +DTSTART:20151223T173000Z +X-APPLE-TRAVEL-ADVISORY-BEHAVIOR:AUTOMATIC +CREATED:20151214T091032Z +END:VEVENT +END:VCALENDAR'; + + public function setUp() { + parent::setUp(); + + $this->logger = $this->createMock(ILogger::class); + $this->backend = $this->createMock(CalDavBackend::class); + $this->output = $this->createMock(IOutput::class); + } + + public function testRunAllValid() { + /** @var CalDAVRemoveEmptyValue|\PHPUnit_Framework_MockObject_MockObject $step */ + $step = $this->getMockBuilder(CalDAVRemoveEmptyValue::class) + ->setConstructorArgs([ + \OC::$server->getDatabaseConnection(), + $this->backend, + $this->logger + ]) + ->setMethods(['getInvalidObjects']) + ->getMock(); + + $step->expects($this->once()) + ->method('getInvalidObjects') + ->willReturn([]); + + $this->output->expects($this->once()) + ->method('startProgress') + ->with(0); + $this->output->expects($this->once()) + ->method('finishProgress'); + + $step->run($this->output); + } + + public function testRunInvalid() { + /** @var CalDAVRemoveEmptyValue|\PHPUnit_Framework_MockObject_MockObject $step */ + $step = $this->getMockBuilder(CalDAVRemoveEmptyValue::class) + ->setConstructorArgs([ + \OC::$server->getDatabaseConnection(), + $this->backend, + $this->logger + ]) + ->setMethods(['getInvalidObjects']) + ->getMock(); + + $step->expects($this->once()) + ->method('getInvalidObjects') + ->willReturn([ + ['calendarid' => '42', 'uri' => 'myuri'], + ]); + + $this->output->expects($this->once()) + ->method('startProgress') + ->with(1); + $this->output->expects($this->once()) + ->method('finishProgress'); + + $this->backend->expects($this->exactly(1)) + ->method('getCalendarObject') + ->with(42, 'myuri') + ->willReturn([ + 'calendardata' => $this->invalid + ]); + + $this->output->expects($this->exactly(1)) + ->method('advance'); + $this->backend->expects($this->exactly(1)) + ->method('getDenormalizedData') + ->with($this->valid); + + $this->backend->expects($this->exactly(1)) + ->method('updateCalendarObject') + ->with(42, 'myuri', $this->valid); + + $step->run($this->output); + } + + public function testRunValid() { + /** @var CalDAVRemoveEmptyValue|\PHPUnit_Framework_MockObject_MockObject $step */ + $step = $this->getMockBuilder(CalDAVRemoveEmptyValue::class) + ->setConstructorArgs([ + \OC::$server->getDatabaseConnection(), + $this->backend, + $this->logger + ]) + ->setMethods(['getInvalidObjects']) + ->getMock(); + + $step->expects($this->once()) + ->method('getInvalidObjects') + ->willReturn([ + ['calendarid' => '42', 'uri' => 'myuri'], + ]); + + $this->output->expects($this->once()) + ->method('startProgress') + ->with(1); + $this->output->expects($this->once()) + ->method('finishProgress'); + + + $this->backend->expects($this->exactly(1)) + ->method('getCalendarObject') + ->with(42, 'myuri') + ->willReturn([ + 'calendardata' => $this->valid + ]); + + $this->output->expects($this->never()) + ->method('advance'); + $this->backend->expects($this->never()) + ->method('getDenormalizedData'); + + $this->backend->expects($this->never()) + ->method('updateCalendarObject'); + + $step->run($this->output); + } + + public function testRunStillInvalid() { + /** @var CalDAVRemoveEmptyValue|\PHPUnit_Framework_MockObject_MockObject $step */ + $step = $this->getMockBuilder(CalDAVRemoveEmptyValue::class) + ->setConstructorArgs([ + \OC::$server->getDatabaseConnection(), + $this->backend, + $this->logger + ]) + ->setMethods(['getInvalidObjects']) + ->getMock(); + + $step->expects($this->once()) + ->method('getInvalidObjects') + ->willReturn([ + ['calendarid' => '42', 'uri' => 'myuri'], + ]); + + $this->output->expects($this->once()) + ->method('startProgress') + ->with(1); + $this->output->expects($this->once()) + ->method('finishProgress'); + + + $this->backend->expects($this->exactly(1)) + ->method('getCalendarObject') + ->with(42, 'myuri') + ->willReturn([ + 'calendardata' => $this->invalid + ]); + + $this->output->expects($this->exactly(1)) + ->method('advance'); + $this->backend->expects($this->exactly(1)) + ->method('getDenormalizedData') + ->with($this->valid) + ->willThrowException(new InvalidDataException()); + + $this->backend->expects($this->never()) + ->method('updateCalendarObject'); + + $step->run($this->output); + } +} diff --git a/apps/dav/tests/unit/Migration/ValueFixInsertTest.php b/apps/dav/tests/unit/Migration/ValueFixInsertTest.php deleted file mode 100644 index 26152e7d01d..00000000000 --- a/apps/dav/tests/unit/Migration/ValueFixInsertTest.php +++ /dev/null @@ -1,117 +0,0 @@ -<?php -/** - * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ -namespace OCA\DAV\Tests\Unit\DAV\Migration; - -use OCA\DAV\Migration\ValueFix; -use OCA\DAV\Migration\ValueFixInsert; -use OCP\BackgroundJob\IJobList; -use OCP\IConfig; -use OCP\IUser; -use OCP\IUserManager; -use OCP\Migration\IOutput; -use Test\TestCase; - -class ValueFixInsertTest extends TestCase { - /** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */ - private $userManager; - - /** @var IJobList|\PHPUnit_Framework_MockObject_MockObject */ - private $jobList; - - /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */ - private $config; - - /** @var ValueFixInsert */ - private $job; - - public function setUp() { - parent::setUp(); - - $this->userManager = $this->createMock(IUserManager::class); - $this->jobList = $this->createMock(IJobList::class); - $this->config = $this->createMock(IConfig::class); - $this->job = new ValueFixInsert( - $this->userManager, - $this->jobList, - $this->config - ); - } - - public function testGetName() { - $this->assertSame('Insert ValueFix background job for each user', $this->job->getName()); - } - - public function testRun() { - $user1 = $this->createMock(IUser::class); - $user1->method('getUID')->willReturn('user1'); - $user2 = $this->createMock(IUser::class); - $user2->method('getUID')->willReturn('user2'); - - $this->config->method('getAppValue') - ->with( - $this->equalTo('dav'), - $this->equalTo(ValueFixInsert::class.'_ran'), - $this->anything() - )->will($this->returnCallback(function($app, $key, $value) { - return $value; - })); - - $this->userManager->method('callForSeenUsers') - ->will($this->returnCallback(function(\Closure $function) use ($user1, $user2) { - $function($user1); - $function($user2); - })); - - $this->jobList->expects($this->at(0)) - ->method('add') - ->with( - $this->equalTo(ValueFix::class), - $this->equalTo(['user' => 'user1']) - ); - $this->jobList->expects($this->at(1)) - ->method('add') - ->with( - $this->equalTo(ValueFix::class), - $this->equalTo(['user' => 'user2']) - ); - - $this->job->run($this->createMock(IOutput::class)); - } - - public function testRunOnlyOnce() { - $this->config->method('getAppValue') - ->with( - $this->equalTo('dav'), - $this->equalTo(ValueFixInsert::class.'_ran'), - $this->anything() - )->willReturn('true'); - - $this->userManager->expects($this->never()) - ->method($this->anything());; - - $this->jobList->expects($this->never()) - ->method($this->anything()); - - $this->job->run($this->createMock(IOutput::class)); - } -} diff --git a/apps/dav/tests/unit/Migration/ValueFixTest.php b/apps/dav/tests/unit/Migration/ValueFixTest.php deleted file mode 100644 index 58b6f79621f..00000000000 --- a/apps/dav/tests/unit/Migration/ValueFixTest.php +++ /dev/null @@ -1,200 +0,0 @@ -<?php -/** - * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ -namespace OCA\DAV\Tests\Unit\DAV\Migration; - -use OCA\DAV\CalDAV\CalDavBackend; -use OCA\DAV\Migration\ValueFix; -use OCP\ILogger; -use Sabre\VObject\InvalidDataException; -use Test\TestCase; - -class ValueFixTest extends TestCase { - - /** @var ILogger|\PHPUnit_Framework_MockObject_MockObject */ - private $logger; - - /** @var CalDavBackend|\PHPUnit_Framework_MockObject_MockObject */ - private $backend; - - /** @var string */ - private $invalid = 'BEGIN:VCALENDAR -VERSION:2.0 -PRODID:-//Apple Inc.//Mac OS X 10.11.2//EN -CALSCALE:GREGORIAN -BEGIN:VEVENT -TRANSP:OPAQUE -DTEND;VALUE=:20151223T223000Z -LAST-MODIFIED:20151214T091032Z -ORGANIZER;CN="User 1":mailto:user1@example.com -UID:1234567890@example.com -DTSTAMP:20151214T091032Z -STATUS:CONFIRMED -SEQUENCE:0 -SUMMARY:Ein Geburtstag -DTSTART;VALUE=:20151223T173000Z -X-APPLE-TRAVEL-ADVISORY-BEHAVIOR:AUTOMATIC -CREATED;VALUE=:20151214T091032Z -END:VEVENT -END:VCALENDAR'; - - /** @var string */ - private $valid = 'BEGIN:VCALENDAR -VERSION:2.0 -PRODID:-//Apple Inc.//Mac OS X 10.11.2//EN -CALSCALE:GREGORIAN -BEGIN:VEVENT -TRANSP:OPAQUE -DTEND:20151223T223000Z -LAST-MODIFIED:20151214T091032Z -ORGANIZER;CN="User 1":mailto:user1@example.com -UID:1234567890@example.com -DTSTAMP:20151214T091032Z -STATUS:CONFIRMED -SEQUENCE:0 -SUMMARY:Ein Geburtstag -DTSTART:20151223T173000Z -X-APPLE-TRAVEL-ADVISORY-BEHAVIOR:AUTOMATIC -CREATED:20151214T091032Z -END:VEVENT -END:VCALENDAR'; - - /** @var ValueFix */ - private $job; - - public function setUp() { - parent::setUp(); - - $this->logger = $this->createMock(ILogger::class); - $this->backend = $this->createMock(CalDavBackend::class); - $this->job = new ValueFix( - $this->backend, - $this->logger - ); - } - - public function testRunInvalid() { - $calendars = [['id' => 42]]; - $objects = [['uri' => 'myuri']]; - - $this->backend->method('getCalendarsForUser') - ->with($this->equalTo('principals/users/u1')) - ->willReturn($calendars); - - $this->backend->method('getCalendarObjects') - ->with($this->equalTo(42)) - ->willReturn($objects); - - $this->backend->method('getCalendarObject') - ->with( - $this->equalTo(42), - $this->equalTo('myuri') - )->willReturn([ - 'calendardata' => $this->invalid - ]); - - $this->backend->expects($this->once()) - ->method('getDenormalizedData') - ->with($this->valid); - - $this->backend->expects($this->once()) - ->method('updateCalendarObject') - ->with( - $this->equalTo(42), - $this->equalTo('myuri'), - $this->equalTo($this->valid) - ); - - $this->job->run(['user' => 'u1']); - } - - public function testRunValid() { - $calendars = [['id' => 42]]; - $objects = [['uri' => 'myuri']]; - - $this->backend->method('getCalendarsForUser') - ->with($this->equalTo('principals/users/u1')) - ->willReturn($calendars); - - $this->backend->method('getCalendarObjects') - ->with($this->equalTo(42)) - ->willReturn($objects); - - $this->backend->method('getCalendarObject') - ->with( - $this->equalTo(42), - $this->equalTo('myuri') - )->willReturn([ - 'calendardata' => $this->valid - ]); - - $this->backend->expects($this->never()) - ->method('getDenormalizedData'); - - $this->backend->expects($this->never()) - ->method('updateCalendarObject'); - - $this->job->run(['user' => 'u1']); - } - - public function testRunStillInvalid() { - $calendars = [['id' => 42]]; - $objects = [['uri' => 'myuri']]; - - $this->backend->method('getCalendarsForUser') - ->with($this->equalTo('principals/users/u1')) - ->willReturn($calendars); - - $this->backend->method('getCalendarObjects') - ->with($this->equalTo(42)) - ->willReturn($objects); - - $this->backend->method('getCalendarObject') - ->with( - $this->equalTo(42), - $this->equalTo('myuri') - )->willReturn([ - 'calendardata' => $this->invalid - ]); - - $this->backend->expects($this->once()) - ->method('getDenormalizedData') - ->with($this->valid) - ->willThrowException(new InvalidDataException()); - - $this->logger->expects($this->once()) - ->method('info') - ->with( - $this->equalTo('Calendar object for calendar {cal} with uri {uri} still invalid'), - $this->equalTo([ - 'app'=> 'dav', - 'cal' => 42, - 'uri' => 'myuri', - ]) - ); - - $this->backend->expects($this->never()) - ->method('updateCalendarObject'); - - $this->job->run(['user' => 'u1']); - } -} diff --git a/apps/files/l10n/es_MX.js b/apps/files/l10n/es_MX.js index 45db24098e5..5c35f269273 100644 --- a/apps/files/l10n/es_MX.js +++ b/apps/files/l10n/es_MX.js @@ -1,64 +1,142 @@ OC.L10N.register( "files", { - "Unknown error" : "Error desconocido", - "Unable to set upload directory." : "Incapaz de crear directorio de subida.", - "Invalid Token" : "Token Inválido", - "No file was uploaded. Unknown error" : "No se subió ningún archivo. Error desconocido", - "There is no error, the file uploaded with success" : "No hubo ningún problema, el archivo se subió con éxito", - "The uploaded file exceeds the upload_max_filesize directive in php.ini: " : "El archivo subido sobrepasa la directiva 'upload_max_filesize' en php.ini:", - "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "El archivo subido sobrepasa la directiva 'MAX_FILE_SIZE' especificada en el formulario HTML", - "The uploaded file was only partially uploaded" : "El archivo subido fue sólo subido parcialmente", - "No file was uploaded" : "No se subió ningún archivo", - "Missing a temporary folder" : "Falta la carpeta temporal", - "Failed to write to disk" : "Falló al escribir al disco", - "Not enough storage available" : "No hay suficiente espacio disponible", - "Upload failed. Could not find uploaded file" : "Actualización fallida. No se pudo encontrar el archivo subido", - "Upload failed. Could not get file info." : "Actualización fallida. No se pudo obtener información del archivo.", - "Invalid directory." : "Directorio inválido.", - "Files" : "Archivos", + "Storage is temporarily not available" : "El almacenamiento no está disponible temporalmente ", + "Storage invalid" : "El almacenamiento es inválido", + "Unknown error" : "Se presentó un error desconocido", + "All files" : "Todos los archivos", + "Recent" : "Reciente", + "File could not be found" : "No fue posible encontrar el archivo", "Home" : "Particular", "Close" : "Cerrar", "Favorites" : "Favoritos", - "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.", - "Uploading..." : "Subiendo...", - "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.", + "Could not create folder \"{dir}\"" : "No fue posible crear la carpeta \"{dir}\"", + "Upload cancelled." : "Carga cancelada.", + "Unable to upload {filename} as it is a directory or has 0 bytes" : "No fue posible cargar {filename} ya que es una carpeta o tiene un tamaño de 0 bytes", + "Not enough free space, you are uploading {size1} but only {size2} is left" : "No cuenta con suficiente espacio disponible, usted se encuentra cargando {size1} pero solo cuenta con {size2} disponible", + "Target folder \"{dir}\" does not exist any more" : "La carpeta destino \"{dir}\" ya no existe", + "Not enough free space" : "No cuenta con suficiente espacio disponible", + "Uploading..." : "Cargando...", + "..." : "...", + "{loadedSize} of {totalSize} ({bitrate})" : "{loadedSize} de {totalSize} ({bitrate})", "Actions" : "Acciones", "Download" : "Descargar", "Rename" : "Renombrar", - "Delete" : "Eliminar", + "Move" : "Mover", + "Target folder" : "Carpeta destino", + "Delete" : "Borrar", + "Disconnect storage" : "Desconectar almacenamiento", "Unshare" : "Dejar de compartir", + "Could not load info for file \"{file}\"" : "No fue posible cargar información para el archivo \"{file}\"", + "Files" : "Archivos", "Details" : "Detalles", + "Select" : "Seleccionar", "Pending" : "Pendiente", + "Unable to determine date" : "No fue posible determinar la fecha", + "This operation is forbidden" : "Esta operación está prohibida", + "This directory is unavailable, please check the logs or contact the administrator" : "Esta carpeta no está disponible, favor de verficiar las bitácoras o contacte al administrador", + "Could not move \"{file}\", target exists" : "No fue posible mover \"{file}\", el destino ya existe", + "Could not move \"{file}\"" : "No fue posible mover \"{file}\"", + "{newName} already exists" : "{newName} ya existe", + "Could not rename \"{fileName}\", it does not exist any more" : "No fue posible renombrar \"{fileName}\", ya no existe", + "The name \"{targetName}\" is already used in the folder \"{dir}\". Please choose a different name." : "El nombre \"{targetName}\" ya está en uso en la carpeta \"{dir}\". Favor de elegir un nombre diferete. ", + "Could not rename \"{fileName}\"" : "No fue posible renombrar \"{fileName}\"", + "Could not create file \"{file}\"" : "No fue posible crear el archivo \"{file}\"", + "Could not create file \"{file}\" because it already exists" : "No fue posible crear el archivo\"{file}\" porque ya existe", + "Could not create folder \"{dir}\" because it already exists" : "No fue posible crear la carpeta \"{dir}\" porque ya existe", + "Error deleting file \"{fileName}\"." : "Se presentó un error al borrar el archivo \"{fileName}\".", + "No search results in other folders for {tag}{filter}{endtag}" : "No se encontraron resultados en otras carpetas para {tag}{filter}{endtag}", "Name" : "Nombre", "Size" : "Tamaño", "Modified" : "Modificado", "_%n folder_::_%n folders_" : ["%n carpeta","%n carpetas"], "_%n file_::_%n files_" : ["%n archivo","%n archivos"], "{dirs} and {files}" : "{dirs} y {files}", - "You don’t have permission to upload or create files here" : "No tienes permisos para subir o crear archivos aquí.", - "_Uploading %n file_::_Uploading %n files_" : ["Subiendo %n archivo","Subiendo %n archivos"], + "_including %n hidden_::_including %n hidden_" : ["incluyendo %n escondido","incluyendo %n escondidos"], + "You don’t have permission to upload or create files here" : "Usted no cuenta con los permisos para cargar o crear archivos aqui", + "_Uploading %n file_::_Uploading %n files_" : ["Subiendo %n archivo","Cargando %n archivos"], "New" : "Nuevo", + "\"{name}\" is an invalid file name." : "\"{name}\" es un nombre de archivo inválido. ", "File name cannot be empty." : "El nombre de archivo no puede estar vacío.", - "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}%)", + "\"{name}\" is not an allowed filetype" : "\"{name}\" es un tipo de archivo no permitido", + "Storage of {owner} is full, files can not be updated or synced anymore!" : "El espacio de {owner} está lleno. ¡Los archivos ya no se pueden actualizar o sincronizar!", + "Your storage is full, files can not be updated or synced anymore!" : "Su espacio está lleno. ¡Los archivos ya no se pueden actualizar o sincronizar!", + "Storage of {owner} is almost full ({usedSpacePercent}%)" : "El espacio de {owner} está casi lleno ({usedSpacePercent}%)", + "Your storage is almost full ({usedSpacePercent}%)" : "Su espacio está casi lleno ({usedSpacePercent}%)", + "_matches '{filter}'_::_match '{filter}'_" : ["coincide '{filter}'","coinciden '{filter}'"], + "View in folder" : "Ver en la carpeta", + "Path" : "Ruta", + "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"], + "Favorited" : "Marcado como favorito", "Favorite" : "Favorito", + "Copy local link" : "Copiar liga local", "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", + "New folder" : "Carpeta nueva", + "Upload" : "Cargar", + "An error occurred while trying to update the tags" : "Se presentó un error al intentar actualizar la etiqueta", + "Added to favorites" : "Agregado a los favoritos", + "Removed from favorites" : "Quitado de los favoritos", + "You added {file} to your favorites" : "Usted agregó {file} a sus favoritos", + "You removed {file} from your favorites" : "Usted quitó {file} de sus favoritos", + "File changes" : "Cambios al archivo", + "Created by {user}" : "Creado por {user}", + "Changed by {user}" : "Cambiado por {user}", + "Deleted by {user}" : "Borrado por {user}", + "Restored by {user}" : "Restaurado por {user}", + "Renamed by {user}" : "Renombrado por {user}", + "Moved by {user}" : "Movido por {user}", + "You created {file}" : "Usted creó {file}", + "{user} created {file}" : "{user} creó {file}", + "{file} was created in a public folder" : "{file} fue creado en una carpeta pública", + "You changed {file}" : "Usted cambió {file}", + "{user} changed {file}" : "{user} cambió {file}", + "You deleted {file}" : "Usted borró {file}", + "{user} deleted {file}" : "{user} borró {file}", + "You restored {file}" : "Usted restauró {file}", + "{user} restored {file}" : "{user} restauró {file}", + "You renamed {oldfile} to {newfile}" : "Usted renombró {oldfile} como {newfile}", + "{user} renamed {oldfile} to {newfile}" : "{user} renombró {oldfile} como {newfile}", + "You moved {oldfile} to {newfile}" : "Usted movió {oldfile} a {newfile}", + "{user} moved {oldfile} to {newfile}" : "{user} movió {oldfile} a {newfile}", + "A file has been added to or removed from your <strong>favorites</strong>" : "Un archivo ha sido agregado o eliminado de sus strong>favoritos</strong>", + "A file or folder has been <strong>changed</strong> or <strong>renamed</strong>" : "Un archivo o carpeta ha sido <strong>cambiado </strong> o <strong>renombrado</strong>", + "A new file or folder has been <strong>created</strong>" : "Un nuevo archivo ha sido <strong>creado</strong>", + "A new file or folder has been <strong>deleted</strong>" : "Un nuevo archivo ha sido <strong>borrado</strong>", + "Limit notifications about creation and changes to your <strong>favorite files</strong> <em>(Stream only)</em>" : "Limite las notificación de la creación y cambios a sus <strong>archivos favoritos</strong> <em>(solo flujo)</em>", + "A new file or folder has been <strong>restored</strong>" : "Un nuevo archivo ha sido <strong>restaurado</strong>", + "Upload (max. %s)" : "Cargar (max. %s)", "File handling" : "Administración de archivos", - "Maximum upload size" : "Tamaño máximo de subida", - "max. possible: " : "máx. posible:", + "Maximum upload size" : "Tamaño máximo de carga", + "max. possible: " : "max. posible:", "Save" : "Guardar", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "Con PHP-FPM podría tomar 5 minutos para que los cambios apliquen. ", + "Missing permissions to edit from here." : "Faltan privilegios para editar desde aquí. ", "Settings" : "Ajustes", + "Show hidden files" : "Mostrar archivos ocultos", "WebDAV" : "WebDAV", - "Upload too large" : "Subida demasido grande", - "The files you are trying to upload exceed the maximum size for file uploads on this server." : "Los archivos que estás intentando subir sobrepasan el tamaño máximo permitido en este servidor.", - "Text file" : "Archivo de texto" + "Use this address to <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">access your Files via WebDAV</a>" : "Use esta dirección para <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">acceder sus archivos vía WebDAV</a>", + "No files in here" : "No hay archivos aquí", + "Upload some content or sync with your devices!" : "¡Cargue algún contenido o sincronice con sus dispositivos!", + "No entries found in this folder" : "No se encontraron elementos en esta carpeta", + "Select all" : "Seleccionar todo", + "Upload too large" : "La carga es demasido grande", + "The files you are trying to upload exceed the maximum size for file uploads on this server." : "Los archivos que está intentando cargar sobrepasan el tamaño máximo permitido para la carga de archivos en este servidor.", + "No favorites" : "No hay favoritos", + "Files and folders you mark as favorite will show up here" : "Los archivos y carpetas que marque como favortios se mostrarán aquí. ", + "Shared with you" : "Compartido con usted", + "Shared with others" : "Compartido con otros", + "Shared by link" : "Compartido por liga", + "Deleted files" : "Archivos borrados", + "Text file" : "Archivo de texto", + "New text file.txt" : "Nuevo archivo de texto .txt", + "_{hours}:{minutes}:{seconds} hour left_::_{hours}:{minutes}:{seconds} hours left_" : ["falta {hours}:{minutes}:{seconds} hora","faltan {hours}:{minutes}:{seconds} horas"], + "{hours}:{minutes}h" : "{hours}:{minutes}h", + "_{minutes}:{seconds} minute left_::_{minutes}:{seconds} minutes left_" : ["falta {minutes}:{seconds} minuto","faltan {minutes}:{seconds} minutos"], + "{minutes}:{seconds}m" : "{minutes}:{seconds}m", + "_{seconds} second left_::_{seconds} seconds left_" : ["falta {seconds} segundo","faltan {seconds} segundos"], + "{seconds}s" : "{seconds}s", + "Any moment now..." : "En cualquier momento...", + "Soon..." : "Pronto...", + "File upload is in progress. Leaving the page now will cancel the upload." : "La carga del archivo está en curso. El salir de la página ahora, la cancelará. " }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/files/l10n/es_MX.json b/apps/files/l10n/es_MX.json index 76e66f1d612..d84f93c8172 100644 --- a/apps/files/l10n/es_MX.json +++ b/apps/files/l10n/es_MX.json @@ -1,62 +1,140 @@ { "translations": { - "Unknown error" : "Error desconocido", - "Unable to set upload directory." : "Incapaz de crear directorio de subida.", - "Invalid Token" : "Token Inválido", - "No file was uploaded. Unknown error" : "No se subió ningún archivo. Error desconocido", - "There is no error, the file uploaded with success" : "No hubo ningún problema, el archivo se subió con éxito", - "The uploaded file exceeds the upload_max_filesize directive in php.ini: " : "El archivo subido sobrepasa la directiva 'upload_max_filesize' en php.ini:", - "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "El archivo subido sobrepasa la directiva 'MAX_FILE_SIZE' especificada en el formulario HTML", - "The uploaded file was only partially uploaded" : "El archivo subido fue sólo subido parcialmente", - "No file was uploaded" : "No se subió ningún archivo", - "Missing a temporary folder" : "Falta la carpeta temporal", - "Failed to write to disk" : "Falló al escribir al disco", - "Not enough storage available" : "No hay suficiente espacio disponible", - "Upload failed. Could not find uploaded file" : "Actualización fallida. No se pudo encontrar el archivo subido", - "Upload failed. Could not get file info." : "Actualización fallida. No se pudo obtener información del archivo.", - "Invalid directory." : "Directorio inválido.", - "Files" : "Archivos", + "Storage is temporarily not available" : "El almacenamiento no está disponible temporalmente ", + "Storage invalid" : "El almacenamiento es inválido", + "Unknown error" : "Se presentó un error desconocido", + "All files" : "Todos los archivos", + "Recent" : "Reciente", + "File could not be found" : "No fue posible encontrar el archivo", "Home" : "Particular", "Close" : "Cerrar", "Favorites" : "Favoritos", - "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.", - "Uploading..." : "Subiendo...", - "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.", + "Could not create folder \"{dir}\"" : "No fue posible crear la carpeta \"{dir}\"", + "Upload cancelled." : "Carga cancelada.", + "Unable to upload {filename} as it is a directory or has 0 bytes" : "No fue posible cargar {filename} ya que es una carpeta o tiene un tamaño de 0 bytes", + "Not enough free space, you are uploading {size1} but only {size2} is left" : "No cuenta con suficiente espacio disponible, usted se encuentra cargando {size1} pero solo cuenta con {size2} disponible", + "Target folder \"{dir}\" does not exist any more" : "La carpeta destino \"{dir}\" ya no existe", + "Not enough free space" : "No cuenta con suficiente espacio disponible", + "Uploading..." : "Cargando...", + "..." : "...", + "{loadedSize} of {totalSize} ({bitrate})" : "{loadedSize} de {totalSize} ({bitrate})", "Actions" : "Acciones", "Download" : "Descargar", "Rename" : "Renombrar", - "Delete" : "Eliminar", + "Move" : "Mover", + "Target folder" : "Carpeta destino", + "Delete" : "Borrar", + "Disconnect storage" : "Desconectar almacenamiento", "Unshare" : "Dejar de compartir", + "Could not load info for file \"{file}\"" : "No fue posible cargar información para el archivo \"{file}\"", + "Files" : "Archivos", "Details" : "Detalles", + "Select" : "Seleccionar", "Pending" : "Pendiente", + "Unable to determine date" : "No fue posible determinar la fecha", + "This operation is forbidden" : "Esta operación está prohibida", + "This directory is unavailable, please check the logs or contact the administrator" : "Esta carpeta no está disponible, favor de verficiar las bitácoras o contacte al administrador", + "Could not move \"{file}\", target exists" : "No fue posible mover \"{file}\", el destino ya existe", + "Could not move \"{file}\"" : "No fue posible mover \"{file}\"", + "{newName} already exists" : "{newName} ya existe", + "Could not rename \"{fileName}\", it does not exist any more" : "No fue posible renombrar \"{fileName}\", ya no existe", + "The name \"{targetName}\" is already used in the folder \"{dir}\". Please choose a different name." : "El nombre \"{targetName}\" ya está en uso en la carpeta \"{dir}\". Favor de elegir un nombre diferete. ", + "Could not rename \"{fileName}\"" : "No fue posible renombrar \"{fileName}\"", + "Could not create file \"{file}\"" : "No fue posible crear el archivo \"{file}\"", + "Could not create file \"{file}\" because it already exists" : "No fue posible crear el archivo\"{file}\" porque ya existe", + "Could not create folder \"{dir}\" because it already exists" : "No fue posible crear la carpeta \"{dir}\" porque ya existe", + "Error deleting file \"{fileName}\"." : "Se presentó un error al borrar el archivo \"{fileName}\".", + "No search results in other folders for {tag}{filter}{endtag}" : "No se encontraron resultados en otras carpetas para {tag}{filter}{endtag}", "Name" : "Nombre", "Size" : "Tamaño", "Modified" : "Modificado", "_%n folder_::_%n folders_" : ["%n carpeta","%n carpetas"], "_%n file_::_%n files_" : ["%n archivo","%n archivos"], "{dirs} and {files}" : "{dirs} y {files}", - "You don’t have permission to upload or create files here" : "No tienes permisos para subir o crear archivos aquí.", - "_Uploading %n file_::_Uploading %n files_" : ["Subiendo %n archivo","Subiendo %n archivos"], + "_including %n hidden_::_including %n hidden_" : ["incluyendo %n escondido","incluyendo %n escondidos"], + "You don’t have permission to upload or create files here" : "Usted no cuenta con los permisos para cargar o crear archivos aqui", + "_Uploading %n file_::_Uploading %n files_" : ["Subiendo %n archivo","Cargando %n archivos"], "New" : "Nuevo", + "\"{name}\" is an invalid file name." : "\"{name}\" es un nombre de archivo inválido. ", "File name cannot be empty." : "El nombre de archivo no puede estar vacío.", - "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}%)", + "\"{name}\" is not an allowed filetype" : "\"{name}\" es un tipo de archivo no permitido", + "Storage of {owner} is full, files can not be updated or synced anymore!" : "El espacio de {owner} está lleno. ¡Los archivos ya no se pueden actualizar o sincronizar!", + "Your storage is full, files can not be updated or synced anymore!" : "Su espacio está lleno. ¡Los archivos ya no se pueden actualizar o sincronizar!", + "Storage of {owner} is almost full ({usedSpacePercent}%)" : "El espacio de {owner} está casi lleno ({usedSpacePercent}%)", + "Your storage is almost full ({usedSpacePercent}%)" : "Su espacio está casi lleno ({usedSpacePercent}%)", + "_matches '{filter}'_::_match '{filter}'_" : ["coincide '{filter}'","coinciden '{filter}'"], + "View in folder" : "Ver en la carpeta", + "Path" : "Ruta", + "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"], + "Favorited" : "Marcado como favorito", "Favorite" : "Favorito", + "Copy local link" : "Copiar liga local", "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", + "New folder" : "Carpeta nueva", + "Upload" : "Cargar", + "An error occurred while trying to update the tags" : "Se presentó un error al intentar actualizar la etiqueta", + "Added to favorites" : "Agregado a los favoritos", + "Removed from favorites" : "Quitado de los favoritos", + "You added {file} to your favorites" : "Usted agregó {file} a sus favoritos", + "You removed {file} from your favorites" : "Usted quitó {file} de sus favoritos", + "File changes" : "Cambios al archivo", + "Created by {user}" : "Creado por {user}", + "Changed by {user}" : "Cambiado por {user}", + "Deleted by {user}" : "Borrado por {user}", + "Restored by {user}" : "Restaurado por {user}", + "Renamed by {user}" : "Renombrado por {user}", + "Moved by {user}" : "Movido por {user}", + "You created {file}" : "Usted creó {file}", + "{user} created {file}" : "{user} creó {file}", + "{file} was created in a public folder" : "{file} fue creado en una carpeta pública", + "You changed {file}" : "Usted cambió {file}", + "{user} changed {file}" : "{user} cambió {file}", + "You deleted {file}" : "Usted borró {file}", + "{user} deleted {file}" : "{user} borró {file}", + "You restored {file}" : "Usted restauró {file}", + "{user} restored {file}" : "{user} restauró {file}", + "You renamed {oldfile} to {newfile}" : "Usted renombró {oldfile} como {newfile}", + "{user} renamed {oldfile} to {newfile}" : "{user} renombró {oldfile} como {newfile}", + "You moved {oldfile} to {newfile}" : "Usted movió {oldfile} a {newfile}", + "{user} moved {oldfile} to {newfile}" : "{user} movió {oldfile} a {newfile}", + "A file has been added to or removed from your <strong>favorites</strong>" : "Un archivo ha sido agregado o eliminado de sus strong>favoritos</strong>", + "A file or folder has been <strong>changed</strong> or <strong>renamed</strong>" : "Un archivo o carpeta ha sido <strong>cambiado </strong> o <strong>renombrado</strong>", + "A new file or folder has been <strong>created</strong>" : "Un nuevo archivo ha sido <strong>creado</strong>", + "A new file or folder has been <strong>deleted</strong>" : "Un nuevo archivo ha sido <strong>borrado</strong>", + "Limit notifications about creation and changes to your <strong>favorite files</strong> <em>(Stream only)</em>" : "Limite las notificación de la creación y cambios a sus <strong>archivos favoritos</strong> <em>(solo flujo)</em>", + "A new file or folder has been <strong>restored</strong>" : "Un nuevo archivo ha sido <strong>restaurado</strong>", + "Upload (max. %s)" : "Cargar (max. %s)", "File handling" : "Administración de archivos", - "Maximum upload size" : "Tamaño máximo de subida", - "max. possible: " : "máx. posible:", + "Maximum upload size" : "Tamaño máximo de carga", + "max. possible: " : "max. posible:", "Save" : "Guardar", + "With PHP-FPM it might take 5 minutes for changes to be applied." : "Con PHP-FPM podría tomar 5 minutos para que los cambios apliquen. ", + "Missing permissions to edit from here." : "Faltan privilegios para editar desde aquí. ", "Settings" : "Ajustes", + "Show hidden files" : "Mostrar archivos ocultos", "WebDAV" : "WebDAV", - "Upload too large" : "Subida demasido grande", - "The files you are trying to upload exceed the maximum size for file uploads on this server." : "Los archivos que estás intentando subir sobrepasan el tamaño máximo permitido en este servidor.", - "Text file" : "Archivo de texto" + "Use this address to <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">access your Files via WebDAV</a>" : "Use esta dirección para <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">acceder sus archivos vía WebDAV</a>", + "No files in here" : "No hay archivos aquí", + "Upload some content or sync with your devices!" : "¡Cargue algún contenido o sincronice con sus dispositivos!", + "No entries found in this folder" : "No se encontraron elementos en esta carpeta", + "Select all" : "Seleccionar todo", + "Upload too large" : "La carga es demasido grande", + "The files you are trying to upload exceed the maximum size for file uploads on this server." : "Los archivos que está intentando cargar sobrepasan el tamaño máximo permitido para la carga de archivos en este servidor.", + "No favorites" : "No hay favoritos", + "Files and folders you mark as favorite will show up here" : "Los archivos y carpetas que marque como favortios se mostrarán aquí. ", + "Shared with you" : "Compartido con usted", + "Shared with others" : "Compartido con otros", + "Shared by link" : "Compartido por liga", + "Deleted files" : "Archivos borrados", + "Text file" : "Archivo de texto", + "New text file.txt" : "Nuevo archivo de texto .txt", + "_{hours}:{minutes}:{seconds} hour left_::_{hours}:{minutes}:{seconds} hours left_" : ["falta {hours}:{minutes}:{seconds} hora","faltan {hours}:{minutes}:{seconds} horas"], + "{hours}:{minutes}h" : "{hours}:{minutes}h", + "_{minutes}:{seconds} minute left_::_{minutes}:{seconds} minutes left_" : ["falta {minutes}:{seconds} minuto","faltan {minutes}:{seconds} minutos"], + "{minutes}:{seconds}m" : "{minutes}:{seconds}m", + "_{seconds} second left_::_{seconds} seconds left_" : ["falta {seconds} segundo","faltan {seconds} segundos"], + "{seconds}s" : "{seconds}s", + "Any moment now..." : "En cualquier momento...", + "Soon..." : "Pronto...", + "File upload is in progress. Leaving the page now will cancel the upload." : "La carga del archivo está en curso. El salir de la página ahora, la cancelará. " },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/files_sharing/lib/Cache.php b/apps/files_sharing/lib/Cache.php index bc10ddbd94f..d7dcb426d85 100644 --- a/apps/files_sharing/lib/Cache.php +++ b/apps/files_sharing/lib/Cache.php @@ -51,6 +51,8 @@ class Cache extends CacheJail { private $ownerDisplayName; + private $numericId; + /** * @param \OCA\Files_Sharing\SharedStorage $storage * @param ICacheEntry $sourceRootInfo @@ -58,6 +60,7 @@ class Cache extends CacheJail { public function __construct($storage, ICacheEntry $sourceRootInfo) { $this->storage = $storage; $this->sourceRootInfo = $sourceRootInfo; + $this->numericId = $sourceRootInfo->getStorageId(); parent::__construct( null, $this->sourceRootInfo->getPath() diff --git a/apps/files_sharing/lib/SharedStorage.php b/apps/files_sharing/lib/SharedStorage.php index ddbc9b8a898..3293e095590 100644 --- a/apps/files_sharing/lib/SharedStorage.php +++ b/apps/files_sharing/lib/SharedStorage.php @@ -350,6 +350,11 @@ class SharedStorage extends \OC\Files\Storage\Wrapper\Jail implements ISharedSto return $this->superShare->getNodeType(); } + /** + * @param string $path + * @param null $storage + * @return Cache + */ public function getCache($path = '', $storage = null) { if ($this->cache) { return $this->cache; diff --git a/apps/files_sharing/tests/CacheTest.php b/apps/files_sharing/tests/CacheTest.php index ae0247a84e2..26ba5b21e46 100644 --- a/apps/files_sharing/tests/CacheTest.php +++ b/apps/files_sharing/tests/CacheTest.php @@ -30,6 +30,8 @@ namespace OCA\Files_Sharing\Tests; +use OCA\Files_Sharing\SharedStorage; + /** * Class CacheTest * @@ -525,4 +527,29 @@ class CacheTest extends TestCase { $this->assertEquals('', $sharedCache->getPathById($folderInfo->getId())); $this->assertEquals('bar/test.txt', $sharedCache->getPathById($fileInfo->getId())); } + + public function testNumericStorageId() { + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + \OC\Files\Filesystem::mkdir('foo'); + + $rootFolder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1); + $node = $rootFolder->get('foo'); + $share = $this->shareManager->newShare(); + $share->setNode($node) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setPermissions(\OCP\Constants::PERMISSION_ALL); + $this->shareManager->createShare($share); + \OC_Util::tearDownFS(); + + list($sourceStorage) = \OC\Files\Filesystem::resolvePath('/' . self::TEST_FILES_SHARING_API_USER1 . '/files/foo'); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + $this->assertTrue(\OC\Files\Filesystem::file_exists('/foo')); + /** @var SharedStorage $sharedStorage */ + list($sharedStorage) = \OC\Files\Filesystem::resolvePath('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/foo'); + + $this->assertEquals($sourceStorage->getCache()->getNumericStorageId(), $sharedStorage->getCache()->getNumericStorageId()); + } } diff --git a/apps/files_versions/css/versions.css b/apps/files_versions/css/versions.css index e749854a942..cd63a90ab51 100644 --- a/apps/files_versions/css/versions.css +++ b/apps/files_versions/css/versions.css @@ -68,7 +68,3 @@ float: right; margin-right: -10px; } - -.versionsTabView .emptycontent { - margin-top: 10px; -} diff --git a/apps/files_versions/js/versionstabview.js b/apps/files_versions/js/versionstabview.js index aa20d8fda7a..3a9026901ea 100644 --- a/apps/files_versions/js/versionstabview.js +++ b/apps/files_versions/js/versionstabview.js @@ -232,8 +232,8 @@ */ render: function() { this.$el.html(this.template({ - emptyResultLabel: t('files_versions', 'No versions available'), - moreVersionsLabel: t('files_versions', 'More versions...') + emptyResultLabel: t('files_versions', 'No earlier versions available'), + moreVersionsLabel: t('files_versions', 'More versions …') })); this.$el.find('.has-tooltip').tooltip(); this.$versionsContainer = this.$el.find('ul.versions'); diff --git a/apps/updatenotification/l10n/de.js b/apps/updatenotification/l10n/de.js index 1afa5bb10bd..ffa7af9e94a 100644 --- a/apps/updatenotification/l10n/de.js +++ b/apps/updatenotification/l10n/de.js @@ -5,8 +5,8 @@ OC.L10N.register( "Could not start updater, please try the manual update" : "Aktualisierungsfunktion konnte nicht gestartet werden, bitte versuche ein mauelles Update", "{version} is available. Get more information on how to update." : "{version} ist verfügbar. Weitere Informationen zur Aktualisierung.", "Channel updated" : "Kanal aktualisiert", - "The update server could not be reached since %d days to check for new updates." : "Der Update-Server konnte seit %d Tagen nicht erreicht werden.", - "Please check the nextcloud and server log files for errors." : "Bitte überprüfe das Nextclound- und das Server-Log auf Fehler.", + "The update server could not be reached since %d days to check for new updates." : "Der Aktualisierungsserver konnte seit %d Tagen nicht erreicht werden um auf verfügbare Aktualisierungen zu prüfen.", + "Please check the nextcloud and server log files for errors." : "Bitte prüfe das Nextcloud- und Server-Log nach Fehlern.", "Update to %1$s is available." : "Aktualisierung auf %1$s ist verfügbar.", "Update for %1$s to version %2$s is available." : "Ein Update von %1$s auf Version %2$s ist verfügbar.", "Update for {app} to version %s is available." : "Ein Update für {app} auf Version %s ist verfügbar.", diff --git a/apps/updatenotification/l10n/de.json b/apps/updatenotification/l10n/de.json index 6099804280d..70a89705cc4 100644 --- a/apps/updatenotification/l10n/de.json +++ b/apps/updatenotification/l10n/de.json @@ -3,8 +3,8 @@ "Could not start updater, please try the manual update" : "Aktualisierungsfunktion konnte nicht gestartet werden, bitte versuche ein mauelles Update", "{version} is available. Get more information on how to update." : "{version} ist verfügbar. Weitere Informationen zur Aktualisierung.", "Channel updated" : "Kanal aktualisiert", - "The update server could not be reached since %d days to check for new updates." : "Der Update-Server konnte seit %d Tagen nicht erreicht werden.", - "Please check the nextcloud and server log files for errors." : "Bitte überprüfe das Nextclound- und das Server-Log auf Fehler.", + "The update server could not be reached since %d days to check for new updates." : "Der Aktualisierungsserver konnte seit %d Tagen nicht erreicht werden um auf verfügbare Aktualisierungen zu prüfen.", + "Please check the nextcloud and server log files for errors." : "Bitte prüfe das Nextcloud- und Server-Log nach Fehlern.", "Update to %1$s is available." : "Aktualisierung auf %1$s ist verfügbar.", "Update for %1$s to version %2$s is available." : "Ein Update von %1$s auf Version %2$s ist verfügbar.", "Update for {app} to version %s is available." : "Ein Update für {app} auf Version %s ist verfügbar.", diff --git a/apps/updatenotification/l10n/de_DE.js b/apps/updatenotification/l10n/de_DE.js index 9f4ee0243df..5ddb1155ace 100644 --- a/apps/updatenotification/l10n/de_DE.js +++ b/apps/updatenotification/l10n/de_DE.js @@ -5,6 +5,8 @@ OC.L10N.register( "Could not start updater, please try the manual update" : "Der Updater konnte nicht gestartet werden, bitte versuchen Sie ein manuelles Update", "{version} is available. Get more information on how to update." : "{version} ist verfügbar. Weitere Informationen zur Aktualisierung.", "Channel updated" : "Kanal aktualisiert", + "The update server could not be reached since %d days to check for new updates." : "Der Aktualisierungsserver konnte seit %d Tagen nicht erreicht werden um auf verfügbare Aktualisierungen zu prüfen.", + "Please check the nextcloud and server log files for errors." : "Bitte prüfen Sie das Nextcloud- und Server-Log nach Fehlern.", "Update to %1$s is available." : "Aktualisierung auf %1$s ist verfügbar.", "Update for %1$s to version %2$s is available." : "Ein Update von %1$s auf Version %2$s ist verfügbar.", "Update for {app} to version %s is available." : "Ein Update für {app} auf Version %s ist verfügbar.", diff --git a/apps/updatenotification/l10n/de_DE.json b/apps/updatenotification/l10n/de_DE.json index 22c6151c4a1..436d26698a3 100644 --- a/apps/updatenotification/l10n/de_DE.json +++ b/apps/updatenotification/l10n/de_DE.json @@ -3,6 +3,8 @@ "Could not start updater, please try the manual update" : "Der Updater konnte nicht gestartet werden, bitte versuchen Sie ein manuelles Update", "{version} is available. Get more information on how to update." : "{version} ist verfügbar. Weitere Informationen zur Aktualisierung.", "Channel updated" : "Kanal aktualisiert", + "The update server could not be reached since %d days to check for new updates." : "Der Aktualisierungsserver konnte seit %d Tagen nicht erreicht werden um auf verfügbare Aktualisierungen zu prüfen.", + "Please check the nextcloud and server log files for errors." : "Bitte prüfen Sie das Nextcloud- und Server-Log nach Fehlern.", "Update to %1$s is available." : "Aktualisierung auf %1$s ist verfügbar.", "Update for %1$s to version %2$s is available." : "Ein Update von %1$s auf Version %2$s ist verfügbar.", "Update for {app} to version %s is available." : "Ein Update für {app} auf Version %s ist verfügbar.", diff --git a/apps/updatenotification/l10n/is.js b/apps/updatenotification/l10n/is.js index e2c54b82b13..94728d28a78 100644 --- a/apps/updatenotification/l10n/is.js +++ b/apps/updatenotification/l10n/is.js @@ -5,6 +5,8 @@ OC.L10N.register( "Could not start updater, please try the manual update" : "Gat ekki ræst uppfærslustýringu, prófaðu að uppfæra handvirkt", "{version} is available. Get more information on how to update." : "{version} er í boði. Fáðu frekari upplýsingar um hvernig á að uppfæra.", "Channel updated" : "Rás uppfærð", + "The update server could not be reached since %d days to check for new updates." : "Ekki hefur verið hægt að nálgast uppfærsluþjóninn í %d daga til að athuga með nýjar uppfærslur.", + "Please check the nextcloud and server log files for errors." : "Skoðaðu hvort einhver villuboð séu í annálaskrám Nextcloud þjónsins.", "Update to %1$s is available." : "Uppfærsla fyrir %1$s er tiltæk.", "Update for %1$s to version %2$s is available." : "Uppfærsla %1$s í útgáfu %2$s er tiltæk.", "Update for {app} to version %s is available." : "Uppfærsla fyrir {app} í útgáfu %s er tiltæk.", diff --git a/apps/updatenotification/l10n/is.json b/apps/updatenotification/l10n/is.json index 786b7b9beb9..81431629edd 100644 --- a/apps/updatenotification/l10n/is.json +++ b/apps/updatenotification/l10n/is.json @@ -3,6 +3,8 @@ "Could not start updater, please try the manual update" : "Gat ekki ræst uppfærslustýringu, prófaðu að uppfæra handvirkt", "{version} is available. Get more information on how to update." : "{version} er í boði. Fáðu frekari upplýsingar um hvernig á að uppfæra.", "Channel updated" : "Rás uppfærð", + "The update server could not be reached since %d days to check for new updates." : "Ekki hefur verið hægt að nálgast uppfærsluþjóninn í %d daga til að athuga með nýjar uppfærslur.", + "Please check the nextcloud and server log files for errors." : "Skoðaðu hvort einhver villuboð séu í annálaskrám Nextcloud þjónsins.", "Update to %1$s is available." : "Uppfærsla fyrir %1$s er tiltæk.", "Update for %1$s to version %2$s is available." : "Uppfærsla %1$s í útgáfu %2$s er tiltæk.", "Update for {app} to version %s is available." : "Uppfærsla fyrir {app} í útgáfu %s er tiltæk.", diff --git a/apps/updatenotification/l10n/pl.js b/apps/updatenotification/l10n/pl.js index 65f41099a75..145aa2884f1 100644 --- a/apps/updatenotification/l10n/pl.js +++ b/apps/updatenotification/l10n/pl.js @@ -5,6 +5,8 @@ OC.L10N.register( "Could not start updater, please try the manual update" : "Nie można uruchomić aktualizacji, spróbuj z aktualizować ręcznie", "{version} is available. Get more information on how to update." : "Wersja {version} jest dostępna. Dowiedz się jak zaktualizować.", "Channel updated" : "Zaktualizowany kanał", + "The update server could not be reached since %d days to check for new updates." : "Połączenie z serwerem z aktualizacjami w celu sprawdzenia nowych aktualizacji nie powiodło się od %d dni.", + "Please check the nextcloud and server log files for errors." : "Proszę sprawdzić błędy w plikach z logami nextclouda i serwera.", "Update to %1$s is available." : "Aktualizacja do %1$s jest dostępna.", "Update for %1$s to version %2$s is available." : "Jest dostępna aktualizacja dla %1$s do wersji %2$s", "Update for {app} to version %s is available." : "aktualizacja dla {app} do wersji %s jest dostępna.", diff --git a/apps/updatenotification/l10n/pl.json b/apps/updatenotification/l10n/pl.json index e41265d404b..f185349d93d 100644 --- a/apps/updatenotification/l10n/pl.json +++ b/apps/updatenotification/l10n/pl.json @@ -3,6 +3,8 @@ "Could not start updater, please try the manual update" : "Nie można uruchomić aktualizacji, spróbuj z aktualizować ręcznie", "{version} is available. Get more information on how to update." : "Wersja {version} jest dostępna. Dowiedz się jak zaktualizować.", "Channel updated" : "Zaktualizowany kanał", + "The update server could not be reached since %d days to check for new updates." : "Połączenie z serwerem z aktualizacjami w celu sprawdzenia nowych aktualizacji nie powiodło się od %d dni.", + "Please check the nextcloud and server log files for errors." : "Proszę sprawdzić błędy w plikach z logami nextclouda i serwera.", "Update to %1$s is available." : "Aktualizacja do %1$s jest dostępna.", "Update for %1$s to version %2$s is available." : "Jest dostępna aktualizacja dla %1$s do wersji %2$s", "Update for {app} to version %s is available." : "aktualizacja dla {app} do wersji %s jest dostępna.", diff --git a/apps/updatenotification/templates/admin.php b/apps/updatenotification/templates/admin.php index 78337eb313b..28a47992410 100644 --- a/apps/updatenotification/templates/admin.php +++ b/apps/updatenotification/templates/admin.php @@ -23,7 +23,7 @@ <a href="<?php p($_['downloadLink']); ?>" class="button<?php if ($_['updaterEnabled']) { p(' hidden'); } ?>"><?php p($l->t('Download now')) ?></a> <?php } ?> <?php } else { ?> - <strong><?php print_unescaped($l->t('Your version is up to date.')); ?></strong> + <strong><?php p($l->t('Your version is up to date.')); ?></strong> <span class="icon-info svg" title="<?php p($l->t('Checked on %s', [$lastCheckedDate])) ?>"></span> <?php } ?> diff --git a/apps/workflowengine/l10n/es_MX.js b/apps/workflowengine/l10n/es_MX.js new file mode 100644 index 00000000000..7d12d893af0 --- /dev/null +++ b/apps/workflowengine/l10n/es_MX.js @@ -0,0 +1,60 @@ +OC.L10N.register( + "workflowengine", + { + "Successfully saved" : "Guardado exitosamente", + "Saving failed:" : "Falla al guardar:", + "File mime type" : "Tipo mime del archivo", + "is" : "es", + "is not" : "no es", + "matches" : "coincide", + "does not match" : "No coincide", + "Example: {placeholder}" : "Ejemplo: {placeholder}", + "File size (upload)" : "Tamaño del archivo (carga)", + "less" : "menor", + "less or equals" : "menor o igual", + "greater or equals" : "mayor o igual", + "greater" : "mayor", + "Request remote address" : "Solicitar dirección remota", + "matches IPv4" : "coincide con IPv4", + "does not match IPv4" : "no coincide con IPv4", + "matches IPv6" : "coincide con IPv6", + "does not match IPv6" : "no coincide con IPv6", + "Request time" : "Solicitar tiempo", + "between" : "entre", + "not between" : "no entre", + "Start" : "Inicio", + "End" : "Fin", + "Select timezone…" : "Seleccionar zona horaria...", + "Request URL" : "Solicitar URL", + "Predefined URLs" : "URLs predefinidos", + "Request user agent" : "Solicitar agente de usuario", + "Sync clients" : "Sincronizar clientes", + "Android client" : "Cliente Android", + "iOS client" : "Cliente iOS", + "Desktop client" : "Cliente de escritorio", + "is member of" : "es miembro de", + "is not member of" : "no es miembro de", + "The given operator is invalid" : "El operador indicado es inválido", + "The given regular expression is invalid" : "La expresión regular indicada es inválida", + "The given file size is invalid" : "El tamaño de archivo indicado es inválido", + "The given IP range is invalid" : "El rango de IP's es inválido", + "The given IP range is not valid for IPv4" : "El rango de IPs dado no es válido para IPv4", + "The given IP range is not valid for IPv6" : "El rango de IPs dado no es válido para IPv6", + "The given start time is invalid" : "El tiempo inicial dado no es válido", + "The given end time is invalid" : "El tiempo final dado no es válido", + "The given group does not exist" : "El grupo dado no existe", + "Check %s is invalid or does not exist" : "La operación %s es inválida o no existe", + "Operation #%s does not exist" : "La operación #%s no existe", + "Operation %s does not exist" : "La operación %s no existe", + "Operation %s is invalid" : "La operación %s es inválida", + "Workflow" : "Flujo de trabajo", + "Open documentation" : "Abrir documentación", + "Add rule group" : "Agregar regla de grupo", + "Short rule description" : "Descripción corta de regla", + "Add rule" : "Agregar regla", + "Reset" : "Restablecer", + "Save" : "Guardar", + "Saving…" : "Guardando...", + "Loading…" : "Cargando..." +}, +"nplurals=2; plural=(n != 1);"); diff --git a/apps/workflowengine/l10n/es_MX.json b/apps/workflowengine/l10n/es_MX.json new file mode 100644 index 00000000000..c1dcb6091f2 --- /dev/null +++ b/apps/workflowengine/l10n/es_MX.json @@ -0,0 +1,58 @@ +{ "translations": { + "Successfully saved" : "Guardado exitosamente", + "Saving failed:" : "Falla al guardar:", + "File mime type" : "Tipo mime del archivo", + "is" : "es", + "is not" : "no es", + "matches" : "coincide", + "does not match" : "No coincide", + "Example: {placeholder}" : "Ejemplo: {placeholder}", + "File size (upload)" : "Tamaño del archivo (carga)", + "less" : "menor", + "less or equals" : "menor o igual", + "greater or equals" : "mayor o igual", + "greater" : "mayor", + "Request remote address" : "Solicitar dirección remota", + "matches IPv4" : "coincide con IPv4", + "does not match IPv4" : "no coincide con IPv4", + "matches IPv6" : "coincide con IPv6", + "does not match IPv6" : "no coincide con IPv6", + "Request time" : "Solicitar tiempo", + "between" : "entre", + "not between" : "no entre", + "Start" : "Inicio", + "End" : "Fin", + "Select timezone…" : "Seleccionar zona horaria...", + "Request URL" : "Solicitar URL", + "Predefined URLs" : "URLs predefinidos", + "Request user agent" : "Solicitar agente de usuario", + "Sync clients" : "Sincronizar clientes", + "Android client" : "Cliente Android", + "iOS client" : "Cliente iOS", + "Desktop client" : "Cliente de escritorio", + "is member of" : "es miembro de", + "is not member of" : "no es miembro de", + "The given operator is invalid" : "El operador indicado es inválido", + "The given regular expression is invalid" : "La expresión regular indicada es inválida", + "The given file size is invalid" : "El tamaño de archivo indicado es inválido", + "The given IP range is invalid" : "El rango de IP's es inválido", + "The given IP range is not valid for IPv4" : "El rango de IPs dado no es válido para IPv4", + "The given IP range is not valid for IPv6" : "El rango de IPs dado no es válido para IPv6", + "The given start time is invalid" : "El tiempo inicial dado no es válido", + "The given end time is invalid" : "El tiempo final dado no es válido", + "The given group does not exist" : "El grupo dado no existe", + "Check %s is invalid or does not exist" : "La operación %s es inválida o no existe", + "Operation #%s does not exist" : "La operación #%s no existe", + "Operation %s does not exist" : "La operación %s no existe", + "Operation %s is invalid" : "La operación %s es inválida", + "Workflow" : "Flujo de trabajo", + "Open documentation" : "Abrir documentación", + "Add rule group" : "Agregar regla de grupo", + "Short rule description" : "Descripción corta de regla", + "Add rule" : "Agregar regla", + "Reset" : "Restablecer", + "Save" : "Guardar", + "Saving…" : "Guardando...", + "Loading…" : "Cargando..." +},"pluralForm" :"nplurals=2; plural=(n != 1);" +}
\ No newline at end of file diff --git a/build/integration/features/external-storage.feature b/build/integration/features/external-storage.feature index da085d9e983..09ffdb29803 100644 --- a/build/integration/features/external-storage.feature +++ b/build/integration/features/external-storage.feature @@ -23,7 +23,6 @@ Feature: external-storage | token | A_TOKEN | | mimetype | httpd/unix-directory | - @local_storage Scenario: Shares dont overwrite external storages Given user "user0" exists And user "user1" exists @@ -40,3 +39,23 @@ Feature: external-storage And folder "/test" of user "user1" is shared with user "user0" And As an "user0" Then as "user0" the file "/test/textfile1.txt" does not exist + + Scenario: Move a file into storage works + Given user "user0" exists + And user "user1" exists + And As an "user0" + And user "user0" created a folder "/local_storage/foo1" + When User "user0" moved file "/textfile0.txt" to "/local_storage/foo1/textfile0.txt" + Then as "user1" the file "/local_storage/foo1/textfile0.txt" exists + And as "user0" the file "/local_storage/foo1/textfile0.txt" exists + + Scenario: Move a file out of the storage works + Given user "user0" exists + And user "user1" exists + And As an "user0" + And user "user0" created a folder "/local_storage/foo2" + And User "user0" moved file "/textfile0.txt" to "/local_storage/foo2/textfile0.txt" + When User "user1" moved file "/local_storage/foo2/textfile0.txt" to "/local.txt" + Then as "user1" the file "/local_storage/foo2/textfile0.txt" does not exist + And as "user0" the file "/local_storage/foo2/textfile0.txt" does not exist + And as "user1" the file "/local.txt" exists diff --git a/build/integration/features/sharing-v1-part2.feature b/build/integration/features/sharing-v1-part2.feature new file mode 100644 index 00000000000..284e5f9a94b --- /dev/null +++ b/build/integration/features/sharing-v1-part2.feature @@ -0,0 +1,717 @@ +Feature: sharing + Background: + Given using api version "1" + Given using old dav path + +# See sharing-v1.feature + + Scenario: getting all shares of a file with reshares + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And user "user3" exists + And file "textfile0.txt" of user "user0" is shared with user "user1" + And file "textfile0 (2).txt" of user "user1" is shared with user "user2" + And As an "user0" + When sending "GET" to "/apps/files_sharing/api/v1/shares?reshares=true&path=textfile0.txt" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And User "user1" should be included in the response + And User "user2" should be included in the response + And User "user3" should not be included in the response + + Scenario: Reshared files can be still accessed if a user in the middle removes it. + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And user "user3" exists + And file "textfile0.txt" of user "user0" is shared with user "user1" + And file "textfile0 (2).txt" of user "user1" is shared with user "user2" + And file "textfile0 (2).txt" of user "user2" is shared with user "user3" + And As an "user1" + When User "user1" deletes file "/textfile0 (2).txt" + And As an "user3" + And Downloading file "/textfile0 (2).txt" with range "bytes=1-8" + Then Downloaded content should be "extcloud" + + Scenario: getting share info of a share + Given user "user0" exists + And user "user1" exists + And file "textfile0.txt" of user "user0" is shared with user "user1" + And As an "user0" + When Getting info of last share + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And Share fields of last share match with + | id | A_NUMBER | + | item_type | file | + | item_source | A_NUMBER | + | share_type | 0 | + | share_with | user1 | + | file_source | A_NUMBER | + | file_target | /textfile0.txt | + | path | /textfile0.txt | + | permissions | 19 | + | stime | A_NUMBER | + | storage | A_NUMBER | + | mail_send | 0 | + | uid_owner | user0 | + | storage_id | home::user0 | + | file_parent | A_NUMBER | + | share_with_displayname | user1 | + | displayname_owner | user0 | + | mimetype | text/plain | + + Scenario: keep group permissions in sync + Given As an "admin" + Given user "user0" exists + And user "user1" exists + And group "group1" exists + And user "user1" belongs to group "group1" + And file "textfile0.txt" of user "user0" is shared with group "group1" + And User "user1" moved file "/textfile0.txt" to "/FOLDER/textfile0.txt" + And As an "user0" + When Updating last share with + | permissions | 1 | + And Getting info of last share + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And Share fields of last share match with + | id | A_NUMBER | + | item_type | file | + | item_source | A_NUMBER | + | share_type | 1 | + | file_source | A_NUMBER | + | file_target | /textfile0.txt | + | permissions | 1 | + | stime | A_NUMBER | + | storage | A_NUMBER | + | mail_send | 0 | + | uid_owner | user0 | + | storage_id | home::user0 | + | file_parent | A_NUMBER | + | displayname_owner | user0 | + | mimetype | text/plain | + + Scenario: Sharee can see the share + Given user "user0" exists + And user "user1" exists + And file "textfile0.txt" of user "user0" is shared with user "user1" + And As an "user1" + When sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=true" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And last share_id is included in the answer + + Scenario: Sharee can see the filtered share + Given user "user0" exists + And user "user1" exists + And file "textfile0.txt" of user "user0" is shared with user "user1" + And file "textfile1.txt" of user "user0" is shared with user "user1" + And As an "user1" + When sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=true&path=textfile1 (2).txt" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And last share_id is included in the answer + + Scenario: Sharee can't see the share that is filtered out + Given user "user0" exists + And user "user1" exists + And file "textfile0.txt" of user "user0" is shared with user "user1" + And file "textfile1.txt" of user "user0" is shared with user "user1" + And As an "user1" + When sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=true&path=textfile0 (2).txt" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And last share_id is not included in the answer + + Scenario: Sharee can see the group share + Given As an "admin" + And user "user0" exists + And user "user1" exists + And group "group0" exists + And user "user1" belongs to group "group0" + And file "textfile0.txt" of user "user0" is shared with group "group0" + And As an "user1" + When sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=true" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And last share_id is included in the answer + + Scenario: User is not allowed to reshare file + As an "admin" + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And As an "user0" + And creating a share with + | path | /textfile0.txt | + | shareType | 0 | + | shareWith | user1 | + | permissions | 8 | + And As an "user1" + When creating a share with + | path | /textfile0 (2).txt | + | shareType | 0 | + | shareWith | user2 | + | permissions | 31 | + Then the OCS status code should be "404" + And the HTTP status code should be "200" + + Scenario: User is not allowed to reshare file with more permissions + As an "admin" + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And As an "user0" + And creating a share with + | path | /textfile0.txt | + | shareType | 0 | + | shareWith | user1 | + | permissions | 16 | + And As an "user1" + When creating a share with + | path | /textfile0 (2).txt | + | shareType | 0 | + | shareWith | user2 | + | permissions | 31 | + Then the OCS status code should be "404" + And the HTTP status code should be "200" + + Scenario: Get a share with a user which didn't received the share + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And file "textfile0.txt" of user "user0" is shared with user "user1" + And As an "user2" + When Getting info of last share + Then the OCS status code should be "404" + And the HTTP status code should be "200" + + Scenario: Share of folder and sub-folder to same user - core#20645 + Given As an "admin" + And user "user0" exists + And user "user1" exists + And group "group0" exists + And user "user1" belongs to group "group0" + And file "/PARENT" of user "user0" is shared with user "user1" + When file "/PARENT/CHILD" of user "user0" is shared with group "group0" + Then user "user1" should see following elements + | /FOLDER/ | + | /PARENT/ | + | /CHILD/ | + | /PARENT/parent.txt | + | /CHILD/child.txt | + And the HTTP status code should be "200" + + Scenario: Share a file by multiple channels + Given As an "admin" + And user "user0" exists + And user "user1" exists + And user "user2" exists + And group "group0" exists + And user "user1" belongs to group "group0" + And user "user2" belongs to group "group0" + And user "user0" created a folder "/common" + And user "user0" created a folder "/common/sub" + And file "common" of user "user0" is shared with group "group0" + And file "textfile0.txt" of user "user1" is shared with user "user2" + And User "user1" moved file "/textfile0.txt" to "/common/textfile0.txt" + And User "user1" moved file "/common/textfile0.txt" to "/common/sub/textfile0.txt" + And As an "user2" + When Downloading file "/common/sub/textfile0.txt" with range "bytes=10-18" + Then Downloaded content should be "test text" + And Downloaded content when downloading file "/textfile0.txt" with range "bytes=10-18" should be "test text" + And user "user2" should see following elements + | /common/sub/textfile0.txt | + + Scenario: Share a file by multiple channels + Given As an "admin" + And user "user0" exists + And user "user1" exists + And user "user2" exists + And group "group0" exists + And user "user1" belongs to group "group0" + And user "user2" belongs to group "group0" + And user "user0" created a folder "/common" + And user "user0" created a folder "/common/sub" + And file "common" of user "user0" is shared with group "group0" + And file "textfile0.txt" of user "user1" is shared with user "user2" + And User "user1" moved file "/textfile0.txt" to "/common/textfile0.txt" + And User "user1" moved file "/common/textfile0.txt" to "/common/sub/textfile0.txt" + And As an "user2" + When Downloading file "/textfile0.txt" with range "bytes=10-18" + Then Downloaded content should be "test text" + And user "user2" should see following elements + | /common/sub/textfile0.txt | + + Scenario: Delete all group shares + Given As an "admin" + And user "user0" exists + And user "user1" exists + And group "group1" exists + And user "user1" belongs to group "group1" + And file "textfile0.txt" of user "user0" is shared with group "group1" + And User "user1" moved file "/textfile0.txt" to "/FOLDER/textfile0.txt" + And As an "user0" + And Deleting last share + And As an "user1" + When sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=true" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And last share_id is not included in the answer + + Scenario: delete a share + Given user "user0" exists + And user "user1" exists + And file "textfile0.txt" of user "user0" is shared with user "user1" + And As an "user0" + When Deleting last share + Then the OCS status code should be "100" + And the HTTP status code should be "200" + + Scenario: Keep usergroup shares (#22143) + Given As an "admin" + And user "user0" exists + And user "user1" exists + And user "user2" exists + And group "group" exists + And user "user1" belongs to group "group" + And user "user2" belongs to group "group" + And user "user0" created a folder "/TMP" + And file "TMP" of user "user0" is shared with group "group" + And user "user1" created a folder "/myFOLDER" + And User "user1" moves file "/TMP" to "/myFOLDER/myTMP" + And user "user2" does not exist + And user "user1" should see following elements + | /myFOLDER/myTMP/ | + + Scenario: Check quota of owners parent directory of a shared file + Given using old dav path + And As an "admin" + And user "user0" exists + And user "user1" exists + And user "user1" has a quota of "0" + And User "user0" moved file "/welcome.txt" to "/myfile.txt" + And file "myfile.txt" of user "user0" is shared with user "user1" + When User "user1" uploads file "data/textfile.txt" to "/myfile.txt" + Then the HTTP status code should be "204" + + Scenario: Don't allow sharing of the root + Given user "user0" exists + And As an "user0" + When creating a share with + | path | / | + | shareType | 3 | + Then the OCS status code should be "403" + + Scenario: Allow modification of reshare + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And user "user0" created a folder "/TMP" + And file "TMP" of user "user0" is shared with user "user1" + And file "TMP" of user "user1" is shared with user "user2" + And As an "user1" + When Updating last share with + | permissions | 1 | + Then the OCS status code should be "100" + + Scenario: Do not allow reshare to exceed permissions + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And user "user0" created a folder "/TMP" + And As an "user0" + And creating a share with + | path | /TMP | + | shareType | 0 | + | shareWith | user1 | + | permissions | 21 | + And As an "user1" + And creating a share with + | path | /TMP | + | shareType | 0 | + | shareWith | user2 | + | permissions | 21 | + When Updating last share with + | permissions | 31 | + Then the OCS status code should be "404" + + Scenario: Only allow 1 link share per file/folder + Given user "user0" exists + And As an "user0" + And creating a share with + | path | welcome.txt | + | shareType | 3 | + When save last share id + And creating a share with + | path | welcome.txt | + | shareType | 3 | + Then share ids should match + + Scenario: Correct webdav share-permissions for owned file + Given user "user0" exists + And User "user0" uploads file with content "foo" to "/tmp.txt" + When as "user0" gets properties of folder "/tmp.txt" with + |{http://open-collaboration-services.org/ns}share-permissions | + Then the single response should contain a property "{http://open-collaboration-services.org/ns}share-permissions" with value "19" + + Scenario: Correct webdav share-permissions for received file with edit and reshare permissions + Given user "user0" exists + And user "user1" exists + And User "user0" uploads file with content "foo" to "/tmp.txt" + And file "/tmp.txt" of user "user0" is shared with user "user1" + When as "user1" gets properties of folder "/tmp.txt" with + |{http://open-collaboration-services.org/ns}share-permissions | + Then the single response should contain a property "{http://open-collaboration-services.org/ns}share-permissions" with value "19" + + Scenario: Correct webdav share-permissions for received file with edit permissions but no reshare permissions + Given user "user0" exists + And user "user1" exists + And User "user0" uploads file with content "foo" to "/tmp.txt" + And file "tmp.txt" of user "user0" is shared with user "user1" + And As an "user0" + And Updating last share with + | permissions | 3 | + When as "user1" gets properties of folder "/tmp.txt" with + |{http://open-collaboration-services.org/ns}share-permissions | + Then the single response should contain a property "{http://open-collaboration-services.org/ns}share-permissions" with value "3" + + Scenario: Correct webdav share-permissions for received file with reshare permissions but no edit permissions + Given user "user0" exists + And user "user1" exists + And User "user0" uploads file with content "foo" to "/tmp.txt" + And file "tmp.txt" of user "user0" is shared with user "user1" + And As an "user0" + And Updating last share with + | permissions | 17 | + When as "user1" gets properties of folder "/tmp.txt" with + |{http://open-collaboration-services.org/ns}share-permissions | + Then the single response should contain a property "{http://open-collaboration-services.org/ns}share-permissions" with value "17" + + Scenario: Correct webdav share-permissions for owned folder + Given user "user0" exists + And user "user0" created a folder "/tmp" + When as "user0" gets properties of folder "/" with + |{http://open-collaboration-services.org/ns}share-permissions | + Then the single response should contain a property "{http://open-collaboration-services.org/ns}share-permissions" with value "31" + + Scenario: Correct webdav share-permissions for received folder with all permissions + Given user "user0" exists + And user "user1" exists + And user "user0" created a folder "/tmp" + And file "/tmp" of user "user0" is shared with user "user1" + When as "user1" gets properties of folder "/tmp" with + |{http://open-collaboration-services.org/ns}share-permissions | + Then the single response should contain a property "{http://open-collaboration-services.org/ns}share-permissions" with value "31" + + Scenario: Correct webdav share-permissions for received folder with all permissions but edit + Given user "user0" exists + And user "user1" exists + And user "user0" created a folder "/tmp" + And file "/tmp" of user "user0" is shared with user "user1" + And As an "user0" + And Updating last share with + | permissions | 29 | + When as "user1" gets properties of folder "/tmp" with + |{http://open-collaboration-services.org/ns}share-permissions | + Then the single response should contain a property "{http://open-collaboration-services.org/ns}share-permissions" with value "29" + + Scenario: Correct webdav share-permissions for received folder with all permissions but create + Given user "user0" exists + And user "user1" exists + And user "user0" created a folder "/tmp" + And file "/tmp" of user "user0" is shared with user "user1" + And As an "user0" + And Updating last share with + | permissions | 27 | + When as "user1" gets properties of folder "/tmp" with + |{http://open-collaboration-services.org/ns}share-permissions | + Then the single response should contain a property "{http://open-collaboration-services.org/ns}share-permissions" with value "27" + + Scenario: Correct webdav share-permissions for received folder with all permissions but delete + Given user "user0" exists + And user "user1" exists + And user "user0" created a folder "/tmp" + And file "/tmp" of user "user0" is shared with user "user1" + And As an "user0" + And Updating last share with + | permissions | 23 | + When as "user1" gets properties of folder "/tmp" with + |{http://open-collaboration-services.org/ns}share-permissions | + Then the single response should contain a property "{http://open-collaboration-services.org/ns}share-permissions" with value "23" + + Scenario: Correct webdav share-permissions for received folder with all permissions but share + Given user "user0" exists + And user "user1" exists + And user "user0" created a folder "/tmp" + And file "/tmp" of user "user0" is shared with user "user1" + And As an "user0" + And Updating last share with + | permissions | 15 | + When as "user1" gets properties of folder "/tmp" with + |{http://open-collaboration-services.org/ns}share-permissions | + Then the single response should contain a property "{http://open-collaboration-services.org/ns}share-permissions" with value "15" + + Scenario: unique target names for incoming shares + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And user "user0" created a folder "/foo" + And user "user1" created a folder "/foo" + When file "/foo" of user "user0" is shared with user "user2" + And file "/foo" of user "user1" is shared with user "user2" + Then user "user2" should see following elements + | /foo/ | + | /foo%20(2)/ | + + Scenario: Creating a new share with a disabled user + Given As an "admin" + And user "user0" exists + And user "user1" exists + And assure user "user0" is disabled + And As an "user0" + When sending "POST" to "/apps/files_sharing/api/v1/shares" with + | path | welcome.txt | + | shareWith | user1 | + | shareType | 0 | + Then the OCS status code should be "997" + And the HTTP status code should be "401" + + Scenario: Deleting a group share as user + Given As an "admin" + And user "user0" exists + And user "user1" exists + And group "group1" exists + And user "user1" belongs to group "group1" + And As an "user0" + And creating a share with + | path | welcome.txt | + | shareType | 1 | + | shareWith | group1 | + When As an "user1" + And Deleting last share + Then the OCS status code should be "100" + And the HTTP status code should be "200" + + Scenario: Merging shares for recipient when shared from outside with group and member + Given using old dav path + And As an "admin" + And user "user0" exists + And user "user1" exists + And group "group1" exists + And user "user1" belongs to group "group1" + And user "user0" created a folder "/merge-test-outside" + When folder "/merge-test-outside" of user "user0" is shared with group "group1" + And folder "/merge-test-outside" of user "user0" is shared with user "user1" + Then as "user1" the folder "/merge-test-outside" exists + And as "user1" the folder "/merge-test-outside (2)" does not exist + + Scenario: Merging shares for recipient when shared from outside with group and member with different permissions + Given As an "admin" + And user "user0" exists + And user "user1" exists + And group "group1" exists + And user "user1" belongs to group "group1" + And user "user0" created a folder "/merge-test-outside-perms" + When folder "/merge-test-outside-perms" of user "user0" is shared with group "group1" with permissions 1 + And folder "/merge-test-outside-perms" of user "user0" is shared with user "user1" with permissions 31 + Then as "user1" gets properties of folder "/merge-test-outside-perms" with + |{http://owncloud.org/ns}permissions| + And the single response should contain a property "{http://owncloud.org/ns}permissions" with value "SRDNVCK" + And as "user1" the folder "/merge-test-outside-perms (2)" does not exist + + Scenario: Merging shares for recipient when shared from outside with two groups + Given As an "admin" + And user "user0" exists + And user "user1" exists + And group "group1" exists + And group "group2" exists + And user "user1" belongs to group "group1" + And user "user1" belongs to group "group2" + And user "user0" created a folder "/merge-test-outside-twogroups" + When folder "/merge-test-outside-twogroups" of user "user0" is shared with group "group1" + And folder "/merge-test-outside-twogroups" of user "user0" is shared with group "group2" + Then as "user1" the folder "/merge-test-outside-twogroups" exists + And as "user1" the folder "/merge-test-outside-twogroups (2)" does not exist + + Scenario: Merging shares for recipient when shared from outside with two groups with different permissions + Given As an "admin" + And user "user0" exists + And user "user1" exists + And group "group1" exists + And group "group2" exists + And user "user1" belongs to group "group1" + And user "user1" belongs to group "group2" + And user "user0" created a folder "/merge-test-outside-twogroups-perms" + When folder "/merge-test-outside-twogroups-perms" of user "user0" is shared with group "group1" with permissions 1 + And folder "/merge-test-outside-twogroups-perms" of user "user0" is shared with group "group2" with permissions 31 + Then as "user1" gets properties of folder "/merge-test-outside-twogroups-perms" with + |{http://owncloud.org/ns}permissions| + And the single response should contain a property "{http://owncloud.org/ns}permissions" with value "SRDNVCK" + And as "user1" the folder "/merge-test-outside-twogroups-perms (2)" does not exist + + Scenario: Merging shares for recipient when shared from outside with two groups and member + Given As an "admin" + And user "user0" exists + And user "user1" exists + And group "group1" exists + And group "group2" exists + And user "user1" belongs to group "group1" + And user "user1" belongs to group "group2" + And user "user0" created a folder "/merge-test-outside-twogroups-member-perms" + When folder "/merge-test-outside-twogroups-member-perms" of user "user0" is shared with group "group1" with permissions 1 + And folder "/merge-test-outside-twogroups-member-perms" of user "user0" is shared with group "group2" with permissions 31 + And folder "/merge-test-outside-twogroups-member-perms" of user "user0" is shared with user "user1" with permissions 1 + Then as "user1" gets properties of folder "/merge-test-outside-twogroups-member-perms" with + |{http://owncloud.org/ns}permissions| + And the single response should contain a property "{http://owncloud.org/ns}permissions" with value "SRDNVCK" + And as "user1" the folder "/merge-test-outside-twogroups-member-perms (2)" does not exist + + Scenario: Merging shares for recipient when shared from inside with group + Given As an "admin" + And user "user0" exists + And group "group1" exists + And user "user0" belongs to group "group1" + And user "user0" created a folder "/merge-test-inside-group" + When folder "/merge-test-inside-group" of user "user0" is shared with group "group1" + Then as "user0" the folder "/merge-test-inside-group" exists + And as "user0" the folder "/merge-test-inside-group (2)" does not exist + + Scenario: Merging shares for recipient when shared from inside with two groups + Given As an "admin" + And user "user0" exists + And group "group1" exists + And group "group2" exists + And user "user0" belongs to group "group1" + And user "user0" belongs to group "group2" + And user "user0" created a folder "/merge-test-inside-twogroups" + When folder "/merge-test-inside-twogroups" of user "user0" is shared with group "group1" + And folder "/merge-test-inside-twogroups" of user "user0" is shared with group "group2" + Then as "user0" the folder "/merge-test-inside-twogroups" exists + And as "user0" the folder "/merge-test-inside-twogroups (2)" does not exist + And as "user0" the folder "/merge-test-inside-twogroups (3)" does not exist + + Scenario: Merging shares for recipient when shared from inside with group with less permissions + Given As an "admin" + And user "user0" exists + And group "group1" exists + And group "group2" exists + And user "user0" belongs to group "group1" + And user "user0" belongs to group "group2" + And user "user0" created a folder "/merge-test-inside-twogroups-perms" + When folder "/merge-test-inside-twogroups-perms" of user "user0" is shared with group "group1" + And folder "/merge-test-inside-twogroups-perms" of user "user0" is shared with group "group2" + Then as "user0" gets properties of folder "/merge-test-inside-twogroups-perms" with + |{http://owncloud.org/ns}permissions| + And the single response should contain a property "{http://owncloud.org/ns}permissions" with value "RDNVCK" + And as "user0" the folder "/merge-test-inside-twogroups-perms (2)" does not exist + And as "user0" the folder "/merge-test-inside-twogroups-perms (3)" does not exist + + Scenario: Merging shares for recipient when shared from outside with group then user and recipient renames in between + Given As an "admin" + And user "user0" exists + And user "user1" exists + And group "group1" exists + And user "user1" belongs to group "group1" + And user "user0" created a folder "/merge-test-outside-groups-renamebeforesecondshare" + When folder "/merge-test-outside-groups-renamebeforesecondshare" of user "user0" is shared with group "group1" + And User "user1" moved folder "/merge-test-outside-groups-renamebeforesecondshare" to "/merge-test-outside-groups-renamebeforesecondshare-renamed" + And Sleep for "1" seconds + And folder "/merge-test-outside-groups-renamebeforesecondshare" of user "user0" is shared with user "user1" + Then as "user1" gets properties of folder "/merge-test-outside-groups-renamebeforesecondshare-renamed" with + |{http://owncloud.org/ns}permissions| + And the single response should contain a property "{http://owncloud.org/ns}permissions" with value "SRDNVCK" + And as "user1" the folder "/merge-test-outside-groups-renamebeforesecondshare" does not exist + + Scenario: Merging shares for recipient when shared from outside with user then group and recipient renames in between + Given using old dav path + Given As an "admin" + And user "user0" exists + And user "user1" exists + And group "group1" exists + And user "user1" belongs to group "group1" + And user "user0" created a folder "/merge-test-outside-groups-renamebeforesecondshare" + When folder "/merge-test-outside-groups-renamebeforesecondshare" of user "user0" is shared with user "user1" + And User "user1" moved folder "/merge-test-outside-groups-renamebeforesecondshare" to "/merge-test-outside-groups-renamebeforesecondshare-renamed" + And Sleep for "1" seconds + And folder "/merge-test-outside-groups-renamebeforesecondshare" of user "user0" is shared with group "group1" + Then as "user1" gets properties of folder "/merge-test-outside-groups-renamebeforesecondshare-renamed" with + |{http://owncloud.org/ns}permissions| + And the single response should contain a property "{http://owncloud.org/ns}permissions" with value "SRDNVCK" + And as "user1" the folder "/merge-test-outside-groups-renamebeforesecondshare" does not exist + + Scenario: Empting trashbin + Given As an "admin" + And user "user0" exists + And User "user0" deletes file "/textfile0.txt" + When User "user0" empties trashbin + Then the HTTP status code should be "200" + + Scenario: orphaned shares + Given As an "admin" + And user "user0" exists + And user "user1" exists + And user "user0" created a folder "/common" + And user "user0" created a folder "/common/sub" + And file "/common/sub" of user "user0" is shared with user "user1" + And User "user0" deletes folder "/common" + When User "user0" empties trashbin + Then as "user1" the folder "/sub" does not exist + + Scenario: sharing again an own file while belonging to a group + Given As an "admin" + Given user "user0" exists + And group "sharing-group" exists + And user "user0" belongs to group "sharing-group" + And file "welcome.txt" of user "user0" is shared with group "sharing-group" + And Deleting last share + When sending "POST" to "/apps/files_sharing/api/v1/shares" with + | path | welcome.txt | + | shareWith | sharing-group | + | shareType | 1 | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + + Scenario: unshare from self + Given As an "admin" + And user "user0" exists + And user "user1" exists + And group "sharing-group" exists + And user "user0" belongs to group "sharing-group" + And user "user1" belongs to group "sharing-group" + And file "/PARENT/parent.txt" of user "user0" is shared with group "sharing-group" + And user "user0" stores etag of element "/PARENT" + And user "user1" stores etag of element "/" + And As an "user1" + When Deleting last share + Then etag of element "/" of user "user1" has changed + And etag of element "/PARENT" of user "user0" has not changed + + Scenario: do not allow to increase link share permissions on reshare + Given As an "admin" + And user "admin" created a folder "/TMP" + And user "user0" exists + And creating a share with + | path | TMP | + | shareType | 0 | + | shareWith | user0 | + | permissions | 17 | + When As an "user0" + And creating a share with + | path | TMP | + | shareType | 3 | + And Updating last share with + | publicUpload | true | + Then the OCS status code should be "404" + + Scenario: moving a file into a share as recipient + Given As an "admin" + And user "user0" exists + And user "user1" exists + And user "user0" created a folder "/shared" + And folder "/shared" of user "user0" is shared with user "user1" + When User "user1" moved file "/textfile0.txt" to "/shared/shared_file.txt" + Then as "user1" the file "/shared/shared_file.txt" exists + And as "user0" the file "/shared/shared_file.txt" exists
\ No newline at end of file diff --git a/build/integration/features/sharing-v1.feature b/build/integration/features/sharing-v1.feature index 4ce32654ba4..5708b7115e4 100644 --- a/build/integration/features/sharing-v1.feature +++ b/build/integration/features/sharing-v1.feature @@ -14,7 +14,7 @@ Feature: sharing Then the OCS status code should be "100" And the HTTP status code should be "200" And The following headers should be set - | Content-Security-Policy | default-src 'none';base-uri 'none' | + | Content-Security-Policy | default-src 'none';base-uri 'none';manifest-src 'self' | Scenario: Creating a share with a group Given user "user0" exists @@ -288,703 +288,4 @@ Feature: sharing And User "user2" should be included in the response And User "user3" should not be included in the response - Scenario: getting all shares of a file with reshares - Given user "user0" exists - And user "user1" exists - And user "user2" exists - And user "user3" exists - And file "textfile0.txt" of user "user0" is shared with user "user1" - And file "textfile0 (2).txt" of user "user1" is shared with user "user2" - And As an "user0" - When sending "GET" to "/apps/files_sharing/api/v1/shares?reshares=true&path=textfile0.txt" - Then the OCS status code should be "100" - And the HTTP status code should be "200" - And User "user1" should be included in the response - And User "user2" should be included in the response - And User "user3" should not be included in the response - - Scenario: Reshared files can be still accessed if a user in the middle removes it. - Given user "user0" exists - And user "user1" exists - And user "user2" exists - And user "user3" exists - And file "textfile0.txt" of user "user0" is shared with user "user1" - And file "textfile0 (2).txt" of user "user1" is shared with user "user2" - And file "textfile0 (2).txt" of user "user2" is shared with user "user3" - And As an "user1" - When User "user1" deletes file "/textfile0 (2).txt" - And As an "user3" - And Downloading file "/textfile0 (2).txt" with range "bytes=1-8" - Then Downloaded content should be "extcloud" - - Scenario: getting share info of a share - Given user "user0" exists - And user "user1" exists - And file "textfile0.txt" of user "user0" is shared with user "user1" - And As an "user0" - When Getting info of last share - Then the OCS status code should be "100" - And the HTTP status code should be "200" - And Share fields of last share match with - | id | A_NUMBER | - | item_type | file | - | item_source | A_NUMBER | - | share_type | 0 | - | share_with | user1 | - | file_source | A_NUMBER | - | file_target | /textfile0.txt | - | path | /textfile0.txt | - | permissions | 19 | - | stime | A_NUMBER | - | storage | A_NUMBER | - | mail_send | 0 | - | uid_owner | user0 | - | storage_id | home::user0 | - | file_parent | A_NUMBER | - | share_with_displayname | user1 | - | displayname_owner | user0 | - | mimetype | text/plain | - - Scenario: keep group permissions in sync - Given As an "admin" - Given user "user0" exists - And user "user1" exists - And group "group1" exists - And user "user1" belongs to group "group1" - And file "textfile0.txt" of user "user0" is shared with group "group1" - And User "user1" moved file "/textfile0.txt" to "/FOLDER/textfile0.txt" - And As an "user0" - When Updating last share with - | permissions | 1 | - And Getting info of last share - Then the OCS status code should be "100" - And the HTTP status code should be "200" - And Share fields of last share match with - | id | A_NUMBER | - | item_type | file | - | item_source | A_NUMBER | - | share_type | 1 | - | file_source | A_NUMBER | - | file_target | /textfile0.txt | - | permissions | 1 | - | stime | A_NUMBER | - | storage | A_NUMBER | - | mail_send | 0 | - | uid_owner | user0 | - | storage_id | home::user0 | - | file_parent | A_NUMBER | - | displayname_owner | user0 | - | mimetype | text/plain | - - Scenario: Sharee can see the share - Given user "user0" exists - And user "user1" exists - And file "textfile0.txt" of user "user0" is shared with user "user1" - And As an "user1" - When sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=true" - Then the OCS status code should be "100" - And the HTTP status code should be "200" - And last share_id is included in the answer - - Scenario: Sharee can see the filtered share - Given user "user0" exists - And user "user1" exists - And file "textfile0.txt" of user "user0" is shared with user "user1" - And file "textfile1.txt" of user "user0" is shared with user "user1" - And As an "user1" - When sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=true&path=textfile1 (2).txt" - Then the OCS status code should be "100" - And the HTTP status code should be "200" - And last share_id is included in the answer - - Scenario: Sharee can't see the share that is filtered out - Given user "user0" exists - And user "user1" exists - And file "textfile0.txt" of user "user0" is shared with user "user1" - And file "textfile1.txt" of user "user0" is shared with user "user1" - And As an "user1" - When sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=true&path=textfile0 (2).txt" - Then the OCS status code should be "100" - And the HTTP status code should be "200" - And last share_id is not included in the answer - - Scenario: Sharee can see the group share - Given As an "admin" - And user "user0" exists - And user "user1" exists - And group "group0" exists - And user "user1" belongs to group "group0" - And file "textfile0.txt" of user "user0" is shared with group "group0" - And As an "user1" - When sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=true" - Then the OCS status code should be "100" - And the HTTP status code should be "200" - And last share_id is included in the answer - - Scenario: User is not allowed to reshare file - As an "admin" - Given user "user0" exists - And user "user1" exists - And user "user2" exists - And As an "user0" - And creating a share with - | path | /textfile0.txt | - | shareType | 0 | - | shareWith | user1 | - | permissions | 8 | - And As an "user1" - When creating a share with - | path | /textfile0 (2).txt | - | shareType | 0 | - | shareWith | user2 | - | permissions | 31 | - Then the OCS status code should be "404" - And the HTTP status code should be "200" - - Scenario: User is not allowed to reshare file with more permissions - As an "admin" - Given user "user0" exists - And user "user1" exists - And user "user2" exists - And As an "user0" - And creating a share with - | path | /textfile0.txt | - | shareType | 0 | - | shareWith | user1 | - | permissions | 16 | - And As an "user1" - When creating a share with - | path | /textfile0 (2).txt | - | shareType | 0 | - | shareWith | user2 | - | permissions | 31 | - Then the OCS status code should be "404" - And the HTTP status code should be "200" - - Scenario: Get a share with a user which didn't received the share - Given user "user0" exists - And user "user1" exists - And user "user2" exists - And file "textfile0.txt" of user "user0" is shared with user "user1" - And As an "user2" - When Getting info of last share - Then the OCS status code should be "404" - And the HTTP status code should be "200" - - Scenario: Share of folder and sub-folder to same user - core#20645 - Given As an "admin" - And user "user0" exists - And user "user1" exists - And group "group0" exists - And user "user1" belongs to group "group0" - And file "/PARENT" of user "user0" is shared with user "user1" - When file "/PARENT/CHILD" of user "user0" is shared with group "group0" - Then user "user1" should see following elements - | /FOLDER/ | - | /PARENT/ | - | /CHILD/ | - | /PARENT/parent.txt | - | /CHILD/child.txt | - And the HTTP status code should be "200" - - Scenario: Share a file by multiple channels - Given As an "admin" - And user "user0" exists - And user "user1" exists - And user "user2" exists - And group "group0" exists - And user "user1" belongs to group "group0" - And user "user2" belongs to group "group0" - And user "user0" created a folder "/common" - And user "user0" created a folder "/common/sub" - And file "common" of user "user0" is shared with group "group0" - And file "textfile0.txt" of user "user1" is shared with user "user2" - And User "user1" moved file "/textfile0.txt" to "/common/textfile0.txt" - And User "user1" moved file "/common/textfile0.txt" to "/common/sub/textfile0.txt" - And As an "user2" - When Downloading file "/common/sub/textfile0.txt" with range "bytes=10-18" - Then Downloaded content should be "test text" - And Downloaded content when downloading file "/textfile0.txt" with range "bytes=10-18" should be "test text" - And user "user2" should see following elements - | /common/sub/textfile0.txt | - - Scenario: Share a file by multiple channels - Given As an "admin" - And user "user0" exists - And user "user1" exists - And user "user2" exists - And group "group0" exists - And user "user1" belongs to group "group0" - And user "user2" belongs to group "group0" - And user "user0" created a folder "/common" - And user "user0" created a folder "/common/sub" - And file "common" of user "user0" is shared with group "group0" - And file "textfile0.txt" of user "user1" is shared with user "user2" - And User "user1" moved file "/textfile0.txt" to "/common/textfile0.txt" - And User "user1" moved file "/common/textfile0.txt" to "/common/sub/textfile0.txt" - And As an "user2" - When Downloading file "/textfile0.txt" with range "bytes=10-18" - Then Downloaded content should be "test text" - And user "user2" should see following elements - | /common/sub/textfile0.txt | - - Scenario: Delete all group shares - Given As an "admin" - And user "user0" exists - And user "user1" exists - And group "group1" exists - And user "user1" belongs to group "group1" - And file "textfile0.txt" of user "user0" is shared with group "group1" - And User "user1" moved file "/textfile0.txt" to "/FOLDER/textfile0.txt" - And As an "user0" - And Deleting last share - And As an "user1" - When sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=true" - Then the OCS status code should be "100" - And the HTTP status code should be "200" - And last share_id is not included in the answer - - Scenario: delete a share - Given user "user0" exists - And user "user1" exists - And file "textfile0.txt" of user "user0" is shared with user "user1" - And As an "user0" - When Deleting last share - Then the OCS status code should be "100" - And the HTTP status code should be "200" - - Scenario: Keep usergroup shares (#22143) - Given As an "admin" - And user "user0" exists - And user "user1" exists - And user "user2" exists - And group "group" exists - And user "user1" belongs to group "group" - And user "user2" belongs to group "group" - And user "user0" created a folder "/TMP" - And file "TMP" of user "user0" is shared with group "group" - And user "user1" created a folder "/myFOLDER" - And User "user1" moves file "/TMP" to "/myFOLDER/myTMP" - And user "user2" does not exist - And user "user1" should see following elements - | /myFOLDER/myTMP/ | - - Scenario: Check quota of owners parent directory of a shared file - Given using old dav path - And As an "admin" - And user "user0" exists - And user "user1" exists - And user "user1" has a quota of "0" - And User "user0" moved file "/welcome.txt" to "/myfile.txt" - And file "myfile.txt" of user "user0" is shared with user "user1" - When User "user1" uploads file "data/textfile.txt" to "/myfile.txt" - Then the HTTP status code should be "204" - - Scenario: Don't allow sharing of the root - Given user "user0" exists - And As an "user0" - When creating a share with - | path | / | - | shareType | 3 | - Then the OCS status code should be "403" - - Scenario: Allow modification of reshare - Given user "user0" exists - And user "user1" exists - And user "user2" exists - And user "user0" created a folder "/TMP" - And file "TMP" of user "user0" is shared with user "user1" - And file "TMP" of user "user1" is shared with user "user2" - And As an "user1" - When Updating last share with - | permissions | 1 | - Then the OCS status code should be "100" - - Scenario: Do not allow reshare to exceed permissions - Given user "user0" exists - And user "user1" exists - And user "user2" exists - And user "user0" created a folder "/TMP" - And As an "user0" - And creating a share with - | path | /TMP | - | shareType | 0 | - | shareWith | user1 | - | permissions | 21 | - And As an "user1" - And creating a share with - | path | /TMP | - | shareType | 0 | - | shareWith | user2 | - | permissions | 21 | - When Updating last share with - | permissions | 31 | - Then the OCS status code should be "404" - - Scenario: Only allow 1 link share per file/folder - Given user "user0" exists - And As an "user0" - And creating a share with - | path | welcome.txt | - | shareType | 3 | - When save last share id - And creating a share with - | path | welcome.txt | - | shareType | 3 | - Then share ids should match - - Scenario: Correct webdav share-permissions for owned file - Given user "user0" exists - And User "user0" uploads file with content "foo" to "/tmp.txt" - When as "user0" gets properties of folder "/tmp.txt" with - |{http://open-collaboration-services.org/ns}share-permissions | - Then the single response should contain a property "{http://open-collaboration-services.org/ns}share-permissions" with value "19" - - Scenario: Correct webdav share-permissions for received file with edit and reshare permissions - Given user "user0" exists - And user "user1" exists - And User "user0" uploads file with content "foo" to "/tmp.txt" - And file "/tmp.txt" of user "user0" is shared with user "user1" - When as "user1" gets properties of folder "/tmp.txt" with - |{http://open-collaboration-services.org/ns}share-permissions | - Then the single response should contain a property "{http://open-collaboration-services.org/ns}share-permissions" with value "19" - - Scenario: Correct webdav share-permissions for received file with edit permissions but no reshare permissions - Given user "user0" exists - And user "user1" exists - And User "user0" uploads file with content "foo" to "/tmp.txt" - And file "tmp.txt" of user "user0" is shared with user "user1" - And As an "user0" - And Updating last share with - | permissions | 3 | - When as "user1" gets properties of folder "/tmp.txt" with - |{http://open-collaboration-services.org/ns}share-permissions | - Then the single response should contain a property "{http://open-collaboration-services.org/ns}share-permissions" with value "3" - - Scenario: Correct webdav share-permissions for received file with reshare permissions but no edit permissions - Given user "user0" exists - And user "user1" exists - And User "user0" uploads file with content "foo" to "/tmp.txt" - And file "tmp.txt" of user "user0" is shared with user "user1" - And As an "user0" - And Updating last share with - | permissions | 17 | - When as "user1" gets properties of folder "/tmp.txt" with - |{http://open-collaboration-services.org/ns}share-permissions | - Then the single response should contain a property "{http://open-collaboration-services.org/ns}share-permissions" with value "17" - - Scenario: Correct webdav share-permissions for owned folder - Given user "user0" exists - And user "user0" created a folder "/tmp" - When as "user0" gets properties of folder "/" with - |{http://open-collaboration-services.org/ns}share-permissions | - Then the single response should contain a property "{http://open-collaboration-services.org/ns}share-permissions" with value "31" - - Scenario: Correct webdav share-permissions for received folder with all permissions - Given user "user0" exists - And user "user1" exists - And user "user0" created a folder "/tmp" - And file "/tmp" of user "user0" is shared with user "user1" - When as "user1" gets properties of folder "/tmp" with - |{http://open-collaboration-services.org/ns}share-permissions | - Then the single response should contain a property "{http://open-collaboration-services.org/ns}share-permissions" with value "31" - - Scenario: Correct webdav share-permissions for received folder with all permissions but edit - Given user "user0" exists - And user "user1" exists - And user "user0" created a folder "/tmp" - And file "/tmp" of user "user0" is shared with user "user1" - And As an "user0" - And Updating last share with - | permissions | 29 | - When as "user1" gets properties of folder "/tmp" with - |{http://open-collaboration-services.org/ns}share-permissions | - Then the single response should contain a property "{http://open-collaboration-services.org/ns}share-permissions" with value "29" - - Scenario: Correct webdav share-permissions for received folder with all permissions but create - Given user "user0" exists - And user "user1" exists - And user "user0" created a folder "/tmp" - And file "/tmp" of user "user0" is shared with user "user1" - And As an "user0" - And Updating last share with - | permissions | 27 | - When as "user1" gets properties of folder "/tmp" with - |{http://open-collaboration-services.org/ns}share-permissions | - Then the single response should contain a property "{http://open-collaboration-services.org/ns}share-permissions" with value "27" - - Scenario: Correct webdav share-permissions for received folder with all permissions but delete - Given user "user0" exists - And user "user1" exists - And user "user0" created a folder "/tmp" - And file "/tmp" of user "user0" is shared with user "user1" - And As an "user0" - And Updating last share with - | permissions | 23 | - When as "user1" gets properties of folder "/tmp" with - |{http://open-collaboration-services.org/ns}share-permissions | - Then the single response should contain a property "{http://open-collaboration-services.org/ns}share-permissions" with value "23" - - Scenario: Correct webdav share-permissions for received folder with all permissions but share - Given user "user0" exists - And user "user1" exists - And user "user0" created a folder "/tmp" - And file "/tmp" of user "user0" is shared with user "user1" - And As an "user0" - And Updating last share with - | permissions | 15 | - When as "user1" gets properties of folder "/tmp" with - |{http://open-collaboration-services.org/ns}share-permissions | - Then the single response should contain a property "{http://open-collaboration-services.org/ns}share-permissions" with value "15" - - Scenario: unique target names for incoming shares - Given user "user0" exists - And user "user1" exists - And user "user2" exists - And user "user0" created a folder "/foo" - And user "user1" created a folder "/foo" - When file "/foo" of user "user0" is shared with user "user2" - And file "/foo" of user "user1" is shared with user "user2" - Then user "user2" should see following elements - | /foo/ | - | /foo%20(2)/ | - - Scenario: Creating a new share with a disabled user - Given As an "admin" - And user "user0" exists - And user "user1" exists - And assure user "user0" is disabled - And As an "user0" - When sending "POST" to "/apps/files_sharing/api/v1/shares" with - | path | welcome.txt | - | shareWith | user1 | - | shareType | 0 | - Then the OCS status code should be "997" - And the HTTP status code should be "401" - - Scenario: Deleting a group share as user - Given As an "admin" - And user "user0" exists - And user "user1" exists - And group "group1" exists - And user "user1" belongs to group "group1" - And As an "user0" - And creating a share with - | path | welcome.txt | - | shareType | 1 | - | shareWith | group1 | - When As an "user1" - And Deleting last share - Then the OCS status code should be "100" - And the HTTP status code should be "200" - - Scenario: Merging shares for recipient when shared from outside with group and member - Given using old dav path - And As an "admin" - And user "user0" exists - And user "user1" exists - And group "group1" exists - And user "user1" belongs to group "group1" - And user "user0" created a folder "/merge-test-outside" - When folder "/merge-test-outside" of user "user0" is shared with group "group1" - And folder "/merge-test-outside" of user "user0" is shared with user "user1" - Then as "user1" the folder "/merge-test-outside" exists - And as "user1" the folder "/merge-test-outside (2)" does not exist - - Scenario: Merging shares for recipient when shared from outside with group and member with different permissions - Given As an "admin" - And user "user0" exists - And user "user1" exists - And group "group1" exists - And user "user1" belongs to group "group1" - And user "user0" created a folder "/merge-test-outside-perms" - When folder "/merge-test-outside-perms" of user "user0" is shared with group "group1" with permissions 1 - And folder "/merge-test-outside-perms" of user "user0" is shared with user "user1" with permissions 31 - Then as "user1" gets properties of folder "/merge-test-outside-perms" with - |{http://owncloud.org/ns}permissions| - And the single response should contain a property "{http://owncloud.org/ns}permissions" with value "SRDNVCK" - And as "user1" the folder "/merge-test-outside-perms (2)" does not exist - - Scenario: Merging shares for recipient when shared from outside with two groups - Given As an "admin" - And user "user0" exists - And user "user1" exists - And group "group1" exists - And group "group2" exists - And user "user1" belongs to group "group1" - And user "user1" belongs to group "group2" - And user "user0" created a folder "/merge-test-outside-twogroups" - When folder "/merge-test-outside-twogroups" of user "user0" is shared with group "group1" - And folder "/merge-test-outside-twogroups" of user "user0" is shared with group "group2" - Then as "user1" the folder "/merge-test-outside-twogroups" exists - And as "user1" the folder "/merge-test-outside-twogroups (2)" does not exist - - Scenario: Merging shares for recipient when shared from outside with two groups with different permissions - Given As an "admin" - And user "user0" exists - And user "user1" exists - And group "group1" exists - And group "group2" exists - And user "user1" belongs to group "group1" - And user "user1" belongs to group "group2" - And user "user0" created a folder "/merge-test-outside-twogroups-perms" - When folder "/merge-test-outside-twogroups-perms" of user "user0" is shared with group "group1" with permissions 1 - And folder "/merge-test-outside-twogroups-perms" of user "user0" is shared with group "group2" with permissions 31 - Then as "user1" gets properties of folder "/merge-test-outside-twogroups-perms" with - |{http://owncloud.org/ns}permissions| - And the single response should contain a property "{http://owncloud.org/ns}permissions" with value "SRDNVCK" - And as "user1" the folder "/merge-test-outside-twogroups-perms (2)" does not exist - - Scenario: Merging shares for recipient when shared from outside with two groups and member - Given As an "admin" - And user "user0" exists - And user "user1" exists - And group "group1" exists - And group "group2" exists - And user "user1" belongs to group "group1" - And user "user1" belongs to group "group2" - And user "user0" created a folder "/merge-test-outside-twogroups-member-perms" - When folder "/merge-test-outside-twogroups-member-perms" of user "user0" is shared with group "group1" with permissions 1 - And folder "/merge-test-outside-twogroups-member-perms" of user "user0" is shared with group "group2" with permissions 31 - And folder "/merge-test-outside-twogroups-member-perms" of user "user0" is shared with user "user1" with permissions 1 - Then as "user1" gets properties of folder "/merge-test-outside-twogroups-member-perms" with - |{http://owncloud.org/ns}permissions| - And the single response should contain a property "{http://owncloud.org/ns}permissions" with value "SRDNVCK" - And as "user1" the folder "/merge-test-outside-twogroups-member-perms (2)" does not exist - - Scenario: Merging shares for recipient when shared from inside with group - Given As an "admin" - And user "user0" exists - And group "group1" exists - And user "user0" belongs to group "group1" - And user "user0" created a folder "/merge-test-inside-group" - When folder "/merge-test-inside-group" of user "user0" is shared with group "group1" - Then as "user0" the folder "/merge-test-inside-group" exists - And as "user0" the folder "/merge-test-inside-group (2)" does not exist - - Scenario: Merging shares for recipient when shared from inside with two groups - Given As an "admin" - And user "user0" exists - And group "group1" exists - And group "group2" exists - And user "user0" belongs to group "group1" - And user "user0" belongs to group "group2" - And user "user0" created a folder "/merge-test-inside-twogroups" - When folder "/merge-test-inside-twogroups" of user "user0" is shared with group "group1" - And folder "/merge-test-inside-twogroups" of user "user0" is shared with group "group2" - Then as "user0" the folder "/merge-test-inside-twogroups" exists - And as "user0" the folder "/merge-test-inside-twogroups (2)" does not exist - And as "user0" the folder "/merge-test-inside-twogroups (3)" does not exist - - Scenario: Merging shares for recipient when shared from inside with group with less permissions - Given As an "admin" - And user "user0" exists - And group "group1" exists - And group "group2" exists - And user "user0" belongs to group "group1" - And user "user0" belongs to group "group2" - And user "user0" created a folder "/merge-test-inside-twogroups-perms" - When folder "/merge-test-inside-twogroups-perms" of user "user0" is shared with group "group1" - And folder "/merge-test-inside-twogroups-perms" of user "user0" is shared with group "group2" - Then as "user0" gets properties of folder "/merge-test-inside-twogroups-perms" with - |{http://owncloud.org/ns}permissions| - And the single response should contain a property "{http://owncloud.org/ns}permissions" with value "RDNVCK" - And as "user0" the folder "/merge-test-inside-twogroups-perms (2)" does not exist - And as "user0" the folder "/merge-test-inside-twogroups-perms (3)" does not exist - - Scenario: Merging shares for recipient when shared from outside with group then user and recipient renames in between - Given As an "admin" - And user "user0" exists - And user "user1" exists - And group "group1" exists - And user "user1" belongs to group "group1" - And user "user0" created a folder "/merge-test-outside-groups-renamebeforesecondshare" - When folder "/merge-test-outside-groups-renamebeforesecondshare" of user "user0" is shared with group "group1" - And User "user1" moved folder "/merge-test-outside-groups-renamebeforesecondshare" to "/merge-test-outside-groups-renamebeforesecondshare-renamed" - And Sleep for "1" seconds - And folder "/merge-test-outside-groups-renamebeforesecondshare" of user "user0" is shared with user "user1" - Then as "user1" gets properties of folder "/merge-test-outside-groups-renamebeforesecondshare-renamed" with - |{http://owncloud.org/ns}permissions| - And the single response should contain a property "{http://owncloud.org/ns}permissions" with value "SRDNVCK" - And as "user1" the folder "/merge-test-outside-groups-renamebeforesecondshare" does not exist - - Scenario: Merging shares for recipient when shared from outside with user then group and recipient renames in between - Given using old dav path - Given As an "admin" - And user "user0" exists - And user "user1" exists - And group "group1" exists - And user "user1" belongs to group "group1" - And user "user0" created a folder "/merge-test-outside-groups-renamebeforesecondshare" - When folder "/merge-test-outside-groups-renamebeforesecondshare" of user "user0" is shared with user "user1" - And User "user1" moved folder "/merge-test-outside-groups-renamebeforesecondshare" to "/merge-test-outside-groups-renamebeforesecondshare-renamed" - And Sleep for "1" seconds - And folder "/merge-test-outside-groups-renamebeforesecondshare" of user "user0" is shared with group "group1" - Then as "user1" gets properties of folder "/merge-test-outside-groups-renamebeforesecondshare-renamed" with - |{http://owncloud.org/ns}permissions| - And the single response should contain a property "{http://owncloud.org/ns}permissions" with value "SRDNVCK" - And as "user1" the folder "/merge-test-outside-groups-renamebeforesecondshare" does not exist - - Scenario: Empting trashbin - Given As an "admin" - And user "user0" exists - And User "user0" deletes file "/textfile0.txt" - When User "user0" empties trashbin - Then the HTTP status code should be "200" - - Scenario: orphaned shares - Given As an "admin" - And user "user0" exists - And user "user1" exists - And user "user0" created a folder "/common" - And user "user0" created a folder "/common/sub" - And file "/common/sub" of user "user0" is shared with user "user1" - And User "user0" deletes folder "/common" - When User "user0" empties trashbin - Then as "user1" the folder "/sub" does not exist - - Scenario: sharing again an own file while belonging to a group - Given As an "admin" - Given user "user0" exists - And group "sharing-group" exists - And user "user0" belongs to group "sharing-group" - And file "welcome.txt" of user "user0" is shared with group "sharing-group" - And Deleting last share - When sending "POST" to "/apps/files_sharing/api/v1/shares" with - | path | welcome.txt | - | shareWith | sharing-group | - | shareType | 1 | - Then the OCS status code should be "100" - And the HTTP status code should be "200" - - Scenario: unshare from self - Given As an "admin" - And user "user0" exists - And user "user1" exists - And group "sharing-group" exists - And user "user0" belongs to group "sharing-group" - And user "user1" belongs to group "sharing-group" - And file "/PARENT/parent.txt" of user "user0" is shared with group "sharing-group" - And user "user0" stores etag of element "/PARENT" - And user "user1" stores etag of element "/" - And As an "user1" - When Deleting last share - Then etag of element "/" of user "user1" has changed - And etag of element "/PARENT" of user "user0" has not changed - - Scenario: do not allow to increase link share permissions on reshare - Given As an "admin" - And user "admin" created a folder "/TMP" - And user "user0" exists - And creating a share with - | path | TMP | - | shareType | 0 | - | shareWith | user0 | - | permissions | 17 | - When As an "user0" - And creating a share with - | path | TMP | - | shareType | 3 | - And Updating last share with - | publicUpload | true | - Then the OCS status code should be "404" +# See sharing-v1-part2.feature diff --git a/core/Controller/CssController.php b/core/Controller/CssController.php index 1206c95a5b8..b467d386f98 100644 --- a/core/Controller/CssController.php +++ b/core/Controller/CssController.php @@ -28,6 +28,8 @@ use OCP\AppFramework\Http\FileDisplayResponse; use OCP\AppFramework\Utility\ITimeFactory; use OCP\Files\IAppData; use OCP\Files\NotFoundException; +use OCP\Files\SimpleFS\ISimpleFile; +use OCP\Files\SimpleFS\ISimpleFolder; use OCP\IRequest; class CssController extends Controller { @@ -62,12 +64,16 @@ class CssController extends Controller { public function getCss($fileName, $appName) { try { $folder = $this->appData->getFolder($appName); - $cssFile = $folder->getFile($fileName); + $gzip = false; + $file = $this->getFile($folder, $fileName, $gzip); } catch(NotFoundException $e) { return new NotFoundResponse(); } - $response = new FileDisplayResponse($cssFile, Http::STATUS_OK, ['Content-Type' => 'text/css']); + $response = new FileDisplayResponse($file, Http::STATUS_OK, ['Content-Type' => 'text/css']); + if ($gzip) { + $response->addHeader('Content-Encoding', 'gzip'); + } $response->cacheFor(86400); $expires = new \DateTime(); $expires->setTimestamp($this->timeFactory->getTime()); @@ -76,4 +82,26 @@ class CssController extends Controller { $response->addHeader('Pragma', 'cache'); return $response; } + + /** + * @param ISimpleFolder $folder + * @param string $fileName + * @param bool $gzip is set to true if we use the gzip file + * @return ISimpleFile + */ + private function getFile(ISimpleFolder $folder, $fileName, &$gzip) { + $encoding = $this->request->getHeader('Accept-Encoding'); + + if ($encoding !== null && strpos($encoding, 'gzip') !== false) { + try { + $gzip = true; + return $folder->getFile($fileName . '.gz'); + } catch (NotFoundException $e) { + // continue + } + } + + $gzip = false; + return $folder->getFile($fileName); + } } diff --git a/core/Controller/JsController.php b/core/Controller/JsController.php index 0770974e7a1..0b50abc158a 100644 --- a/core/Controller/JsController.php +++ b/core/Controller/JsController.php @@ -29,6 +29,8 @@ use OCP\AppFramework\Http\FileDisplayResponse; use OCP\AppFramework\Utility\ITimeFactory; use OCP\Files\IAppData; use OCP\Files\NotFoundException; +use OCP\Files\SimpleFS\ISimpleFile; +use OCP\Files\SimpleFS\ISimpleFolder; use OCP\IRequest; class JsController extends Controller { @@ -63,12 +65,16 @@ class JsController extends Controller { public function getJs($fileName, $appName) { try { $folder = $this->appData->getFolder($appName); - $jsFile = $folder->getFile($fileName); + $gzip = false; + $file = $this->getFile($folder, $fileName, $gzip); } catch(NotFoundException $e) { return new NotFoundResponse(); } - $response = new FileDisplayResponse($jsFile, Http::STATUS_OK, ['Content-Type' => 'application/javascript']); + $response = new FileDisplayResponse($file, Http::STATUS_OK, ['Content-Type' => 'application/javascript']); + if ($gzip) { + $response->addHeader('Content-Encoding', 'gzip'); + } $response->cacheFor(86400); $expires = new \DateTime(); $expires->setTimestamp($this->timeFactory->getTime()); @@ -77,4 +83,26 @@ class JsController extends Controller { $response->addHeader('Pragma', 'cache'); return $response; } + + /** + * @param ISimpleFolder $folder + * @param string $fileName + * @param bool $gzip is set to true if we use the gzip file + * @return ISimpleFile + */ + private function getFile(ISimpleFolder $folder, $fileName, &$gzip) { + $encoding = $this->request->getHeader('Accept-Encoding'); + + if ($encoding !== null && strpos($encoding, 'gzip') !== false) { + try { + $gzip = true; + return $folder->getFile($fileName . '.gz'); + } catch (NotFoundException $e) { + // continue + } + } + + $gzip = false; + return $folder->getFile($fileName); + } } diff --git a/core/css/styles.scss b/core/css/styles.scss index a5b7f2481d9..c9ba8695032 100644 --- a/core/css/styles.scss +++ b/core/css/styles.scss @@ -308,6 +308,10 @@ body { width: 100%; } +#app-sidebar #emptycontent, #app-sidebar .emptycontent { + margin-top: 10vh; +} + #emptycontent.emptycontent-search, .emptycontent.emptycontent-search { position: static; } diff --git a/core/img/manifest.json b/core/img/manifest.json new file mode 100644 index 00000000000..fcecb856614 --- /dev/null +++ b/core/img/manifest.json @@ -0,0 +1,14 @@ +{ + "name": "Nextcloud", + "start_url": "../../", + "icons": [{ + "src": "favicon-touch.png", + "type": "image/png", + "sizes": "128x128" + }, { + "src": "favicon-mask.svg", + "type": "image/svg+xml", + "sizes": "16x16" + }], + "display": "standalone" +} diff --git a/core/l10n/ca.js b/core/l10n/ca.js index b3a8111f56d..efc4b5d0d55 100644 --- a/core/l10n/ca.js +++ b/core/l10n/ca.js @@ -24,6 +24,7 @@ OC.L10N.register( "[%d / %d]: %s" : "[%d / %d]: %s", "Repair warning: " : "Advertiment de reparació:", "Repair error: " : "Error de reparació:", + "[%d / %d]: Checking table %s" : "[%d / %d]: Revisant la taula %s", "Turned on maintenance mode" : "Activat el mode de manteniment", "Turned off maintenance mode" : "Desactivat el mode de manteniment", "Maintenance mode is kept active" : "El mode de manteniment es manté activat", diff --git a/core/l10n/ca.json b/core/l10n/ca.json index 83a9c36c199..98b2b6b6ca7 100644 --- a/core/l10n/ca.json +++ b/core/l10n/ca.json @@ -22,6 +22,7 @@ "[%d / %d]: %s" : "[%d / %d]: %s", "Repair warning: " : "Advertiment de reparació:", "Repair error: " : "Error de reparació:", + "[%d / %d]: Checking table %s" : "[%d / %d]: Revisant la taula %s", "Turned on maintenance mode" : "Activat el mode de manteniment", "Turned off maintenance mode" : "Desactivat el mode de manteniment", "Maintenance mode is kept active" : "El mode de manteniment es manté activat", diff --git a/core/l10n/de.js b/core/l10n/de.js index d51f6acf898..be71a076ebd 100644 --- a/core/l10n/de.js +++ b/core/l10n/de.js @@ -126,6 +126,7 @@ OC.L10N.register( "Password protect" : "Passwortschutz", "Allow upload and editing" : "Hochladen und Bearbeiten erlauben", "Allow editing" : "Bearbeitung erlauben", + "upload only" : "Nur Hochladen", "Email link to person" : "Link per E-Mail verschicken", "Send" : "Senden", "Shared with you and the group {group} by {owner}" : "{owner} hat dies mit Dir und der Gruppe {group} geteilt", diff --git a/core/l10n/de.json b/core/l10n/de.json index 34abe0d3673..0ce9721d384 100644 --- a/core/l10n/de.json +++ b/core/l10n/de.json @@ -124,6 +124,7 @@ "Password protect" : "Passwortschutz", "Allow upload and editing" : "Hochladen und Bearbeiten erlauben", "Allow editing" : "Bearbeitung erlauben", + "upload only" : "Nur Hochladen", "Email link to person" : "Link per E-Mail verschicken", "Send" : "Senden", "Shared with you and the group {group} by {owner}" : "{owner} hat dies mit Dir und der Gruppe {group} geteilt", diff --git a/core/l10n/de_DE.js b/core/l10n/de_DE.js index 2fbd72282e0..f081ba7dbc2 100644 --- a/core/l10n/de_DE.js +++ b/core/l10n/de_DE.js @@ -126,6 +126,7 @@ OC.L10N.register( "Password protect" : "Passwortschutz", "Allow upload and editing" : "Hochladen und Bearbeiten erlauben", "Allow editing" : "Bearbeitung erlauben", + "upload only" : "Nur Hochladen", "Email link to person" : "Link per E-Mail verschicken", "Send" : "Senden", "Shared with you and the group {group} by {owner}" : "Von {owner} mit Ihnen und der Gruppe {group} geteilt.", diff --git a/core/l10n/de_DE.json b/core/l10n/de_DE.json index 6f6f22c8876..e4de794101e 100644 --- a/core/l10n/de_DE.json +++ b/core/l10n/de_DE.json @@ -124,6 +124,7 @@ "Password protect" : "Passwortschutz", "Allow upload and editing" : "Hochladen und Bearbeiten erlauben", "Allow editing" : "Bearbeitung erlauben", + "upload only" : "Nur Hochladen", "Email link to person" : "Link per E-Mail verschicken", "Send" : "Senden", "Shared with you and the group {group} by {owner}" : "Von {owner} mit Ihnen und der Gruppe {group} geteilt.", diff --git a/core/l10n/es.js b/core/l10n/es.js index 8d21c4cdfae..98f51ddca50 100644 --- a/core/l10n/es.js +++ b/core/l10n/es.js @@ -126,6 +126,7 @@ OC.L10N.register( "Password protect" : "Protección con contraseña", "Allow upload and editing" : "Permitir subito y edición", "Allow editing" : "Permitir edición", + "upload only" : "solo subida", "Email link to person" : "Enviar enlace por correo electrónico a una persona", "Send" : "Enviar", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", diff --git a/core/l10n/es.json b/core/l10n/es.json index 22bc3a75ec6..45d9977e9db 100644 --- a/core/l10n/es.json +++ b/core/l10n/es.json @@ -124,6 +124,7 @@ "Password protect" : "Protección con contraseña", "Allow upload and editing" : "Permitir subito y edición", "Allow editing" : "Permitir edición", + "upload only" : "solo subida", "Email link to person" : "Enviar enlace por correo electrónico a una persona", "Send" : "Enviar", "Shared with you and the group {group} by {owner}" : "Compartido contigo y el grupo {group} por {owner}", diff --git a/core/l10n/fr.js b/core/l10n/fr.js index b16b132ea66..f9d25c24703 100644 --- a/core/l10n/fr.js +++ b/core/l10n/fr.js @@ -126,6 +126,7 @@ OC.L10N.register( "Password protect" : "Protéger par un mot de passe", "Allow upload and editing" : "Autoriser l'envoi et l'édition", "Allow editing" : "Permettre la modification", + "upload only" : " Envoyer uniquement", "Email link to person" : "Envoyer le lien par courriel", "Send" : "Envoyer", "Shared with you and the group {group} by {owner}" : "Partagé avec vous et le groupe {group} par {owner}", diff --git a/core/l10n/fr.json b/core/l10n/fr.json index daff3723d9f..253ce0d4b94 100644 --- a/core/l10n/fr.json +++ b/core/l10n/fr.json @@ -124,6 +124,7 @@ "Password protect" : "Protéger par un mot de passe", "Allow upload and editing" : "Autoriser l'envoi et l'édition", "Allow editing" : "Permettre la modification", + "upload only" : " Envoyer uniquement", "Email link to person" : "Envoyer le lien par courriel", "Send" : "Envoyer", "Shared with you and the group {group} by {owner}" : "Partagé avec vous et le groupe {group} par {owner}", diff --git a/core/l10n/is.js b/core/l10n/is.js index 3f4d865f1d8..971660f3e54 100644 --- a/core/l10n/is.js +++ b/core/l10n/is.js @@ -126,6 +126,7 @@ OC.L10N.register( "Password protect" : "Verja með lykilorði", "Allow upload and editing" : "Leyfa innsendingu og breytingar", "Allow editing" : "Leyfa breytingar", + "upload only" : "einungis innsending", "Email link to person" : "Senda veftengil í tölvupósti til notanda", "Send" : "Senda", "Shared with you and the group {group} by {owner}" : "Deilt með þér og hópnum {group} af {owner}", diff --git a/core/l10n/is.json b/core/l10n/is.json index bd4c77bae03..1a03d937b3a 100644 --- a/core/l10n/is.json +++ b/core/l10n/is.json @@ -124,6 +124,7 @@ "Password protect" : "Verja með lykilorði", "Allow upload and editing" : "Leyfa innsendingu og breytingar", "Allow editing" : "Leyfa breytingar", + "upload only" : "einungis innsending", "Email link to person" : "Senda veftengil í tölvupósti til notanda", "Send" : "Senda", "Shared with you and the group {group} by {owner}" : "Deilt með þér og hópnum {group} af {owner}", diff --git a/core/l10n/pl.js b/core/l10n/pl.js index 8da2c6c72a4..75db60d1e76 100644 --- a/core/l10n/pl.js +++ b/core/l10n/pl.js @@ -126,6 +126,7 @@ OC.L10N.register( "Password protect" : "Zabezpiecz hasłem", "Allow upload and editing" : "Pozwól na przesyłanie i edycję", "Allow editing" : "Pozwól na edycję", + "upload only" : "tylko wysyłanie", "Email link to person" : "Wyślij osobie odnośnik poprzez e-mail", "Send" : "Wyślij", "Shared with you and the group {group} by {owner}" : "Udostępnione tobie i grupie {group} przez {owner}", diff --git a/core/l10n/pl.json b/core/l10n/pl.json index e96d3b9d4dc..778ff3f1072 100644 --- a/core/l10n/pl.json +++ b/core/l10n/pl.json @@ -124,6 +124,7 @@ "Password protect" : "Zabezpiecz hasłem", "Allow upload and editing" : "Pozwól na przesyłanie i edycję", "Allow editing" : "Pozwól na edycję", + "upload only" : "tylko wysyłanie", "Email link to person" : "Wyślij osobie odnośnik poprzez e-mail", "Send" : "Wyślij", "Shared with you and the group {group} by {owner}" : "Udostępnione tobie i grupie {group} przez {owner}", diff --git a/core/l10n/ru.js b/core/l10n/ru.js index c3cbc916344..124728dc38c 100644 --- a/core/l10n/ru.js +++ b/core/l10n/ru.js @@ -126,6 +126,7 @@ OC.L10N.register( "Password protect" : "Защитить паролем", "Allow upload and editing" : "Разрешить загрузку и редактирование", "Allow editing" : "Разрешить редактирование", + "upload only" : "только загружать", "Email link to person" : "Отправить ссылку по электронной почте", "Send" : "Отправить", "Shared with you and the group {group} by {owner}" : "{owner} поделился с вами и группой {group} ", diff --git a/core/l10n/ru.json b/core/l10n/ru.json index 3c93d3f8c46..767c032eade 100644 --- a/core/l10n/ru.json +++ b/core/l10n/ru.json @@ -124,6 +124,7 @@ "Password protect" : "Защитить паролем", "Allow upload and editing" : "Разрешить загрузку и редактирование", "Allow editing" : "Разрешить редактирование", + "upload only" : "только загружать", "Email link to person" : "Отправить ссылку по электронной почте", "Send" : "Отправить", "Shared with you and the group {group} by {owner}" : "{owner} поделился с вами и группой {group} ", diff --git a/core/l10n/tr.js b/core/l10n/tr.js index f99a3fbb9fc..59ecdefc2f9 100644 --- a/core/l10n/tr.js +++ b/core/l10n/tr.js @@ -126,6 +126,7 @@ OC.L10N.register( "Password protect" : "Parola koruması", "Allow upload and editing" : "Yükleme ve düzenleme yapılabilsin", "Allow editing" : "Düzenleme yapılabilsin", + "upload only" : "yalnız yükleme", "Email link to person" : "Bağlantıyı e-posta ile gönder", "Send" : "Gönder", "Shared with you and the group {group} by {owner}" : "{owner} tarafından sizinle ve {group} ile paylaşılmış", diff --git a/core/l10n/tr.json b/core/l10n/tr.json index f7c878dd951..78813b72762 100644 --- a/core/l10n/tr.json +++ b/core/l10n/tr.json @@ -124,6 +124,7 @@ "Password protect" : "Parola koruması", "Allow upload and editing" : "Yükleme ve düzenleme yapılabilsin", "Allow editing" : "Düzenleme yapılabilsin", + "upload only" : "yalnız yükleme", "Email link to person" : "Bağlantıyı e-posta ile gönder", "Send" : "Gönder", "Shared with you and the group {group} by {owner}" : "{owner} tarafından sizinle ve {group} ile paylaşılmış", diff --git a/core/templates/error.php b/core/templates/error.php index 6e044b72414..b5e8c8eab3f 100644 --- a/core/templates/error.php +++ b/core/templates/error.php @@ -3,7 +3,7 @@ <li class='error'> <?php p($error['error']) ?><br> <?php if(isset($error['hint']) && $error['hint']): ?> - <p class='hint'><?php print_unescaped($error['hint']) ?></p> + <p class='hint'><?php p($error['hint']) ?></p> <?php endif;?> </li> <?php endforeach ?> diff --git a/core/templates/layout.base.php b/core/templates/layout.base.php index 8f376619a1e..4ae33341e2f 100644 --- a/core/templates/layout.base.php +++ b/core/templates/layout.base.php @@ -12,17 +12,17 @@ <link rel="icon" href="<?php print_unescaped(image_path('', 'favicon.ico')); /* IE11+ supports png */ ?>"> <link rel="apple-touch-icon-precomposed" href="<?php print_unescaped(image_path('', 'favicon-touch.png')); ?>"> <link rel="mask-icon" sizes="any" href="<?php print_unescaped(image_path('', 'favicon-mask.svg')); ?>" color="<?php p($theme->getMailHeaderColor()); ?>"> + <?php if (isset($_['inline_ocjs'])): ?> + <script nonce="<?php p(\OC::$server->getContentSecurityPolicyNonceManager()->getNonce()) ?>" type="text/javascript"> + <?php print_unescaped($_['inline_ocjs']); ?> + </script> + <?php endif; ?> <?php foreach ($_['cssfiles'] as $cssfile): ?> <link rel="stylesheet" href="<?php print_unescaped($cssfile); ?>"> <?php endforeach; ?> <?php foreach($_['printcssfiles'] as $cssfile): ?> <link rel="stylesheet" href="<?php print_unescaped($cssfile); ?>" media="print"> <?php endforeach; ?> - <?php if (isset($_['inline_ocjs'])): ?> - <script nonce="<?php p(\OC::$server->getContentSecurityPolicyNonceManager()->getNonce()) ?>" type="text/javascript"> - <?php print_unescaped($_['inline_ocjs']); ?> - </script> - <?php endif; ?> <?php foreach ($_['jsfiles'] as $jsfile): ?> <script nonce="<?php p(\OC::$server->getContentSecurityPolicyNonceManager()->getNonce()) ?>" src="<?php print_unescaped($jsfile); ?>"></script> <?php endforeach; ?> diff --git a/core/templates/layout.guest.php b/core/templates/layout.guest.php index ee844047a11..9b89ed6300f 100644 --- a/core/templates/layout.guest.php +++ b/core/templates/layout.guest.php @@ -13,17 +13,17 @@ <link rel="icon" href="<?php print_unescaped(image_path('', 'favicon.ico')); /* IE11+ supports png */ ?>"> <link rel="apple-touch-icon-precomposed" href="<?php print_unescaped(image_path('', 'favicon-touch.png')); ?>"> <link rel="mask-icon" sizes="any" href="<?php print_unescaped(image_path('', 'favicon-mask.svg')); ?>" color="<?php p($theme->getMailHeaderColor()); ?>"> + <?php if (isset($_['inline_ocjs'])): ?> + <script nonce="<?php p(\OC::$server->getContentSecurityPolicyNonceManager()->getNonce()) ?>" type="text/javascript"> + <?php print_unescaped($_['inline_ocjs']); ?> + </script> + <?php endif; ?> <?php foreach($_['cssfiles'] as $cssfile): ?> <link rel="stylesheet" href="<?php print_unescaped($cssfile); ?>"> <?php endforeach; ?> <?php foreach($_['printcssfiles'] as $cssfile): ?> <link rel="stylesheet" href="<?php print_unescaped($cssfile); ?>" media="print"> <?php endforeach; ?> - <?php if (isset($_['inline_ocjs'])): ?> - <script nonce="<?php p(\OC::$server->getContentSecurityPolicyNonceManager()->getNonce()) ?>" type="text/javascript"> - <?php print_unescaped($_['inline_ocjs']); ?> - </script> - <?php endif; ?> <?php foreach($_['jsfiles'] as $jsfile): ?> <script nonce="<?php p(\OC::$server->getContentSecurityPolicyNonceManager()->getNonce()) ?>" src="<?php print_unescaped($jsfile); ?>"></script> <?php endforeach; ?> diff --git a/core/templates/layout.user.php b/core/templates/layout.user.php index 339903f1eaf..439567fe6a1 100644 --- a/core/templates/layout.user.php +++ b/core/templates/layout.user.php @@ -20,17 +20,18 @@ <link rel="icon" href="<?php print_unescaped(image_path($_['appid'], 'favicon.ico')); /* IE11+ supports png */ ?>"> <link rel="apple-touch-icon-precomposed" href="<?php print_unescaped(image_path($_['appid'], 'favicon-touch.png')); ?>"> <link rel="mask-icon" sizes="any" href="<?php print_unescaped(image_path($_['appid'], 'favicon-mask.svg')); ?>" color="<?php p($theme->getMailHeaderColor()); ?>"> + <link rel="manifest" href="<?php print_unescaped(image_path($_['appid'], 'manifest.json')); ?>"> + <?php if (isset($_['inline_ocjs'])): ?> + <script nonce="<?php p(\OC::$server->getContentSecurityPolicyNonceManager()->getNonce()) ?>" type="text/javascript"> + <?php print_unescaped($_['inline_ocjs']); ?> + </script> + <?php endif; ?> <?php foreach($_['cssfiles'] as $cssfile): ?> <link rel="stylesheet" href="<?php print_unescaped($cssfile); ?>"> <?php endforeach; ?> <?php foreach($_['printcssfiles'] as $cssfile): ?> <link rel="stylesheet" href="<?php print_unescaped($cssfile); ?>" media="print"> <?php endforeach; ?> - <?php if (isset($_['inline_ocjs'])): ?> - <script nonce="<?php p(\OC::$server->getContentSecurityPolicyNonceManager()->getNonce()) ?>" type="text/javascript"> - <?php print_unescaped($_['inline_ocjs']); ?> - </script> - <?php endif; ?> <?php foreach($_['jsfiles'] as $jsfile): ?> <script nonce="<?php p(\OC::$server->getContentSecurityPolicyNonceManager()->getNonce()) ?>" src="<?php print_unescaped($jsfile); ?>"></script> <?php endforeach; ?> diff --git a/lib/l10n/de_DE.js b/lib/l10n/de_DE.js index 9c89793808f..76b58951580 100644 --- a/lib/l10n/de_DE.js +++ b/lib/l10n/de_DE.js @@ -45,6 +45,7 @@ OC.L10N.register( "Help" : "Hilfe", "Apps" : "Apps", "Personal" : "Persönlich", + "Log out" : "Abmelden", "Users" : "Benutzer", "Admin" : "Administrator", "APCu" : "APCu", diff --git a/lib/l10n/de_DE.json b/lib/l10n/de_DE.json index 2688ec4579f..ddea99752de 100644 --- a/lib/l10n/de_DE.json +++ b/lib/l10n/de_DE.json @@ -43,6 +43,7 @@ "Help" : "Hilfe", "Apps" : "Apps", "Personal" : "Persönlich", + "Log out" : "Abmelden", "Users" : "Benutzer", "Admin" : "Administrator", "APCu" : "APCu", diff --git a/lib/l10n/is.js b/lib/l10n/is.js index b3802c3c674..ceadf0bb098 100644 --- a/lib/l10n/is.js +++ b/lib/l10n/is.js @@ -38,6 +38,7 @@ OC.L10N.register( "Help" : "Hjálp", "Apps" : "Forrit", "Personal" : "Einka", + "Log out" : "Skrá út", "Users" : "Notendur", "Admin" : "Stjórnun", "APCu" : "APCu", @@ -158,9 +159,16 @@ OC.L10N.register( "Cannot write into \"apps\" directory" : "Get ekki skrifað í \"apps\" möppuna", "Cannot create \"data\" directory (%s)" : "Get ekki búið til \"data\" möppu (%s)", "Setting locale to %s failed" : "Mistókst að setja upp staðfærsluna %s", + "Please install one of these locales on your system and restart your webserver." : "Settu upp eina af þessum staðfærslum og endurræstu vefþjóninn.", "Please ask your server administrator to install the module." : "Biddu kerfisstjórann þinn um að setja eininguna upp.", "PHP module %s not installed." : "PHP-einingin %s er ekki uppsett.", "PHP setting \"%s\" is not set to \"%s\"." : "PHP-stillingin \"%s\" er ekki sett á \"%s\".", + "Adjusting this setting in php.ini will make Nextcloud run again" : "Ef þessi stilling er löguð í php.ini mun Nextcloud keyra aftur", + "mbstring.func_overload is set to \"%s\" instead of the expected value \"0\"" : "mbstring.func_overload er stillt á \"%s\" í stað gildisins \"0\" eins og vænst var", + "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "Til að laga þetta vandamál ættirðu að setja <code>mbstring.func_overload</code> sem <code>0</code> í php.ini", + "libxml2 2.7.0 is at least required. Currently %s is installed." : "Krafist er libxml2 2.7.0 hið minnsta. Núna er %s uppsett.", + "To fix this issue update your libxml2 version and restart your web server." : "Til að laga þetta vandamál ættirðu að uppfæra útgáfu þína af libxml2 og endurræsa vefþjóninn.", + "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP virðist vera sett upp to fjarlægja innantextablokkir (inline doc blocks). Þetta mun gera ýmis kjarnaforrit óaðgengileg.", "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Þessu veldur væntanlega biðminni/hraðall á borð við Zend OPcache eða eAccelerator.", "Please ask your server administrator to restart the web server." : "Biddu kerfisstjórann þinn um að endurræsa vefþjóninn.", "PostgreSQL >= 9 required" : "Krefst PostgreSQL >= 9", diff --git a/lib/l10n/is.json b/lib/l10n/is.json index 6681f9cc6c0..b1a26f38640 100644 --- a/lib/l10n/is.json +++ b/lib/l10n/is.json @@ -36,6 +36,7 @@ "Help" : "Hjálp", "Apps" : "Forrit", "Personal" : "Einka", + "Log out" : "Skrá út", "Users" : "Notendur", "Admin" : "Stjórnun", "APCu" : "APCu", @@ -156,9 +157,16 @@ "Cannot write into \"apps\" directory" : "Get ekki skrifað í \"apps\" möppuna", "Cannot create \"data\" directory (%s)" : "Get ekki búið til \"data\" möppu (%s)", "Setting locale to %s failed" : "Mistókst að setja upp staðfærsluna %s", + "Please install one of these locales on your system and restart your webserver." : "Settu upp eina af þessum staðfærslum og endurræstu vefþjóninn.", "Please ask your server administrator to install the module." : "Biddu kerfisstjórann þinn um að setja eininguna upp.", "PHP module %s not installed." : "PHP-einingin %s er ekki uppsett.", "PHP setting \"%s\" is not set to \"%s\"." : "PHP-stillingin \"%s\" er ekki sett á \"%s\".", + "Adjusting this setting in php.ini will make Nextcloud run again" : "Ef þessi stilling er löguð í php.ini mun Nextcloud keyra aftur", + "mbstring.func_overload is set to \"%s\" instead of the expected value \"0\"" : "mbstring.func_overload er stillt á \"%s\" í stað gildisins \"0\" eins og vænst var", + "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "Til að laga þetta vandamál ættirðu að setja <code>mbstring.func_overload</code> sem <code>0</code> í php.ini", + "libxml2 2.7.0 is at least required. Currently %s is installed." : "Krafist er libxml2 2.7.0 hið minnsta. Núna er %s uppsett.", + "To fix this issue update your libxml2 version and restart your web server." : "Til að laga þetta vandamál ættirðu að uppfæra útgáfu þína af libxml2 og endurræsa vefþjóninn.", + "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP virðist vera sett upp to fjarlægja innantextablokkir (inline doc blocks). Þetta mun gera ýmis kjarnaforrit óaðgengileg.", "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Þessu veldur væntanlega biðminni/hraðall á borð við Zend OPcache eða eAccelerator.", "Please ask your server administrator to restart the web server." : "Biddu kerfisstjórann þinn um að endurræsa vefþjóninn.", "PostgreSQL >= 9 required" : "Krefst PostgreSQL >= 9", diff --git a/lib/l10n/pl.js b/lib/l10n/pl.js index 4e6f5954cda..bd9113027c3 100644 --- a/lib/l10n/pl.js +++ b/lib/l10n/pl.js @@ -45,6 +45,7 @@ OC.L10N.register( "Help" : "Pomoc", "Apps" : "Aplikacje", "Personal" : "Osobiste", + "Log out" : "Wyloguj", "Users" : "Użytkownicy", "Admin" : "Administracja", "APCu" : "APCu", diff --git a/lib/l10n/pl.json b/lib/l10n/pl.json index b8322967bd6..8673a21fb46 100644 --- a/lib/l10n/pl.json +++ b/lib/l10n/pl.json @@ -43,6 +43,7 @@ "Help" : "Pomoc", "Apps" : "Aplikacje", "Personal" : "Osobiste", + "Log out" : "Wyloguj", "Users" : "Użytkownicy", "Admin" : "Administracja", "APCu" : "APCu", diff --git a/lib/private/Activity/EventMerger.php b/lib/private/Activity/EventMerger.php index 91e79068665..04aa41b2690 100644 --- a/lib/private/Activity/EventMerger.php +++ b/lib/private/Activity/EventMerger.php @@ -201,25 +201,25 @@ class EventMerger implements IEventMerger { case 2: $replacement = $this->l10n->t( '%1$s and %2$s', - ['{' . $parameter . '1}', '{' . $parameter . '2}'] + ['{' . $parameter . '2}', '{' . $parameter . '1}'] ); break; case 3: $replacement = $this->l10n->t( '%1$s, %2$s and %3$s', - ['{' . $parameter . '1}', '{' . $parameter . '2}', '{' . $parameter . '3}'] + ['{' . $parameter . '3}', '{' . $parameter . '2}', '{' . $parameter . '1}'] ); break; case 4: $replacement = $this->l10n->t( '%1$s, %2$s, %3$s and %4$s', - ['{' . $parameter . '1}', '{' . $parameter . '2}', '{' . $parameter . '3}', '{' . $parameter . '4}'] + ['{' . $parameter . '4}', '{' . $parameter . '3}', '{' . $parameter . '2}', '{' . $parameter . '1}'] ); break; case 5: $replacement = $this->l10n->t( '%1$s, %2$s, %3$s, %4$s and %5$s', - ['{' . $parameter . '1}', '{' . $parameter . '2}', '{' . $parameter . '3}', '{' . $parameter . '4}', '{' . $parameter . '5}'] + ['{' . $parameter . '5}', '{' . $parameter . '4}', '{' . $parameter . '3}', '{' . $parameter . '2}', '{' . $parameter . '1}'] ); break; default: diff --git a/lib/private/Files/Cache/Cache.php b/lib/private/Files/Cache/Cache.php index 9b2cff62627..2b04226f20e 100644 --- a/lib/private/Files/Cache/Cache.php +++ b/lib/private/Files/Cache/Cache.php @@ -500,6 +500,7 @@ class Cache implements ICache { * @param string $sourcePath * @param string $targetPath * @throws \OC\DatabaseException + * @throws \Exception if the given storages have an invalid id */ public function moveFromCache(ICache $sourceCache, $sourcePath, $targetPath) { if ($sourceCache instanceof Cache) { @@ -514,6 +515,13 @@ class Cache implements ICache { list($sourceStorageId, $sourcePath) = $sourceCache->getMoveInfo($sourcePath); list($targetStorageId, $targetPath) = $this->getMoveInfo($targetPath); + if (is_null($sourceStorageId) || $sourceStorageId === false) { + throw new \Exception('Invalid source storage id: ' . $sourceStorageId); + } + if (is_null($targetStorageId) || $targetStorageId === false) { + throw new \Exception('Invalid target storage id: ' . $targetStorageId); + } + // sql for final update $moveSql = 'UPDATE `*PREFIX*filecache` SET `storage` = ?, `path` = ?, `path_hash` = ?, `name` = ?, `parent` =? WHERE `fileid` = ?'; diff --git a/lib/private/Files/Storage/Local.php b/lib/private/Files/Storage/Local.php index 80d48680be1..5597c0c64cc 100644 --- a/lib/private/Files/Storage/Local.php +++ b/lib/private/Files/Storage/Local.php @@ -369,9 +369,10 @@ class Local extends \OC\Files\Storage\Common { } if (substr($realPath, 0, $this->dataDirLength) === $this->realDataDir) { return $fullPath; - } else { - throw new ForbiddenException("Following symlinks is not allowed ('$fullPath' -> '$realPath' not inside '{$this->realDataDir}')", false); } + + \OCP\Util::writeLog('core', "Following symlinks is not allowed ('$fullPath' -> '$realPath' not inside '{$this->realDataDir}')", \OCP\Util::ERROR); + throw new ForbiddenException('Following symlinks is not allowed', false); } /** diff --git a/lib/private/Template/JSCombiner.php b/lib/private/Template/JSCombiner.php index 9f92813f905..0f30fb915f7 100644 --- a/lib/private/Template/JSCombiner.php +++ b/lib/private/Template/JSCombiner.php @@ -155,8 +155,15 @@ class JSCombiner { } try { + $gzipFile = $folder->getFile($fileName . '.gz'); + } catch (NotFoundException $e) { + $gzipFile = $folder->newFile($fileName . '.gz'); + } + + try { $cachedfile->putContent($res); $depFile->putContent(json_encode($deps)); + $gzipFile->putContent(gzencode($res, 9)); return true; } catch (NotPermittedException $e) { return false; diff --git a/lib/private/Template/SCSSCacher.php b/lib/private/Template/SCSSCacher.php index c12d8771513..df2e0232508 100644 --- a/lib/private/Template/SCSSCacher.php +++ b/lib/private/Template/SCSSCacher.php @@ -186,9 +186,18 @@ class SCSSCacher { return false; } + // Gzip file try { - $cachedfile->putContent($this->rebaseUrls($compiledScss, $webDir)); + $gzipFile = $folder->getFile($fileNameCSS . '.gz'); + } catch (NotFoundException $e) { + $gzipFile = $folder->newFile($fileNameCSS . '.gz'); + } + + try { + $data = $this->rebaseUrls($compiledScss, $webDir); + $cachedfile->putContent($data); $depFile->putContent(json_encode($scss->getParsedFiles())); + $gzipFile->putContent(gzencode($data, 9)); $this->logger->debug($webDir.'/'.$fileNameSCSS.' compiled and successfully cached', ['app' => 'core']); return true; } catch(NotPermittedException $e) { diff --git a/lib/private/legacy/response.php b/lib/private/legacy/response.php index 8937b56a707..115eb5baa68 100644 --- a/lib/private/legacy/response.php +++ b/lib/private/legacy/response.php @@ -253,7 +253,9 @@ class OC_Response { . 'img-src * data: blob:; ' . 'font-src \'self\' data:; ' . 'media-src *; ' - . 'connect-src *'; + . 'connect-src *; ' + . 'object-src \'none\'; ' + . 'base-uri \'self\'; '; header('Content-Security-Policy:' . $policy); header('X-Frame-Options: Sameorigin'); // Disallow iFraming from other domains diff --git a/lib/public/AppFramework/Http/EmptyContentSecurityPolicy.php b/lib/public/AppFramework/Http/EmptyContentSecurityPolicy.php index c53b5b2146c..09eb5a1c151 100644 --- a/lib/public/AppFramework/Http/EmptyContentSecurityPolicy.php +++ b/lib/public/AppFramework/Http/EmptyContentSecurityPolicy.php @@ -336,6 +336,7 @@ class EmptyContentSecurityPolicy { public function buildPolicy() { $policy = "default-src 'none';"; $policy .= "base-uri 'none';"; + $policy .= "manifest-src 'self';"; if(!empty($this->allowedScriptDomains) || $this->inlineScriptAllowed || $this->evalScriptAllowed) { $policy .= 'script-src '; diff --git a/settings/l10n/de.js b/settings/l10n/de.js index 5e58cdd5e7d..da6e13d69b1 100644 --- a/settings/l10n/de.js +++ b/settings/l10n/de.js @@ -321,6 +321,7 @@ OC.L10N.register( "Subscribe to our twitter channel!" : "Abonniere unseren Twitter-Kanal!", "Subscribe to our news feed!" : "Abonniere unseren RSS-Feed!", "Subscribe to our newsletter!" : "Abonniere unseren Newsletter!", + "Settings" : "Einstellungen", "Show storage location" : "Speicherort anzeigen", "Show last log in" : "Letzte Anmeldung anzeigen", "Show user backend" : "Benutzer-Backend anzeigen", diff --git a/settings/l10n/de.json b/settings/l10n/de.json index b0bf6cae15a..fe874b71f0b 100644 --- a/settings/l10n/de.json +++ b/settings/l10n/de.json @@ -319,6 +319,7 @@ "Subscribe to our twitter channel!" : "Abonniere unseren Twitter-Kanal!", "Subscribe to our news feed!" : "Abonniere unseren RSS-Feed!", "Subscribe to our newsletter!" : "Abonniere unseren Newsletter!", + "Settings" : "Einstellungen", "Show storage location" : "Speicherort anzeigen", "Show last log in" : "Letzte Anmeldung anzeigen", "Show user backend" : "Benutzer-Backend anzeigen", diff --git a/settings/l10n/de_DE.js b/settings/l10n/de_DE.js index 6f847ddf021..880bca6890d 100644 --- a/settings/l10n/de_DE.js +++ b/settings/l10n/de_DE.js @@ -321,6 +321,7 @@ OC.L10N.register( "Subscribe to our twitter channel!" : "Abonnieren Sie unseren Twitter-Kanal!", "Subscribe to our news feed!" : "Abonnieren Sie unseren RSS-Feed!", "Subscribe to our newsletter!" : "Abonnieren Sie unseren Newsletter!", + "Settings" : "Einstellungen", "Show storage location" : "Speicherort anzeigen", "Show last log in" : "Letzte Anmeldung anzeigen", "Show user backend" : "Benutzer-Backend anzeigen", diff --git a/settings/l10n/de_DE.json b/settings/l10n/de_DE.json index 3e1cc5dda8e..47d9ac7c9c8 100644 --- a/settings/l10n/de_DE.json +++ b/settings/l10n/de_DE.json @@ -319,6 +319,7 @@ "Subscribe to our twitter channel!" : "Abonnieren Sie unseren Twitter-Kanal!", "Subscribe to our news feed!" : "Abonnieren Sie unseren RSS-Feed!", "Subscribe to our newsletter!" : "Abonnieren Sie unseren Newsletter!", + "Settings" : "Einstellungen", "Show storage location" : "Speicherort anzeigen", "Show last log in" : "Letzte Anmeldung anzeigen", "Show user backend" : "Benutzer-Backend anzeigen", diff --git a/settings/l10n/es.js b/settings/l10n/es.js index 0fdb962705c..e460ee3e708 100644 --- a/settings/l10n/es.js +++ b/settings/l10n/es.js @@ -321,6 +321,7 @@ OC.L10N.register( "Subscribe to our twitter channel!" : "Suscríbete a nuestro canal de Twitter!", "Subscribe to our news feed!" : "¡Suscríbete a nuestro feed de noticias!", "Subscribe to our newsletter!" : "¡Suscríbete a nuestro boletín!", + "Settings" : "Configuración", "Show storage location" : "Mostrar la ubicación del almacenamiento", "Show last log in" : "Mostrar el último inicio de sesión", "Show user backend" : "Mostrar motor de usuario", diff --git a/settings/l10n/es.json b/settings/l10n/es.json index 2affd92c741..2a183f1c54b 100644 --- a/settings/l10n/es.json +++ b/settings/l10n/es.json @@ -319,6 +319,7 @@ "Subscribe to our twitter channel!" : "Suscríbete a nuestro canal de Twitter!", "Subscribe to our news feed!" : "¡Suscríbete a nuestro feed de noticias!", "Subscribe to our newsletter!" : "¡Suscríbete a nuestro boletín!", + "Settings" : "Configuración", "Show storage location" : "Mostrar la ubicación del almacenamiento", "Show last log in" : "Mostrar el último inicio de sesión", "Show user backend" : "Mostrar motor de usuario", diff --git a/settings/l10n/fr.js b/settings/l10n/fr.js index 5ebee2f2ff6..4c755041ea1 100644 --- a/settings/l10n/fr.js +++ b/settings/l10n/fr.js @@ -321,6 +321,7 @@ OC.L10N.register( "Subscribe to our twitter channel!" : "Enregistrez notre page twitter!", "Subscribe to our news feed!" : "Abonnez-vous à notre flux d'actualités!", "Subscribe to our newsletter!" : "Abonnez-vous à notre newsletter!", + "Settings" : "Paramètres", "Show storage location" : "Afficher l'emplacement du stockage", "Show last log in" : "Montrer la dernière connexion", "Show user backend" : "Montrer la source de l'identifiant", diff --git a/settings/l10n/fr.json b/settings/l10n/fr.json index 9d32a9ad0bf..81b913ad3e4 100644 --- a/settings/l10n/fr.json +++ b/settings/l10n/fr.json @@ -319,6 +319,7 @@ "Subscribe to our twitter channel!" : "Enregistrez notre page twitter!", "Subscribe to our news feed!" : "Abonnez-vous à notre flux d'actualités!", "Subscribe to our newsletter!" : "Abonnez-vous à notre newsletter!", + "Settings" : "Paramètres", "Show storage location" : "Afficher l'emplacement du stockage", "Show last log in" : "Montrer la dernière connexion", "Show user backend" : "Montrer la source de l'identifiant", diff --git a/settings/l10n/is.js b/settings/l10n/is.js index d6a5b00f8cb..8b4655c755e 100644 --- a/settings/l10n/is.js +++ b/settings/l10n/is.js @@ -8,6 +8,7 @@ OC.L10N.register( "No user supplied" : "Enginn notandi gefinn", "Unable to change password" : "Ekki tókst að breyta lykilorði", "Authentication error" : "Villa við auðkenningu", + "Please provide an admin recovery password; otherwise, all user data will be lost." : "Settu inn endurheimtulykilorð kerfisstjóra, annars munu öll notandagögn tapast.", "Wrong admin recovery password. Please check the password and try again." : "Rangt endurheimtulykilorð kerfisstjóra, athugaðu lykilorðið og reyndu aftur.", "Backend doesn't support password change, but the user's encryption key was successfully updated." : "Bakendi styður ekki breytingu á lykilorði, en það tókst að uppfæra dulritunarlykil notandans.", "installing and updating apps via the app store or Federated Cloud Sharing" : "uppsetning eða uppfærsla forrita úr forritabúð eða með skýjasambandi", @@ -320,6 +321,7 @@ OC.L10N.register( "Subscribe to our twitter channel!" : "Gerstu áskrifandi að twitter-rásinni okkar!", "Subscribe to our news feed!" : "Gerstu áskrifandi að fréttastraumi okkar!", "Subscribe to our newsletter!" : "Gerstu áskrifandi að fréttabréfinu okkar!", + "Settings" : "Stillingar", "Show storage location" : "Birta staðsetningu gagnageymslu", "Show last log in" : "Birta síðustu innskráningu", "Show user backend" : "Birta bakenda notanda", diff --git a/settings/l10n/is.json b/settings/l10n/is.json index 82690dccf96..853ef6bfc62 100644 --- a/settings/l10n/is.json +++ b/settings/l10n/is.json @@ -6,6 +6,7 @@ "No user supplied" : "Enginn notandi gefinn", "Unable to change password" : "Ekki tókst að breyta lykilorði", "Authentication error" : "Villa við auðkenningu", + "Please provide an admin recovery password; otherwise, all user data will be lost." : "Settu inn endurheimtulykilorð kerfisstjóra, annars munu öll notandagögn tapast.", "Wrong admin recovery password. Please check the password and try again." : "Rangt endurheimtulykilorð kerfisstjóra, athugaðu lykilorðið og reyndu aftur.", "Backend doesn't support password change, but the user's encryption key was successfully updated." : "Bakendi styður ekki breytingu á lykilorði, en það tókst að uppfæra dulritunarlykil notandans.", "installing and updating apps via the app store or Federated Cloud Sharing" : "uppsetning eða uppfærsla forrita úr forritabúð eða með skýjasambandi", @@ -318,6 +319,7 @@ "Subscribe to our twitter channel!" : "Gerstu áskrifandi að twitter-rásinni okkar!", "Subscribe to our news feed!" : "Gerstu áskrifandi að fréttastraumi okkar!", "Subscribe to our newsletter!" : "Gerstu áskrifandi að fréttabréfinu okkar!", + "Settings" : "Stillingar", "Show storage location" : "Birta staðsetningu gagnageymslu", "Show last log in" : "Birta síðustu innskráningu", "Show user backend" : "Birta bakenda notanda", diff --git a/settings/l10n/pl.js b/settings/l10n/pl.js index 33aa7d4a606..a1d69766114 100644 --- a/settings/l10n/pl.js +++ b/settings/l10n/pl.js @@ -321,6 +321,7 @@ OC.L10N.register( "Subscribe to our twitter channel!" : "Zapisz się do naszego kanału na Twitterze!", "Subscribe to our news feed!" : "Zapisz się do naszego kanału informacyjnego!", "Subscribe to our newsletter!" : "Zapisz się do naszego newslettera!", + "Settings" : "Ustawienia", "Show storage location" : "Pokaż miejsce przechowywania", "Show last log in" : "Pokaż ostatni login", "Show user backend" : "Pokaż moduł użytkownika", diff --git a/settings/l10n/pl.json b/settings/l10n/pl.json index fd674856036..2c3729f9cda 100644 --- a/settings/l10n/pl.json +++ b/settings/l10n/pl.json @@ -319,6 +319,7 @@ "Subscribe to our twitter channel!" : "Zapisz się do naszego kanału na Twitterze!", "Subscribe to our news feed!" : "Zapisz się do naszego kanału informacyjnego!", "Subscribe to our newsletter!" : "Zapisz się do naszego newslettera!", + "Settings" : "Ustawienia", "Show storage location" : "Pokaż miejsce przechowywania", "Show last log in" : "Pokaż ostatni login", "Show user backend" : "Pokaż moduł użytkownika", diff --git a/settings/l10n/ru.js b/settings/l10n/ru.js index 996088c323c..a68ee39e83e 100644 --- a/settings/l10n/ru.js +++ b/settings/l10n/ru.js @@ -321,6 +321,7 @@ OC.L10N.register( "Subscribe to our twitter channel!" : "Подпишитесь на наш twitter-канал!", "Subscribe to our news feed!" : "Подпишитесь на нашу ленту новостей!", "Subscribe to our newsletter!" : "Подписывайтесь на нашу новостную рассылку!", + "Settings" : "Настройки", "Show storage location" : "Показать местонахождение хранилища", "Show last log in" : "Показать последний вход в систему", "Show user backend" : "Показать механизм учёта пользователей", diff --git a/settings/l10n/ru.json b/settings/l10n/ru.json index 6a3d0c751d8..52b6ce97f00 100644 --- a/settings/l10n/ru.json +++ b/settings/l10n/ru.json @@ -319,6 +319,7 @@ "Subscribe to our twitter channel!" : "Подпишитесь на наш twitter-канал!", "Subscribe to our news feed!" : "Подпишитесь на нашу ленту новостей!", "Subscribe to our newsletter!" : "Подписывайтесь на нашу новостную рассылку!", + "Settings" : "Настройки", "Show storage location" : "Показать местонахождение хранилища", "Show last log in" : "Показать последний вход в систему", "Show user backend" : "Показать механизм учёта пользователей", diff --git a/settings/l10n/tr.js b/settings/l10n/tr.js index 33c11df641f..dcd4fbe32cd 100644 --- a/settings/l10n/tr.js +++ b/settings/l10n/tr.js @@ -321,6 +321,7 @@ OC.L10N.register( "Subscribe to our twitter channel!" : "Twitter kanalımıza abone olun!", "Subscribe to our news feed!" : "Haber akışımıza abone olun!", "Subscribe to our newsletter!" : " Bültenimize abone olun!", + "Settings" : "Ayarlar", "Show storage location" : "Depolama konumu görüntülensin", "Show last log in" : "Son oturum açma zamanı görüntülensin", "Show user backend" : "Kullanıcı arka ucu görüntülensin", diff --git a/settings/l10n/tr.json b/settings/l10n/tr.json index 973870f4a51..930ff54103c 100644 --- a/settings/l10n/tr.json +++ b/settings/l10n/tr.json @@ -319,6 +319,7 @@ "Subscribe to our twitter channel!" : "Twitter kanalımıza abone olun!", "Subscribe to our news feed!" : "Haber akışımıza abone olun!", "Subscribe to our newsletter!" : " Bültenimize abone olun!", + "Settings" : "Ayarlar", "Show storage location" : "Depolama konumu görüntülensin", "Show last log in" : "Son oturum açma zamanı görüntülensin", "Show user backend" : "Kullanıcı arka ucu görüntülensin", diff --git a/tests/Core/Controller/CssControllerTest.php b/tests/Core/Controller/CssControllerTest.php index 60fef9dddad..7fa358e056e 100644 --- a/tests/Core/Controller/CssControllerTest.php +++ b/tests/Core/Controller/CssControllerTest.php @@ -40,6 +40,9 @@ class CssControllerTest extends TestCase { /** @var IAppData|\PHPUnit_Framework_MockObject_MockObject */ private $appData; + /** @var IRequests|\PHPUnit_Framework_MockObject_MockObject */ + private $request; + /** @var CssController */ private $controller; @@ -52,9 +55,11 @@ class CssControllerTest extends TestCase { $timeFactory->method('getTime') ->willReturn(1337); + $this->request = $this->createMock(IRequest::class); + $this->controller = new CssController( 'core', - $this->createMock(IRequest::class), + $this->request, $this->appData, $timeFactory ); @@ -108,4 +113,65 @@ class CssControllerTest extends TestCase { $this->assertEquals($expected, $result); } + public function testGetGzipFile() { + $folder = $this->createMock(ISimpleFolder::class); + $gzipFile = $this->createMock(ISimpleFile::class); + $this->appData->method('getFolder') + ->with('myapp') + ->willReturn($folder); + + $folder->method('getFile') + ->with('file.css.gz') + ->willReturn($gzipFile); + + $this->request->method('getHeader') + ->with('Accept-Encoding') + ->willReturn('gzip, deflate'); + + $expected = new FileDisplayResponse($gzipFile, Http::STATUS_OK, ['Content-Type' => 'text/css']); + $expected->addHeader('Content-Encoding', 'gzip'); + $expected->cacheFor(86400); + $expires = new \DateTime(); + $expires->setTimestamp(1337); + $expires->add(new \DateInterval('PT24H')); + $expected->addHeader('Expires', $expires->format(\DateTime::RFC1123)); + $expected->addHeader('Pragma', 'cache'); + + $result = $this->controller->getCss('file.css', 'myapp'); + $this->assertEquals($expected, $result); + } + + public function testGetGzipFileNotFound() { + $folder = $this->createMock(ISimpleFolder::class); + $file = $this->createMock(ISimpleFile::class); + $this->appData->method('getFolder') + ->with('myapp') + ->willReturn($folder); + + $folder->method('getFile') + ->will($this->returnCallback( + function($fileName) use ($file) { + if ($fileName === 'file.css') { + return $file; + } + throw new NotFoundException(); + }) + ); + + $this->request->method('getHeader') + ->with('Accept-Encoding') + ->willReturn('gzip, deflate'); + + $expected = new FileDisplayResponse($file, Http::STATUS_OK, ['Content-Type' => 'text/css']); + $expected->cacheFor(86400); + $expires = new \DateTime(); + $expires->setTimestamp(1337); + $expires->add(new \DateInterval('PT24H')); + $expected->addHeader('Expires', $expires->format(\DateTime::RFC1123)); + $expected->addHeader('Pragma', 'cache'); + + $result = $this->controller->getCss('file.css', 'myapp'); + $this->assertEquals($expected, $result); + } + } diff --git a/tests/Core/Controller/JsControllerTest.php b/tests/Core/Controller/JsControllerTest.php index febb785f60d..8f48a7c3390 100644 --- a/tests/Core/Controller/JsControllerTest.php +++ b/tests/Core/Controller/JsControllerTest.php @@ -42,6 +42,9 @@ class JsControllerTest extends TestCase { /** @var JsController */ private $controller; + /** @var IRequest|\PHPUnit_Framework_MockObject_MockObject */ + private $request; + public function setUp() { parent::setUp(); @@ -51,9 +54,11 @@ class JsControllerTest extends TestCase { $timeFactory->method('getTime') ->willReturn(1337); + $this->request = $this->createMock(IRequest::class); + $this->controller = new JsController( 'core', - $this->createMock(IRequest::class), + $this->request, $this->appData, $timeFactory ); @@ -107,4 +112,65 @@ class JsControllerTest extends TestCase { $this->assertEquals($expected, $result); } + public function testGetGzipFile() { + $folder = $this->createMock(ISimpleFolder::class); + $gzipFile = $this->createMock(ISimpleFile::class); + $this->appData->method('getFolder') + ->with('myapp') + ->willReturn($folder); + + $folder->method('getFile') + ->with('file.js.gz') + ->willReturn($gzipFile); + + $this->request->method('getHeader') + ->with('Accept-Encoding') + ->willReturn('gzip, deflate'); + + $expected = new FileDisplayResponse($gzipFile, Http::STATUS_OK, ['Content-Type' => 'application/javascript']); + $expected->addHeader('Content-Encoding', 'gzip'); + $expected->cacheFor(86400); + $expires = new \DateTime(); + $expires->setTimestamp(1337); + $expires->add(new \DateInterval('PT24H')); + $expected->addHeader('Expires', $expires->format(\DateTime::RFC1123)); + $expected->addHeader('Pragma', 'cache'); + + $result = $this->controller->getJs('file.js', 'myapp'); + $this->assertEquals($expected, $result); + } + + public function testGetGzipFileNotFound() { + $folder = $this->createMock(ISimpleFolder::class); + $file = $this->createMock(ISimpleFile::class); + $this->appData->method('getFolder') + ->with('myapp') + ->willReturn($folder); + + $folder->method('getFile') + ->will($this->returnCallback( + function($fileName) use ($file) { + if ($fileName === 'file.js') { + return $file; + } + throw new NotFoundException(); + }) + ); + + $this->request->method('getHeader') + ->with('Accept-Encoding') + ->willReturn('gzip, deflate'); + + $expected = new FileDisplayResponse($file, Http::STATUS_OK, ['Content-Type' => 'application/javascript']); + $expected->cacheFor(86400); + $expires = new \DateTime(); + $expires->setTimestamp(1337); + $expires->add(new \DateInterval('PT24H')); + $expected->addHeader('Expires', $expires->format(\DateTime::RFC1123)); + $expected->addHeader('Pragma', 'cache'); + + $result = $this->controller->getJs('file.js', 'myapp'); + $this->assertEquals($expected, $result); + } + } diff --git a/tests/lib/AppFramework/Controller/ControllerTest.php b/tests/lib/AppFramework/Controller/ControllerTest.php index 9d14f3aace8..59e2904e740 100644 --- a/tests/lib/AppFramework/Controller/ControllerTest.php +++ b/tests/lib/AppFramework/Controller/ControllerTest.php @@ -184,7 +184,7 @@ class ControllerTest extends \Test\TestCase { 'test' => 'something', 'Cache-Control' => 'no-cache, no-store, must-revalidate', 'Content-Type' => 'application/json; charset=utf-8', - 'Content-Security-Policy' => "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'", + 'Content-Security-Policy' => "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'", ]; $response = $this->controller->customDataResponse(array('hi')); diff --git a/tests/lib/AppFramework/Http/ContentSecurityPolicyTest.php b/tests/lib/AppFramework/Http/ContentSecurityPolicyTest.php index fa46e596d76..503148d633a 100644 --- a/tests/lib/AppFramework/Http/ContentSecurityPolicyTest.php +++ b/tests/lib/AppFramework/Http/ContentSecurityPolicyTest.php @@ -28,19 +28,19 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDefault() { - $defaultPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $defaultPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->assertSame($defaultPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyScriptDomainValid() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' www.owncloud.com 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' www.owncloud.com 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyScriptDomainValidMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' www.owncloud.com www.owncloud.org 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' www.owncloud.com www.owncloud.org 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.org'); @@ -48,7 +48,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowScriptDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowScriptDomain('www.owncloud.com'); @@ -56,7 +56,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowScriptDomainMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' www.owncloud.com 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' www.owncloud.com 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowScriptDomain('www.owncloud.org'); @@ -64,7 +64,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowScriptDomainMultipleStacked() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowScriptDomain('www.owncloud.org')->disallowScriptDomain('www.owncloud.com'); @@ -72,14 +72,14 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyScriptAllowInline() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-inline' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-inline' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->allowInlineScript(true); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyScriptAllowInlineWithDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' www.owncloud.com 'unsafe-inline' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' www.owncloud.com 'unsafe-inline' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); $this->contentSecurityPolicy->allowInlineScript(true); @@ -87,7 +87,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyScriptDisallowInlineAndEval() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->allowInlineScript(false); $this->contentSecurityPolicy->allowEvalScript(false); @@ -95,14 +95,14 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyStyleDomainValid() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' www.owncloud.com 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' www.owncloud.com 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyStyleDomainValidMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' www.owncloud.com www.owncloud.org 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' www.owncloud.com www.owncloud.org 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.org'); @@ -110,7 +110,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowStyleDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowStyleDomain('www.owncloud.com'); @@ -118,7 +118,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowStyleDomainMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' www.owncloud.com 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' www.owncloud.com 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowStyleDomain('www.owncloud.org'); @@ -126,7 +126,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowStyleDomainMultipleStacked() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowStyleDomain('www.owncloud.org')->disallowStyleDomain('www.owncloud.com'); @@ -134,35 +134,35 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyStyleAllowInline() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->allowInlineStyle(true); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyStyleAllowInlineWithDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' www.owncloud.com 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' www.owncloud.com 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyStyleDisallowInline() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->allowInlineStyle(false); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyImageDomainValid() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob: www.owncloud.com;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob: www.owncloud.com;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.com'); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyImageDomainValidMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob: www.owncloud.com www.owncloud.org;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob: www.owncloud.com www.owncloud.org;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.com'); $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.org'); @@ -170,7 +170,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowImageDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowImageDomain('www.owncloud.com'); @@ -178,7 +178,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowImageDomainMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob: www.owncloud.com;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob: www.owncloud.com;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowImageDomain('www.owncloud.org'); @@ -186,7 +186,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowImageDomainMultipleStakes() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowImageDomain('www.owncloud.org')->disallowImageDomain('www.owncloud.com'); @@ -194,14 +194,14 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyFontDomainValid() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self' www.owncloud.com;connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self' www.owncloud.com;connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.com'); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyFontDomainValidMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self' www.owncloud.com www.owncloud.org;connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self' www.owncloud.com www.owncloud.org;connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.com'); $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.org'); @@ -209,7 +209,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowFontDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowFontDomain('www.owncloud.com'); @@ -217,7 +217,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowFontDomainMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self' www.owncloud.com;connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self' www.owncloud.com;connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowFontDomain('www.owncloud.org'); @@ -225,7 +225,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowFontDomainMultipleStakes() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowFontDomain('www.owncloud.org')->disallowFontDomain('www.owncloud.com'); @@ -233,14 +233,14 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyConnectDomainValid() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self' www.owncloud.com;media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self' www.owncloud.com;media-src 'self'"; $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.com'); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyConnectDomainValidMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self' www.owncloud.com www.owncloud.org;media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self' www.owncloud.com www.owncloud.org;media-src 'self'"; $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.com'); $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.org'); @@ -248,7 +248,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowConnectDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowConnectDomain('www.owncloud.com'); @@ -256,7 +256,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowConnectDomainMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self' www.owncloud.com;media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self' www.owncloud.com;media-src 'self'"; $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowConnectDomain('www.owncloud.org'); @@ -264,7 +264,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowConnectDomainMultipleStakes() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowConnectDomain('www.owncloud.org')->disallowConnectDomain('www.owncloud.com'); @@ -272,14 +272,14 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyMediaDomainValid() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self' www.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self' www.owncloud.com"; $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.com'); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyMediaDomainValidMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self' www.owncloud.com www.owncloud.org"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self' www.owncloud.com www.owncloud.org"; $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.com'); $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.org'); @@ -287,7 +287,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowMediaDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowMediaDomain('www.owncloud.com'); @@ -295,7 +295,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowMediaDomainMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self' www.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self' www.owncloud.com"; $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowMediaDomain('www.owncloud.org'); @@ -303,7 +303,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowMediaDomainMultipleStakes() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowMediaDomain('www.owncloud.org')->disallowMediaDomain('www.owncloud.com'); @@ -311,14 +311,14 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyObjectDomainValid() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';object-src www.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';object-src www.owncloud.com"; $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.com'); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyObjectDomainValidMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';object-src www.owncloud.com www.owncloud.org"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';object-src www.owncloud.com www.owncloud.org"; $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.com'); $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.org'); @@ -326,7 +326,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowObjectDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowObjectDomain('www.owncloud.com'); @@ -334,7 +334,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowObjectDomainMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';object-src www.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';object-src www.owncloud.com"; $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowObjectDomain('www.owncloud.org'); @@ -342,7 +342,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowObjectDomainMultipleStakes() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowObjectDomain('www.owncloud.org')->disallowObjectDomain('www.owncloud.com'); @@ -350,14 +350,14 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetAllowedFrameDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';frame-src www.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';frame-src www.owncloud.com"; $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.com'); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyFrameDomainValidMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';frame-src www.owncloud.com www.owncloud.org"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';frame-src www.owncloud.com www.owncloud.org"; $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.com'); $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.org'); @@ -365,7 +365,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowFrameDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowFrameDomain('www.owncloud.com'); @@ -373,7 +373,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowFrameDomainMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';frame-src www.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';frame-src www.owncloud.com"; $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowFrameDomain('www.owncloud.org'); @@ -381,7 +381,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowFrameDomainMultipleStakes() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowFrameDomain('www.owncloud.org')->disallowFrameDomain('www.owncloud.com'); @@ -389,14 +389,14 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetAllowedChildSrcDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';child-src child.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';child-src child.owncloud.com"; $this->contentSecurityPolicy->addAllowedChildSrcDomain('child.owncloud.com'); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyChildSrcValidMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';child-src child.owncloud.com child.owncloud.org"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';child-src child.owncloud.com child.owncloud.org"; $this->contentSecurityPolicy->addAllowedChildSrcDomain('child.owncloud.com'); $this->contentSecurityPolicy->addAllowedChildSrcDomain('child.owncloud.org'); @@ -404,7 +404,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowChildSrcDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedChildSrcDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowChildSrcDomain('www.owncloud.com'); @@ -412,7 +412,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowChildSrcDomainMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';child-src www.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';child-src www.owncloud.com"; $this->contentSecurityPolicy->addAllowedChildSrcDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowChildSrcDomain('www.owncloud.org'); @@ -420,7 +420,7 @@ class ContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowChildSrcDomainMultipleStakes() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->contentSecurityPolicy->addAllowedChildSrcDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowChildSrcDomain('www.owncloud.org')->disallowChildSrcDomain('www.owncloud.com'); diff --git a/tests/lib/AppFramework/Http/DataResponseTest.php b/tests/lib/AppFramework/Http/DataResponseTest.php index bbd23c874d7..5b5eda8f11d 100644 --- a/tests/lib/AppFramework/Http/DataResponseTest.php +++ b/tests/lib/AppFramework/Http/DataResponseTest.php @@ -68,7 +68,7 @@ class DataResponseTest extends \Test\TestCase { $expectedHeaders = [ 'Cache-Control' => 'no-cache, no-store, must-revalidate', - 'Content-Security-Policy' => "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'", + 'Content-Security-Policy' => "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'", ]; $expectedHeaders = array_merge($expectedHeaders, $headers); diff --git a/tests/lib/AppFramework/Http/EmptyContentSecurityPolicyTest.php b/tests/lib/AppFramework/Http/EmptyContentSecurityPolicyTest.php index ee4ec6c368c..7c30df730d3 100644 --- a/tests/lib/AppFramework/Http/EmptyContentSecurityPolicyTest.php +++ b/tests/lib/AppFramework/Http/EmptyContentSecurityPolicyTest.php @@ -28,19 +28,19 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDefault() { - $defaultPolicy = "default-src 'none';base-uri 'none'"; + $defaultPolicy = "default-src 'none';base-uri 'none';manifest-src 'self'"; $this->assertSame($defaultPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyScriptDomainValid() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src www.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src www.owncloud.com"; $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyScriptDomainValidMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src www.owncloud.com www.owncloud.org"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src www.owncloud.com www.owncloud.org"; $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.org'); @@ -48,7 +48,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowScriptDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self'"; $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowScriptDomain('www.owncloud.com'); @@ -56,7 +56,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowScriptDomainMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src www.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src www.owncloud.com"; $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowScriptDomain('www.owncloud.org'); @@ -64,7 +64,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowScriptDomainMultipleStacked() { - $expectedPolicy = "default-src 'none';base-uri 'none'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self'"; $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowScriptDomain('www.owncloud.org')->disallowScriptDomain('www.owncloud.com'); @@ -72,14 +72,14 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyScriptAllowInline() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'unsafe-inline'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'unsafe-inline'"; $this->contentSecurityPolicy->allowInlineScript(true); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyScriptAllowInlineWithDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src www.owncloud.com 'unsafe-inline'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src www.owncloud.com 'unsafe-inline'"; $this->contentSecurityPolicy->addAllowedScriptDomain('www.owncloud.com'); $this->contentSecurityPolicy->allowInlineScript(true); @@ -87,7 +87,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyScriptAllowInlineAndEval() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'unsafe-inline' 'unsafe-eval'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'unsafe-inline' 'unsafe-eval'"; $this->contentSecurityPolicy->allowInlineScript(true); $this->contentSecurityPolicy->allowEvalScript(true); @@ -95,14 +95,14 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyStyleDomainValid() { - $expectedPolicy = "default-src 'none';base-uri 'none';style-src www.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';style-src www.owncloud.com"; $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyStyleDomainValidMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';style-src www.owncloud.com www.owncloud.org"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';style-src www.owncloud.com www.owncloud.org"; $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.org'); @@ -110,7 +110,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowStyleDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self'"; $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowStyleDomain('www.owncloud.com'); @@ -118,7 +118,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowStyleDomainMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';style-src www.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';style-src www.owncloud.com"; $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowStyleDomain('www.owncloud.org'); @@ -126,7 +126,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowStyleDomainMultipleStacked() { - $expectedPolicy = "default-src 'none';base-uri 'none'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self'"; $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowStyleDomain('www.owncloud.org')->disallowStyleDomain('www.owncloud.com'); @@ -134,14 +134,14 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyStyleAllowInline() { - $expectedPolicy = "default-src 'none';base-uri 'none';style-src 'unsafe-inline'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';style-src 'unsafe-inline'"; $this->contentSecurityPolicy->allowInlineStyle(true); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyStyleAllowInlineWithDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none';style-src www.owncloud.com 'unsafe-inline'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';style-src www.owncloud.com 'unsafe-inline'"; $this->contentSecurityPolicy->addAllowedStyleDomain('www.owncloud.com'); $this->contentSecurityPolicy->allowInlineStyle(true); @@ -149,21 +149,21 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyStyleDisallowInline() { - $expectedPolicy = "default-src 'none';base-uri 'none'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self'"; $this->contentSecurityPolicy->allowInlineStyle(false); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyImageDomainValid() { - $expectedPolicy = "default-src 'none';base-uri 'none';img-src www.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';img-src www.owncloud.com"; $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.com'); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyImageDomainValidMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';img-src www.owncloud.com www.owncloud.org"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';img-src www.owncloud.com www.owncloud.org"; $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.com'); $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.org'); @@ -171,7 +171,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowImageDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self'"; $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowImageDomain('www.owncloud.com'); @@ -179,7 +179,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowImageDomainMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';img-src www.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';img-src www.owncloud.com"; $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowImageDomain('www.owncloud.org'); @@ -187,7 +187,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowImageDomainMultipleStakes() { - $expectedPolicy = "default-src 'none';base-uri 'none'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self'"; $this->contentSecurityPolicy->addAllowedImageDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowImageDomain('www.owncloud.org')->disallowImageDomain('www.owncloud.com'); @@ -195,14 +195,14 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyFontDomainValid() { - $expectedPolicy = "default-src 'none';base-uri 'none';font-src www.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';font-src www.owncloud.com"; $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.com'); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyFontDomainValidMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';font-src www.owncloud.com www.owncloud.org"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';font-src www.owncloud.com www.owncloud.org"; $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.com'); $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.org'); @@ -210,7 +210,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowFontDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self'"; $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowFontDomain('www.owncloud.com'); @@ -218,7 +218,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowFontDomainMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';font-src www.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';font-src www.owncloud.com"; $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowFontDomain('www.owncloud.org'); @@ -226,7 +226,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowFontDomainMultipleStakes() { - $expectedPolicy = "default-src 'none';base-uri 'none'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self'"; $this->contentSecurityPolicy->addAllowedFontDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowFontDomain('www.owncloud.org')->disallowFontDomain('www.owncloud.com'); @@ -234,14 +234,14 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyConnectDomainValid() { - $expectedPolicy = "default-src 'none';base-uri 'none';connect-src www.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';connect-src www.owncloud.com"; $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.com'); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyConnectDomainValidMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';connect-src www.owncloud.com www.owncloud.org"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';connect-src www.owncloud.com www.owncloud.org"; $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.com'); $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.org'); @@ -249,7 +249,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowConnectDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self'"; $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowConnectDomain('www.owncloud.com'); @@ -257,7 +257,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowConnectDomainMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';connect-src www.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';connect-src www.owncloud.com"; $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowConnectDomain('www.owncloud.org'); @@ -265,7 +265,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowConnectDomainMultipleStakes() { - $expectedPolicy = "default-src 'none';base-uri 'none'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self'"; $this->contentSecurityPolicy->addAllowedConnectDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowConnectDomain('www.owncloud.org')->disallowConnectDomain('www.owncloud.com'); @@ -273,14 +273,14 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyMediaDomainValid() { - $expectedPolicy = "default-src 'none';base-uri 'none';media-src www.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';media-src www.owncloud.com"; $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.com'); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyMediaDomainValidMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';media-src www.owncloud.com www.owncloud.org"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';media-src www.owncloud.com www.owncloud.org"; $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.com'); $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.org'); @@ -288,7 +288,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowMediaDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self'"; $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowMediaDomain('www.owncloud.com'); @@ -296,7 +296,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowMediaDomainMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';media-src www.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';media-src www.owncloud.com"; $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowMediaDomain('www.owncloud.org'); @@ -304,7 +304,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowMediaDomainMultipleStakes() { - $expectedPolicy = "default-src 'none';base-uri 'none'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self'"; $this->contentSecurityPolicy->addAllowedMediaDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowMediaDomain('www.owncloud.org')->disallowMediaDomain('www.owncloud.com'); @@ -312,14 +312,14 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyObjectDomainValid() { - $expectedPolicy = "default-src 'none';base-uri 'none';object-src www.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';object-src www.owncloud.com"; $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.com'); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyObjectDomainValidMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';object-src www.owncloud.com www.owncloud.org"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';object-src www.owncloud.com www.owncloud.org"; $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.com'); $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.org'); @@ -327,7 +327,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowObjectDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self'"; $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowObjectDomain('www.owncloud.com'); @@ -335,7 +335,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowObjectDomainMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';object-src www.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';object-src www.owncloud.com"; $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowObjectDomain('www.owncloud.org'); @@ -343,7 +343,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowObjectDomainMultipleStakes() { - $expectedPolicy = "default-src 'none';base-uri 'none'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self'"; $this->contentSecurityPolicy->addAllowedObjectDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowObjectDomain('www.owncloud.org')->disallowObjectDomain('www.owncloud.com'); @@ -351,14 +351,14 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetAllowedFrameDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none';frame-src www.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';frame-src www.owncloud.com"; $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.com'); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyFrameDomainValidMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';frame-src www.owncloud.com www.owncloud.org"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';frame-src www.owncloud.com www.owncloud.org"; $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.com'); $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.org'); @@ -366,7 +366,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowFrameDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self'"; $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowFrameDomain('www.owncloud.com'); @@ -374,7 +374,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowFrameDomainMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';frame-src www.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';frame-src www.owncloud.com"; $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowFrameDomain('www.owncloud.org'); @@ -382,7 +382,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowFrameDomainMultipleStakes() { - $expectedPolicy = "default-src 'none';base-uri 'none'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self'"; $this->contentSecurityPolicy->addAllowedFrameDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowFrameDomain('www.owncloud.org')->disallowFrameDomain('www.owncloud.com'); @@ -390,14 +390,14 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetAllowedChildSrcDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none';child-src child.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';child-src child.owncloud.com"; $this->contentSecurityPolicy->addAllowedChildSrcDomain('child.owncloud.com'); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); } public function testGetPolicyChildSrcValidMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';child-src child.owncloud.com child.owncloud.org"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';child-src child.owncloud.com child.owncloud.org"; $this->contentSecurityPolicy->addAllowedChildSrcDomain('child.owncloud.com'); $this->contentSecurityPolicy->addAllowedChildSrcDomain('child.owncloud.org'); @@ -405,7 +405,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowChildSrcDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self'"; $this->contentSecurityPolicy->addAllowedChildSrcDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowChildSrcDomain('www.owncloud.com'); @@ -413,7 +413,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowChildSrcDomainMultiple() { - $expectedPolicy = "default-src 'none';base-uri 'none';child-src www.owncloud.com"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';child-src www.owncloud.com"; $this->contentSecurityPolicy->addAllowedChildSrcDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowChildSrcDomain('www.owncloud.org'); @@ -421,7 +421,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyDisallowChildSrcDomainMultipleStakes() { - $expectedPolicy = "default-src 'none';base-uri 'none'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self'"; $this->contentSecurityPolicy->addAllowedChildSrcDomain('www.owncloud.com'); $this->contentSecurityPolicy->disallowChildSrcDomain('www.owncloud.org')->disallowChildSrcDomain('www.owncloud.com'); @@ -429,7 +429,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyWithJsNonceAndScriptDomains() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'nonce-TXlKc05vbmNl' www.nextcloud.com www.nextcloud.org"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'nonce-TXlKc05vbmNl' www.nextcloud.com www.nextcloud.org"; $this->contentSecurityPolicy->addAllowedScriptDomain('www.nextcloud.com'); $this->contentSecurityPolicy->useJsNonce('MyJsNonce'); @@ -438,7 +438,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyWithJsNonceAndSelfScriptDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'nonce-TXlKc05vbmNl'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'nonce-TXlKc05vbmNl'"; $this->contentSecurityPolicy->useJsNonce('MyJsNonce'); $this->contentSecurityPolicy->addAllowedScriptDomain("'self'"); @@ -446,7 +446,7 @@ class EmptyContentSecurityPolicyTest extends \Test\TestCase { } public function testGetPolicyWithoutJsNonceAndSelfScriptDomain() { - $expectedPolicy = "default-src 'none';base-uri 'none';script-src 'self'"; + $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self'"; $this->contentSecurityPolicy->addAllowedScriptDomain("'self'"); $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy()); diff --git a/tests/lib/AppFramework/Http/ResponseTest.php b/tests/lib/AppFramework/Http/ResponseTest.php index 0331bb42c01..4840a5f94c3 100644 --- a/tests/lib/AppFramework/Http/ResponseTest.php +++ b/tests/lib/AppFramework/Http/ResponseTest.php @@ -58,14 +58,14 @@ class ResponseTest extends \Test\TestCase { $this->childResponse->setHeaders($expected); $headers = $this->childResponse->getHeaders(); - $expected['Content-Security-Policy'] = "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; + $expected['Content-Security-Policy'] = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'"; $this->assertEquals($expected, $headers); } public function testOverwriteCsp() { $expected = [ - 'Content-Security-Policy' => "default-src 'none';base-uri 'none';script-src 'self' 'unsafe-inline' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self'", + 'Content-Security-Policy' => "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-inline' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self';font-src 'self';connect-src 'self';media-src 'self'", ]; $policy = new Http\ContentSecurityPolicy(); $policy->allowInlineScript(true); diff --git a/tests/lib/Security/CSP/ContentSecurityPolicyManagerTest.php b/tests/lib/Security/CSP/ContentSecurityPolicyManagerTest.php index 4d70d4fa28f..f0fb1610d98 100644 --- a/tests/lib/Security/CSP/ContentSecurityPolicyManagerTest.php +++ b/tests/lib/Security/CSP/ContentSecurityPolicyManagerTest.php @@ -60,7 +60,7 @@ class ContentSecurityPolicyManagerTest extends \Test\TestCase { $expected->addAllowedImageDomain('anotherdomain.de'); $expected->addAllowedImageDomain('example.org'); $expected->addAllowedChildSrcDomain('childdomain'); - $expectedStringPolicy = 'default-src \'none\';base-uri \'none\';script-src \'self\' \'unsafe-inline\' \'unsafe-eval\';style-src \'self\' \'unsafe-inline\';img-src \'self\' data: blob: anotherdomain.de example.org;font-src \'self\' mydomain.com example.com anotherFontDomain;connect-src \'self\';media-src \'self\';child-src childdomain'; + $expectedStringPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-inline' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob: anotherdomain.de example.org;font-src 'self' mydomain.com example.com anotherFontDomain;connect-src 'self';media-src 'self';child-src childdomain"; $this->assertEquals($expected, $this->contentSecurityPolicyManager->getDefaultPolicy()); $this->assertSame($expectedStringPolicy, $this->contentSecurityPolicyManager->getDefaultPolicy()->buildPolicy()); diff --git a/tests/lib/Template/JSCombinerTest.php b/tests/lib/Template/JSCombinerTest.php index 7b09b879225..1e6234a062c 100644 --- a/tests/lib/Template/JSCombinerTest.php +++ b/tests/lib/Template/JSCombinerTest.php @@ -22,6 +22,7 @@ */ namespace Test\Template; +use function foo\func; use OC\SystemConfig; use OC\Template\JSCombiner; use OCP\Files\IAppData; @@ -100,17 +101,18 @@ class JSCombinerTest extends \Test\TestCase { $this->appData->expects($this->once())->method('getFolder')->with('awesomeapp')->willThrowException(new NotFoundException()); $this->appData->expects($this->once())->method('newFolder')->with('awesomeapp')->willReturn($folder); $file = $this->createMock(ISimpleFile::class); + $gzfile = $this->createMock(ISimpleFile::class); $fileDeps = $this->createMock(ISimpleFile::class); $folder->method('getFile') - ->will($this->returnCallback(function($path) use ($file) { + ->will($this->returnCallback(function($path) use ($file, $gzfile) { if ($path === 'combine.js') { return $file; - } - - if ($path === 'combine.js.deps') { + } else if ($path === 'combine.js.deps') { throw new NotFoundException(); + } else if ($path === 'combine.js.gz') { + return $gzfile; } $this->fail(); })); @@ -137,17 +139,17 @@ class JSCombinerTest extends \Test\TestCase { $folder = $this->createMock(ISimpleFolder::class); $this->appData->expects($this->once())->method('getFolder')->with('awesomeapp')->willReturn($folder); $file = $this->createMock(ISimpleFile::class); - $fileDeps = $this->createMock(ISimpleFile::class); + $gzfile = $this->createMock(ISimpleFile::class); $folder->method('getFile') - ->will($this->returnCallback(function($path) use ($file) { + ->will($this->returnCallback(function($path) use ($file, $gzfile) { if ($path === 'combine.js') { return $file; - } - - if ($path === 'combine.js.deps') { + } else if ($path === 'combine.js.deps') { throw new NotFoundException(); + } else if ($path === 'combine.js.gz') { + return $gzfile; } $this->fail(); })); @@ -288,16 +290,28 @@ class JSCombinerTest extends \Test\TestCase { $folder = $this->createMock(ISimpleFolder::class); $file = $this->createMock(ISimpleFile::class); $depsFile = $this->createMock(ISimpleFile::class); + $gzFile = $this->createMock(ISimpleFile::class); $path = __DIR__ . '/data/'; - $folder->expects($this->at(0))->method('getFile')->with($fileName)->willThrowException(new NotFoundException()); - $folder->expects($this->at(1))->method('newFile')->with($fileName)->willReturn($file); - $folder->expects($this->at(2))->method('getFile')->with($fileName . '.deps')->willThrowException(new NotFoundException()); - $folder->expects($this->at(3))->method('newFile')->with($fileName . '.deps')->willReturn($depsFile); + $folder->method('getFile')->willThrowException(new NotFoundException()); + + $folder->method('newFile')->will($this->returnCallback( + function ($filename) use ($file, $depsFile, $gzFile) { + if ($filename === 'combine.js') { + return $file; + } else if ($filename === 'combine.js.deps') { + return $depsFile; + } else if ($filename === 'combine.js.gz') { + return $gzFile; + } + $this->fail(); + } + )); $file->expects($this->once())->method('putContent'); $depsFile->expects($this->once())->method('putContent'); + $gzFile->expects($this->once())->method('putContent'); $actual = self::invokePrivate($this->jsCombiner, 'cache', [$path, 'combine.json', $folder]); $this->assertTrue($actual); @@ -309,14 +323,26 @@ class JSCombinerTest extends \Test\TestCase { $folder = $this->createMock(ISimpleFolder::class); $file = $this->createMock(ISimpleFile::class); $depsFile = $this->createMock(ISimpleFile::class); + $gzFile = $this->createMock(ISimpleFile::class); $path = __DIR__ . '/data/'; - $folder->expects($this->at(0))->method('getFile')->with($fileName)->willReturn($file); - $folder->expects($this->at(1))->method('getFile')->with($fileName . '.deps')->willReturn($depsFile); + $folder->method('getFile')->will($this->returnCallback( + function ($filename) use ($file, $depsFile, $gzFile) { + if ($filename === 'combine.js') { + return $file; + } else if ($filename === 'combine.js.deps') { + return $depsFile; + } else if ($filename === 'combine.js.gz') { + return $gzFile; + } + $this->fail(); + } + )); $file->expects($this->once())->method('putContent'); $depsFile->expects($this->once())->method('putContent'); + $gzFile->expects($this->once())->method('putContent'); $actual = self::invokePrivate($this->jsCombiner, 'cache', [$path, 'combine.json', $folder]); $this->assertTrue($actual); @@ -364,11 +390,23 @@ var b = \'world\'; $folder = $this->createMock(ISimpleFolder::class); $file = $this->createMock(ISimpleFile::class); $depsFile = $this->createMock(ISimpleFile::class); + $gzFile = $this->createMock(ISimpleFile::class); $path = __DIR__ . '/data/'; - $folder->expects($this->at(0))->method('getFile')->with($fileName)->willReturn($file); - $folder->expects($this->at(1))->method('getFile')->with($fileName . '.deps')->willReturn($depsFile); + + $folder->method('getFile')->will($this->returnCallback( + function ($filename) use ($file, $depsFile, $gzFile) { + if ($filename === 'combine.js') { + return $file; + } else if ($filename === 'combine.js.deps') { + return $depsFile; + } else if ($filename === 'combine.js.gz') { + return $gzFile; + } + $this->fail(); + } + )); $file->expects($this->at(0)) ->method('putContent') @@ -385,6 +423,17 @@ var b = \'world\'; return array_key_exists(__DIR__ . '/data//1.js', $deps) && array_key_exists(__DIR__ . '/data//2.js', $deps); })); + $gzFile->expects($this->at(0))->method('putContent')->with($this->callback( + function ($content) { + return gzdecode($content) === 'var a = \'hello\'; + + +var b = \'world\'; + + +'; + } + )); $actual = self::invokePrivate($this->jsCombiner, 'cache', [$path, 'combine.json', $folder]); $this->assertTrue($actual); diff --git a/tests/lib/Template/SCSSCacherTest.php b/tests/lib/Template/SCSSCacherTest.php index 898ea89cf40..887fa1ed605 100644 --- a/tests/lib/Template/SCSSCacherTest.php +++ b/tests/lib/Template/SCSSCacherTest.php @@ -73,13 +73,16 @@ class SCSSCacherTest extends \Test\TestCase { $file = $this->createMock(ISimpleFile::class); $file->expects($this->any())->method('getSize')->willReturn(1); $fileDeps = $this->createMock(ISimpleFile::class); + $gzfile = $this->createMock(ISimpleFile::class); $folder->method('getFile') - ->will($this->returnCallback(function($path) use ($file) { + ->will($this->returnCallback(function($path) use ($file, $gzfile) { if ($path === 'styles.css') { return $file; } else if ($path === 'styles.css.deps') { throw new NotFoundException(); + } else if ($path === 'styles.css.gz') { + return $gzfile; } else { $this->fail(); } @@ -99,14 +102,17 @@ class SCSSCacherTest extends \Test\TestCase { $file = $this->createMock(ISimpleFile::class); $file->expects($this->any())->method('getSize')->willReturn(1); $fileDeps = $this->createMock(ISimpleFile::class); + $gzfile = $this->createMock(ISimpleFile::class); $folder->method('getFile') - ->will($this->returnCallback(function($path) use ($file) { + ->will($this->returnCallback(function($path) use ($file, $gzfile) { if ($path === 'styles.css') { return $file; } else if ($path === 'styles.css.deps') { throw new NotFoundException(); - } else { + } else if ($path === 'styles.css.gz') { + return $gzfile; + }else { $this->fail(); } })); @@ -211,17 +217,26 @@ class SCSSCacherTest extends \Test\TestCase { $folder = $this->createMock(ISimpleFolder::class); $file = $this->createMock(ISimpleFile::class); $depsFile = $this->createMock(ISimpleFile::class); + $gzipFile = $this->createMock(ISimpleFile::class); $webDir = "core/css"; $path = \OC::$SERVERROOT . '/core/css/'; - $folder->expects($this->at(0))->method('getFile')->with($fileNameCSS)->willThrowException(new NotFoundException()); - $folder->expects($this->at(1))->method('newFile')->with($fileNameCSS)->willReturn($file); - $folder->expects($this->at(2))->method('getFile')->with($fileNameCSS . '.deps')->willThrowException(new NotFoundException()); - $folder->expects($this->at(3))->method('newFile')->with($fileNameCSS . '.deps')->willReturn($depsFile); + $folder->method('getFile')->willThrowException(new NotFoundException()); + $folder->method('newFile')->will($this->returnCallback(function($fileName) use ($file, $depsFile, $gzipFile) { + if ($fileName === 'styles.css') { + return $file; + } else if ($fileName === 'styles.css.deps') { + return $depsFile; + } else if ($fileName === 'styles.css.gz') { + return $gzipFile; + } + throw new \Exception(); + })); $file->expects($this->once())->method('putContent'); $depsFile->expects($this->once())->method('putContent'); + $gzipFile->expects($this->once())->method('putContent'); $actual = self::invokePrivate($this->scssCacher, 'cache', [$path, $fileNameCSS, $fileNameSCSS, $folder, $webDir]); $this->assertTrue($actual); @@ -233,15 +248,25 @@ class SCSSCacherTest extends \Test\TestCase { $folder = $this->createMock(ISimpleFolder::class); $file = $this->createMock(ISimpleFile::class); $depsFile = $this->createMock(ISimpleFile::class); + $gzipFile = $this->createMock(ISimpleFile::class); $webDir = "core/css"; $path = \OC::$SERVERROOT; - $folder->expects($this->at(0))->method('getFile')->with($fileNameCSS)->willReturn($file); - $folder->expects($this->at(1))->method('getFile')->with($fileNameCSS . '.deps')->willReturn($depsFile); + $folder->method('getFile')->will($this->returnCallback(function($fileName) use ($file, $depsFile, $gzipFile) { + if ($fileName === 'styles.css') { + return $file; + } else if ($fileName === 'styles.css.deps') { + return $depsFile; + } else if ($fileName === 'styles.css.gz') { + return $gzipFile; + } + throw new \Exception(); + })); $file->expects($this->once())->method('putContent'); $depsFile->expects($this->once())->method('putContent'); + $gzipFile->expects($this->once())->method('putContent'); $actual = self::invokePrivate($this->scssCacher, 'cache', [$path, $fileNameCSS, $fileNameSCSS, $folder, $webDir]); $this->assertTrue($actual); @@ -253,12 +278,21 @@ class SCSSCacherTest extends \Test\TestCase { $folder = $this->createMock(ISimpleFolder::class); $file = $this->createMock(ISimpleFile::class); $depsFile = $this->createMock(ISimpleFile::class); + $gzipFile = $this->createMock(ISimpleFile::class); $webDir = "tests/data/scss"; $path = \OC::$SERVERROOT . $webDir; - $folder->expects($this->at(0))->method('getFile')->with($fileNameCSS)->willReturn($file); - $folder->expects($this->at(1))->method('getFile')->with($fileNameCSS . '.deps')->willReturn($depsFile); + $folder->method('getFile')->will($this->returnCallback(function($fileName) use ($file, $depsFile, $gzipFile) { + if ($fileName === 'styles-success.css') { + return $file; + } else if ($fileName === 'styles-success.css.deps') { + return $depsFile; + } else if ($fileName === 'styles-success.css.gz') { + return $gzipFile; + } + throw new \Exception(); + })); $file->expects($this->at(0))->method('putContent')->with($this->callback( function ($content){ @@ -270,6 +304,11 @@ class SCSSCacherTest extends \Test\TestCase { return array_key_exists(\OC::$SERVERROOT . '/core/css/variables.scss', $deps) && array_key_exists(\OC::$SERVERROOT . '/tests/data/scss/styles-success.scss', $deps); })); + $gzipFile->expects($this->at(0))->method('putContent')->with($this->callback( + function ($content) { + return gzdecode($content) === 'body{background-color:#0082c9}'; + } + )); $actual = self::invokePrivate($this->scssCacher, 'cache', [$path, $fileNameCSS, $fileNameSCSS, $folder, $webDir]); $this->assertTrue($actual); |