diff options
29 files changed, 311 insertions, 447 deletions
diff --git a/apps/dav/appinfo/info.xml b/apps/dav/appinfo/info.xml index 314391a1448..0024e41e753 100644 --- a/apps/dav/appinfo/info.xml +++ b/apps/dav/appinfo/info.xml @@ -22,12 +22,8 @@ </background-jobs> <repair-steps> <post-migration> - <step>OCA\DAV\Migration\Classification</step> <step>OCA\DAV\Migration\FixBirthdayCalendarComponent</step> </post-migration> - <live-migration> - <step>OCA\DAV\Migration\GenerateBirthdays</step> - </live-migration> </repair-steps> <commands> <command>OCA\DAV\Command\CreateAddressBook</command> diff --git a/apps/dav/lib/CardDAV/Converter.php b/apps/dav/lib/CardDAV/Converter.php index 065c5494ec3..ba0c4c2a2d5 100644 --- a/apps/dav/lib/CardDAV/Converter.php +++ b/apps/dav/lib/CardDAV/Converter.php @@ -71,7 +71,7 @@ class Converter { break; case AccountManager::PROPERTY_AVATAR: if ($image !== null) { - $vCard->add('PHOTO', $image->data(), ['ENCODING' => 'b', 'TYPE' => $image->mimeType()]); + $vCard->add('PHOTO', 'data:'.$image->mimeType().';base64,' . base64_encode($image->data())); } break; case AccountManager::PROPERTY_EMAIL: diff --git a/apps/dav/lib/Migration/Classification.php b/apps/dav/lib/Migration/Classification.php deleted file mode 100644 index a18646023c8..00000000000 --- a/apps/dav/lib/Migration/Classification.php +++ /dev/null @@ -1,94 +0,0 @@ -<?php -/** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Thomas Müller <thomas.mueller@tmit.eu> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * - */ - - -namespace OCA\DAV\Migration; - -use OCA\DAV\CalDAV\CalDavBackend; -use OCP\IUser; -use OCP\IUserManager; -use OCP\Migration\IOutput; -use OCP\Migration\IRepairStep; - -class Classification implements IRepairStep { - - /** @var CalDavBackend */ - private $calDavBackend; - - /** @var IUserManager */ - private $userManager; - - /** - * Classification constructor. - * - * @param CalDavBackend $calDavBackend - */ - public function __construct(CalDavBackend $calDavBackend, IUserManager $userManager) { - $this->calDavBackend = $calDavBackend; - $this->userManager = $userManager; - } - - /** - * @param IUser $user - */ - public function runForUser($user) { - $principal = 'principals/users/' . $user->getUID(); - $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']); - $classification = $this->extractClassification($calObject['calendardata']); - $this->calDavBackend->setClassification($object['id'], $classification); - } - } - } - - /** - * @param $calendarData - * @return integer - * @throws \Sabre\DAV\Exception\BadRequest - */ - protected function extractClassification($calendarData) { - return $this->calDavBackend->getDenormalizedData($calendarData)['classification']; - } - - /** - * @inheritdoc - */ - public function getName() { - return 'Fix classification for calendar objects'; - } - - /** - * @inheritdoc - */ - public function run(IOutput $output) { - $output->startProgress(); - $this->userManager->callForAllUsers(function($user) use ($output) { - /** @var IUser $user */ - $output->advance(1, $user->getDisplayName()); - $this->runForUser($user); - }); - $output->finishProgress(); - } -} diff --git a/apps/dav/lib/Migration/GenerateBirthdays.php b/apps/dav/lib/Migration/GenerateBirthdays.php deleted file mode 100644 index 20e000314ac..00000000000 --- a/apps/dav/lib/Migration/GenerateBirthdays.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php -/** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Thomas Müller <thomas.mueller@tmit.eu> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * - */ - - -namespace OCA\DAV\Migration; - -use OCA\DAV\CalDAV\BirthdayService; -use OCP\IUser; -use OCP\IUserManager; -use OCP\Migration\IOutput; -use OCP\Migration\IRepairStep; - -class GenerateBirthdays implements IRepairStep { - - /** @var BirthdayService */ - private $birthdayService; - - /** @var IUserManager */ - private $userManager; - - /** - * GenerateBirthdays constructor. - * - * @param BirthdayService $birthdayService - * @param IUserManager $userManager - */ - public function __construct(BirthdayService $birthdayService, IUserManager $userManager) { - $this->birthdayService = $birthdayService; - $this->userManager = $userManager; - } - - /** - * @inheritdoc - */ - public function getName() { - return 'Regenerate birthday calendar for all users'; - } - - /** - * @inheritdoc - */ - public function run(IOutput $output) { - - $output->startProgress(); - $this->userManager->callForAllUsers(function($user) use ($output) { - /** @var IUser $user */ - $output->advance(1, $user->getDisplayName()); - $this->birthdayService->syncUser($user->getUID()); - }); - $output->finishProgress(); - } -} diff --git a/apps/dav/tests/unit/CardDAV/ConverterTest.php b/apps/dav/tests/unit/CardDAV/ConverterTest.php index 737bbd96aaa..528b3aa9ef4 100644 --- a/apps/dav/tests/unit/CardDAV/ConverterTest.php +++ b/apps/dav/tests/unit/CardDAV/ConverterTest.php @@ -134,11 +134,45 @@ class ConverterTest extends TestCase { public function providesNewUsers() { return [ - [null], - [null, null, 'foo@bar.net'], - [['cloud' => 'foo@cloud.net', 'email' => 'foo@bar.net'], null, 'foo@bar.net', 'foo@cloud.net'], - [['cloud' => 'foo@cloud.net', 'email' => 'foo@bar.net', 'fn' => 'Dr. Foo Bar'], "Dr. Foo Bar", "foo@bar.net", 'foo@cloud.net'], - [['cloud' => 'foo@cloud.net', 'fn' => 'Dr. Foo Bar'], "Dr. Foo Bar", null, "foo@cloud.net"], + [ + null + ], + [ + null, + null, + 'foo@bar.net' + ], + [ + [ + 'cloud' => 'foo@cloud.net', + 'email' => 'foo@bar.net', + 'photo' => 'data:image/jpeg;base64,MTIzNDU2Nzg5', + ], + null, + 'foo@bar.net', + 'foo@cloud.net' + ], + [ + [ + 'cloud' => 'foo@cloud.net', + 'email' => 'foo@bar.net', + 'fn' => 'Dr. Foo Bar', + 'photo' => 'data:image/jpeg;base64,MTIzNDU2Nzg5', + ], + "Dr. Foo Bar", + "foo@bar.net", + 'foo@cloud.net' + ], + [ + [ + 'cloud' => 'foo@cloud.net', + 'fn' => 'Dr. Foo Bar', + 'photo' => 'data:image/jpeg;base64,MTIzNDU2Nzg5', + ], + "Dr. Foo Bar", + null, + "foo@cloud.net" + ], ]; } @@ -171,7 +205,7 @@ class ConverterTest extends TestCase { */ protected function getUserMock($displayName, $eMailAddress, $cloudId) { $image0 = $this->getMockBuilder(IImage::class)->disableOriginalConstructor()->getMock(); - $image0->method('mimeType')->willReturn('JPEG'); + $image0->method('mimeType')->willReturn('image/jpeg'); $image0->method('data')->willReturn('123456789'); $user = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock(); $user->method('getUID')->willReturn('12345'); diff --git a/apps/dav/tests/unit/Migration/ClassificationTest.php b/apps/dav/tests/unit/Migration/ClassificationTest.php deleted file mode 100644 index 1960fa031e1..00000000000 --- a/apps/dav/tests/unit/Migration/ClassificationTest.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php -/** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Thomas Müller <thomas.mueller@tmit.eu> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * - */ - -namespace OCA\DAV\Tests\unit\DAV\Migration; - -use OCA\DAV\CalDAV\CalDavBackend; -use OCA\DAV\Migration\Classification; -use OCA\DAV\Tests\unit\CalDAV\AbstractCalDavBackendTest; -use OCP\IUser; - -/** - * Class ClassificationTest - * - * @group DB - * - * @package OCA\DAV\Tests\unit\DAV - */ -class ClassificationTest extends AbstractCalDavBackendTest { - public function test() { - // setup data - $calendarId = $this->createTestCalendar(); - $eventUri = $this->createEvent($calendarId, '20130912T130000Z', '20130912T140000Z'); - $object = $this->backend->getCalendarObject($calendarId, $eventUri); - - // assert proper classification - $this->assertEquals(CalDavBackend::CLASSIFICATION_PUBLIC, $object['classification']); - $this->backend->setClassification($object['id'], CalDavBackend::CLASSIFICATION_CONFIDENTIAL); - $object = $this->backend->getCalendarObject($calendarId, $eventUri); - $this->assertEquals(CalDavBackend::CLASSIFICATION_CONFIDENTIAL, $object['classification']); - - // run migration - $c = new Classification($this->backend, $this->userManager); - - /** @var IUser | \PHPUnit_Framework_MockObject_MockObject $user */ - $user = $this->getMockBuilder('OCP\IUser') - ->disableOriginalConstructor() - ->getMock(); - $user->expects($this->once())->method('getUID')->willReturn('caldav-unit-test'); - - $c->runForUser($user); - - // assert classification after migration - $object = $this->backend->getCalendarObject($calendarId, $eventUri); - $this->assertEquals(CalDavBackend::CLASSIFICATION_PUBLIC, $object['classification']); - } -} diff --git a/apps/encryption/lib/Crypto/Encryption.php b/apps/encryption/lib/Crypto/Encryption.php index c71e25b6442..fdcbd41a09c 100644 --- a/apps/encryption/lib/Crypto/Encryption.php +++ b/apps/encryption/lib/Crypto/Encryption.php @@ -177,6 +177,14 @@ class Encryption implements IEncryptionModule { $this->isWriteOperation = false; $this->writeCache = ''; + if($this->session->isReady() === false) { + // if the master key is enabled we can initialize encryption + // with a empty password and user name + if ($this->util->isMasterKeyEnabled()) { + $this->keyManager->init('', ''); + } + } + if ($this->session->decryptAllModeActivated()) { $encryptedFileKey = $this->keyManager->getEncryptedFileKey($this->path); $shareKey = $this->keyManager->getShareKey($this->path, $this->session->getDecryptAllUid()); diff --git a/apps/encryption/lib/Session.php b/apps/encryption/lib/Session.php index 92132d6080c..a61ee25fadb 100644 --- a/apps/encryption/lib/Session.php +++ b/apps/encryption/lib/Session.php @@ -68,6 +68,16 @@ class Session { } /** + * check if encryption was initialized successfully + * + * @return bool + */ + public function isReady() { + $status = $this->getStatus(); + return $status === self::INIT_SUCCESSFUL; + } + + /** * Gets user or public share private key from session * * @return string $privateKey The user's plaintext private key diff --git a/apps/encryption/tests/Crypto/EncryptionTest.php b/apps/encryption/tests/Crypto/EncryptionTest.php index 658f6275bb4..3525d2d4aec 100644 --- a/apps/encryption/tests/Crypto/EncryptionTest.php +++ b/apps/encryption/tests/Crypto/EncryptionTest.php @@ -280,6 +280,21 @@ class EncryptionTest extends TestCase { } /** + * test begin() if encryption is not initialized but the master key is enabled + * in this case we can initialize the encryption without a username/password + * and continue + */ + public function testBeginInitMasterKey() { + + $this->sessionMock->expects($this->once())->method('isReady')->willReturn(false); + $this->utilMock->expects($this->once())->method('isMasterKeyEnabled') + ->willReturn(true); + $this->keyManagerMock->expects($this->once())->method('init')->with('', ''); + + $this->instance->begin('/user/files/welcome.txt', 'user', 'r', [], []); + } + + /** * @dataProvider dataTestUpdate * * @param string $fileKey diff --git a/apps/encryption/tests/SessionTest.php b/apps/encryption/tests/SessionTest.php index 099acddbca1..3000fedf2c3 100644 --- a/apps/encryption/tests/SessionTest.php +++ b/apps/encryption/tests/SessionTest.php @@ -134,6 +134,32 @@ class SessionTest extends TestCase { } /** + * @dataProvider dataTestIsReady + * + * @param int $status + * @param bool $expected + */ + public function testIsReady($status, $expected) { + /** @var Session | \PHPUnit_Framework_MockObject_MockObject $instance */ + $instance = $this->getMockBuilder(Session::class) + ->setConstructorArgs([$this->sessionMock]) + ->setMethods(['getStatus'])->getMock(); + + $instance->expects($this->once())->method('getStatus') + ->willReturn($status); + + $this->assertSame($expected, $instance->isReady()); + } + + public function dataTestIsReady() { + return [ + [Session::INIT_SUCCESSFUL, true], + [Session::INIT_EXECUTED, false], + [Session::NOT_INITIALIZED, false], + ]; + } + + /** * @param $key * @param $value */ diff --git a/apps/files/css/files.css b/apps/files/css/files.css index c0460ff6058..1983d51809c 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -652,7 +652,7 @@ html.ie8 .column-mtime .selectedActions { #fileList .name:focus a.action:focus { -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=70)"; filter: alpha(opacity=70); - opacity: 7; + opacity: .7; display:inline; } #fileList tr a.action.disabled { @@ -660,14 +660,20 @@ html.ie8 .column-mtime .selectedActions { } /* show share action of shared items darker to distinguish from non-shared */ -#fileList a.action.permanent.shared-style, -#fileList a.action.action-favorite.permanent { +#fileList a.action.action-share.permanent.shared-style, +#fileList a.action.action-favorite.permanent, +/* show hovered permanent entries darker */ +#fileList tr a.action.action-share.permanent:hover, +#fileList tr a.action.action-share.permanent:focus, +#fileList tr a.action.action-menu.permanent:hover, +#fileList tr a.action.action-menu.permanent:focus { -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=70)" !important; filter: alpha(opacity=70) !important; opacity: .7 !important; display:inline; } /* always show actions on mobile, not only on hover */ +#fileList a.action.action-share.permanent, #fileList a.action.action-menu.permanent { -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=30)" !important; filter: alpha(opacity=30) !important; diff --git a/apps/files/lib/Activity/Provider.php b/apps/files/lib/Activity/Provider.php index c2e753e9165..f1ffb851203 100644 --- a/apps/files/lib/Activity/Provider.php +++ b/apps/files/lib/Activity/Provider.php @@ -26,6 +26,8 @@ use OCP\Activity\IManager; use OCP\Activity\IProvider; use OCP\IL10N; use OCP\IURLGenerator; +use OCP\IUser; +use OCP\IUserManager; class Provider implements IProvider { @@ -38,15 +40,23 @@ class Provider implements IProvider { /** @var IManager */ protected $activityManager; + /** @var IUserManager */ + protected $userManager; + + /** @var string[] cached displayNames - key is the UID and value the displayname */ + protected $displayNames = []; + /** * @param IL10N $l * @param IURLGenerator $url * @param IManager $activityManager + * @param IUserManager $userManager */ - public function __construct(IL10N $l, IURLGenerator $url, IManager $activityManager) { + public function __construct(IL10N $l, IURLGenerator $url, IManager $activityManager, IUserManager $userManager) { $this->l = $l; $this->url = $url; $this->activityManager = $activityManager; + $this->userManager = $userManager; } /** @@ -265,11 +275,28 @@ class Provider implements IProvider { ]; } - protected function getRichUserParameter($parameter) { + protected function getRichUserParameter($uid) { + if (!isset($this->displayNames[$uid])) { + $this->displayNames[$uid] = $this->getDisplayName($uid); + } + return [ 'type' => 'user', - 'id' => $parameter, - 'name' => $parameter,// FIXME Use display name + 'id' => $uid, + 'name' => $this->displayNames[$uid], ]; } + + /** + * @param string $uid + * @return string + */ + protected function getDisplayName($uid) { + $user = $this->userManager->get($uid); + if ($user instanceof IUser) { + return $user->getDisplayName(); + } else { + return $uid; + } + } } diff --git a/apps/files_sharing/lib/Activity/Providers/Downloads.php b/apps/files_sharing/lib/Activity/Providers/Downloads.php index 84ef5895dde..39e2a846b30 100644 --- a/apps/files_sharing/lib/Activity/Providers/Downloads.php +++ b/apps/files_sharing/lib/Activity/Providers/Downloads.php @@ -87,7 +87,7 @@ class Downloads implements IProvider { public function parseShortVersion(IEvent $event) { $parsedParameters = $this->getParsedParameters($event); - if ($event->getSubject() === self::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED || + if ($event->getSubject() === self::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED || $event->getSubject() === self::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED) { $event->setParsedSubject($this->l->t('Downloaded via public link')) ->setIcon($this->url->getAbsoluteURL($this->url->imagePath('core', 'actions/download.svg'))); @@ -114,7 +114,7 @@ class Downloads implements IProvider { public function parseLongVersion(IEvent $event) { $parsedParameters = $this->getParsedParameters($event); - if ($event->getSubject() === self::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED || + if ($event->getSubject() === self::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED || $event->getSubject() === self::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED) { $event->setParsedSubject($this->l->t('%1$s downloaded via public link', [ $parsedParameters['file']['path'], @@ -150,6 +150,11 @@ class Downloads implements IProvider { $parameters = $event->getSubjectParameters(); switch ($subject) { + case self::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED: + case self::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED: + return [ + 'file' => $this->generateFileParameter($event->getObjectId(), $parameters[0]), + ]; case self::SUBJECT_SHARED_FILE_BY_EMAIL_DOWNLOADED: case self::SUBJECT_SHARED_FOLDER_BY_EMAIL_DOWNLOADED: return [ @@ -161,7 +166,8 @@ class Downloads implements IProvider { ], ]; } - return []; + + throw new \InvalidArgumentException(); } /** diff --git a/apps/files_sharing/lib/Activity/Providers/Groups.php b/apps/files_sharing/lib/Activity/Providers/Groups.php index 50b3df785e5..c42cc1bb59b 100644 --- a/apps/files_sharing/lib/Activity/Providers/Groups.php +++ b/apps/files_sharing/lib/Activity/Providers/Groups.php @@ -110,17 +110,17 @@ class Groups implements IProvider { ]) ->setIcon($this->url->getAbsoluteURL($this->url->imagePath('core', 'actions/share.svg'))); } else if ($event->getSubject() === self::SUBJECT_RESHARED_GROUP_BY) { - $event->setParsedSubject($this->l->t('%2$s shared with %1$s by', [ + $event->setParsedSubject($this->l->t('%2$s shared with group %1$s', [ $parsedParameters['group']['name'], $parsedParameters['actor']['name'], ])) - ->setRichSubject($this->l->t('{actor} shared with {group}'), [ + ->setRichSubject($this->l->t('{actor} shared with group {group}'), [ 'group' => $parsedParameters['group'], 'actor' => $parsedParameters['actor'], ]) ->setIcon($this->url->getAbsoluteURL($this->url->imagePath('core', 'actions/share.svg'))); } else if ($event->getSubject() === self::SUBJECT_UNSHARED_GROUP_BY) { - $event->setParsedSubject($this->l->t('%2$s removed share for %1$s', [ + $event->setParsedSubject($this->l->t('%2$s removed share for group %1$s', [ $parsedParameters['group']['name'], $parsedParameters['actor']['name'], ])) diff --git a/apps/files_sharing/lib/Activity/Providers/RemoteShares.php b/apps/files_sharing/lib/Activity/Providers/RemoteShares.php index c7906b84970..8760733a261 100644 --- a/apps/files_sharing/lib/Activity/Providers/RemoteShares.php +++ b/apps/files_sharing/lib/Activity/Providers/RemoteShares.php @@ -159,10 +159,10 @@ class RemoteShares implements IProvider { $subject = $event->getSubject(); $parameters = $event->getSubjectParameters(); - $remoteUser = explode('@', $parameters[0], 2); switch ($subject) { case self::SUBJECT_REMOTE_SHARE_RECEIVED: case self::SUBJECT_REMOTE_SHARE_UNSHARED: + $remoteUser = explode('@', $parameters[0], 2); return [ 'file' => [ 'type' => 'pending-federated-share', @@ -178,6 +178,7 @@ class RemoteShares implements IProvider { ]; case self::SUBJECT_REMOTE_SHARE_ACCEPTED: case self::SUBJECT_REMOTE_SHARE_DECLINED: + $remoteUser = explode('@', $parameters[0], 2); return [ 'file' => $this->generateFileParameter($event->getObjectId(), $event->getObjectName()), 'user' => [ @@ -188,7 +189,7 @@ class RemoteShares implements IProvider { ], ]; } - return []; + throw new \InvalidArgumentException(); } /** diff --git a/apps/files_sharing/lib/Activity/Providers/Users.php b/apps/files_sharing/lib/Activity/Providers/Users.php index 915dbcf225a..c85452aec06 100644 --- a/apps/files_sharing/lib/Activity/Providers/Users.php +++ b/apps/files_sharing/lib/Activity/Providers/Users.php @@ -112,7 +112,7 @@ class Users implements IProvider { ]) ->setIcon($this->url->getAbsoluteURL($this->url->imagePath('core', 'actions/share.svg'))); } else if ($event->getSubject() === self::SUBJECT_RESHARED_USER_BY) { - $event->setParsedSubject($this->l->t('%2$s shared with %1$s by', [ + $event->setParsedSubject($this->l->t('%2$s shared with %1$s', [ $parsedParameters['user']['name'], $parsedParameters['actor']['name'], ])) diff --git a/apps/systemtags/css/systemtagsfilelist.css b/apps/systemtags/css/systemtagsfilelist.css index 2da8cd40012..6318d43687e 100644 --- a/apps/systemtags/css/systemtagsfilelist.css +++ b/apps/systemtags/css/systemtagsfilelist.css @@ -9,6 +9,7 @@ */ #app-content-systemtagsfilter .select2-container { width: 30%; + margin-left: 10px; } #app-content-systemtagsfilter .select2-choices { @@ -19,7 +20,6 @@ box-sizing: content-box; border-radius: 3px; border: 1px solid #ddd; - margin: 3px 3px 3px 0; padding: 0; min-height: auto; } diff --git a/apps/systemtags/lib/Activity/Provider.php b/apps/systemtags/lib/Activity/Provider.php index 9d85300d5be..37ede8c3b8f 100644 --- a/apps/systemtags/lib/Activity/Provider.php +++ b/apps/systemtags/lib/Activity/Provider.php @@ -26,6 +26,8 @@ use OCP\Activity\IManager; use OCP\Activity\IProvider; use OCP\IL10N; use OCP\IURLGenerator; +use OCP\IUser; +use OCP\IUserManager; class Provider implements IProvider { @@ -45,15 +47,23 @@ class Provider implements IProvider { /** @var IManager */ protected $activityManager; + /** @var IUserManager */ + protected $userManager; + + /** @var string[] */ + protected $displayNames = []; + /** * @param IL10N $l * @param IURLGenerator $url * @param IManager $activityManager + * @param IUserManager $userManager */ - public function __construct(IL10N $l, IURLGenerator $url, IManager $activityManager) { + public function __construct(IL10N $l, IURLGenerator $url, IManager $activityManager, IUserManager $userManager) { $this->l = $l; $this->url = $url; $this->activityManager = $activityManager; + $this->userManager = $userManager; } /** @@ -278,11 +288,15 @@ class Provider implements IProvider { ]; } - protected function getUserParameter($parameter) { + protected function getUserParameter($uid) { + if (!isset($this->displayNames[$uid])) { + $this->displayNames[$uid] = $this->getDisplayName($uid); + } + return [ 'type' => 'user', - 'id' => $parameter, - 'name' => $parameter,// FIXME Use display name + 'id' => $uid, + 'name' => $this->displayNames[$uid], ]; } @@ -295,4 +309,17 @@ class Provider implements IProvider { return $this->l->t('%s (invisible)', $parameter['name']); } } + + /** + * @param string $uid + * @return string + */ + protected function getDisplayName($uid) { + $user = $this->userManager->get($uid); + if ($user instanceof IUser) { + return $user->getDisplayName(); + } else { + return $uid; + } + } } diff --git a/apps/theming/lib/Controller/ThemingController.php b/apps/theming/lib/Controller/ThemingController.php index 58e843c5d9d..73e3ed3a4b4 100644 --- a/apps/theming/lib/Controller/ThemingController.php +++ b/apps/theming/lib/Controller/ThemingController.php @@ -211,7 +211,9 @@ class ThemingController extends Controller { $tmpFile = $this->tempManager->getTemporaryFile(); if(function_exists('imagescale')) { // FIXME: Once PHP 5.5.0 is a requirement the above check can be removed - $image = imagescale($image, 1920); + // Workaround for https://bugs.php.net/bug.php?id=65171 + $newHeight = imagesy($image)/(imagesx($image)/1920); + $image = imagescale($image, 1920, $newHeight); } imageinterlace($image, 1); imagejpeg($image, $tmpFile, 75); diff --git a/core/css/inputs.css b/core/css/inputs.css index 3d74ff38271..f2233395658 100644 --- a/core/css/inputs.css +++ b/core/css/inputs.css @@ -243,8 +243,8 @@ select:hover { #select2-drop .select2-search input { width: calc(100% - 14px); min-height: auto; - background: url('../img/actions/search.svg') no-repeat right center; - background-origin: content-box; + background: url('../img/actions/search.svg') no-repeat right center !important; + background-origin: content-box !important; } #select2-drop .select2-results { max-height: 250px; @@ -252,7 +252,6 @@ select:hover { padding: 0; } #select2-drop .select2-results .select2-result-label { - padding: 12px !important; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -340,7 +339,7 @@ select:hover { border: none; } .select2-container .select2-choice .select2-arrow b { - background: url('../img/actions/triangle-s.svg') no-repeat center; + background: url('../img/actions/triangle-s.svg') no-repeat center !important; opacity: .5; } .select2-container .select2-choice:hover .select2-arrow b, diff --git a/core/js/sharedialogview.js b/core/js/sharedialogview.js index 6377d16dd4c..f83a2675958 100644 --- a/core/js/sharedialogview.js +++ b/core/js/sharedialogview.js @@ -265,17 +265,11 @@ var text = item.label; if (item.value.shareType === OC.Share.SHARE_TYPE_GROUP) { - text = t('core', '{sharee} (group)', { - sharee: text - }); + text = t('core', '{sharee} (group)', { sharee: text }, undefined, { escape: false }); } else if (item.value.shareType === OC.Share.SHARE_TYPE_REMOTE) { - text = t('core', '{sharee} (remote)', { - sharee: text - }); + text = t('core', '{sharee} (remote)', { sharee: text }, undefined, { escape: false }); } else if (item.value.shareType === OC.Share.SHARE_TYPE_EMAIL) { - text = t('core', '{sharee} (email)', { - sharee: text - }); + text = t('core', '{sharee} (email)', { sharee: text }, undefined, { escape: false }); } var insert = $("<div class='share-autocomplete-item'/>"); var avatar = $("<div class='avatardiv'></div>").appendTo(insert); diff --git a/core/templates/installation.php b/core/templates/installation.php index f7556988634..d3f5021821d 100644 --- a/core/templates/installation.php +++ b/core/templates/installation.php @@ -147,8 +147,6 @@ script('core', [ <?php endif; ?> <?php endif; ?> - <div class="icon-loading-dark float-spinner"> </div> - <?php if(!$_['dbIsSet'] OR count($_['errors']) > 0): ?> <fieldset id="sqliteInformation" class="warning"> <legend><?php p($l->t('Performance warning'));?></legend> @@ -158,6 +156,8 @@ script('core', [ </fieldset> <?php endif ?> + <div class="icon-loading-dark float-spinner"> </div> + <div class="buttons"><input type="submit" class="primary" value="<?php p($l->t( 'Finish setup' )); ?>" data-finishing="<?php p($l->t( 'Finishing …' )); ?>"></div> <p class="info"> diff --git a/lib/base.php b/lib/base.php index d6c6e17eff9..2f5517f4614 100644 --- a/lib/base.php +++ b/lib/base.php @@ -493,10 +493,18 @@ class OC { 'lax', 'strict', ]; + + // Append __Host to the cookie if it meets the requirements + $cookiePrefix = ''; + if($cookieParams['secure'] === true && $cookieParams['path'] === '/') { + $cookiePrefix = '__Host-'; + } + foreach($policies as $policy) { header( sprintf( - 'Set-Cookie: nc_sameSiteCookie%s=true; path=%s; httponly;' . $secureCookie . 'expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=%s', + 'Set-Cookie: %snc_sameSiteCookie%s=true; path=%s; httponly;' . $secureCookie . 'expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=%s', + $cookiePrefix, $policy, $cookieParams['path'], $policy diff --git a/lib/private/AppFramework/Http/Request.php b/lib/private/AppFramework/Http/Request.php index c7a3be163fe..62d7fc7ed30 100644 --- a/lib/private/AppFramework/Http/Request.php +++ b/lib/private/AppFramework/Http/Request.php @@ -498,6 +498,31 @@ class Request implements \ArrayAccess, \Countable, IRequest { } /** + * Wrapper around session_get_cookie_params + * + * @return array + */ + protected function getCookieParams() { + return session_get_cookie_params(); + } + + /** + * Appends the __Host- prefix to the cookie if applicable + * + * @param string $name + * @return string + */ + protected function getProtectedCookieName($name) { + $cookieParams = $this->getCookieParams(); + $prefix = ''; + if($cookieParams['secure'] === true && $cookieParams['path'] === '/') { + $prefix = '__Host-'; + } + + return $prefix.$name; + } + + /** * Checks if the strict cookie has been sent with the request if the request * is including any cookies. * @@ -508,7 +533,9 @@ class Request implements \ArrayAccess, \Countable, IRequest { if(!$this->cookieCheckRequired()) { return true; } - if($this->getCookie('nc_sameSiteCookiestrict') === 'true' + + $cookieName = $this->getProtectedCookieName('nc_sameSiteCookiestrict'); + if($this->getCookie($cookieName) === 'true' && $this->passesLaxCookieCheck()) { return true; } @@ -526,7 +553,9 @@ class Request implements \ArrayAccess, \Countable, IRequest { if(!$this->cookieCheckRequired()) { return true; } - if($this->getCookie('nc_sameSiteCookielax') === 'true') { + + $cookieName = $this->getProtectedCookieName('nc_sameSiteCookielax'); + if($this->getCookie($cookieName) === 'true') { return true; } return false; diff --git a/settings/Application.php b/settings/Application.php index 14110c6ca95..d907cd666fb 100644 --- a/settings/Application.php +++ b/settings/Application.php @@ -34,21 +34,9 @@ use OC\App\AppStore\Fetcher\AppFetcher; use OC\App\AppStore\Fetcher\CategoryFetcher; use OC\AppFramework\Utility\TimeFactory; use OC\Authentication\Token\IProvider; -use OC\Files\View; use OC\Server; -use OC\Settings\Controller\AppSettingsController; -use OC\Settings\Controller\AuthSettingsController; -use OC\Settings\Controller\CertificateController; -use OC\Settings\Controller\CheckSetupController; -use OC\Settings\Controller\EncryptionController; -use OC\Settings\Controller\GroupsController; -use OC\Settings\Controller\LogSettingsController; -use OC\Settings\Controller\MailSettingsController; -use OC\Settings\Controller\SecuritySettingsController; -use OC\Settings\Controller\UsersController; use OC\Settings\Middleware\SubadminMiddleware; use OCP\AppFramework\App; -use OCP\AppFramework\IAppContainer; use OCP\IContainer; use OCP\Settings\IManager; use OCP\Util; @@ -72,130 +60,6 @@ class Application extends App { $container->registerMiddleWare('SubadminMiddleware'); /** - * Controllers - */ - $container->registerService('MailSettingsController', function(IContainer $c) { - return new MailSettingsController( - $c->query('AppName'), - $c->query('Request'), - $c->query('L10N'), - $c->query('Config'), - $c->query('UserSession'), - $c->query('Defaults'), - $c->query('Mailer'), - $c->query('DefaultMailAddress') - ); - }); - $container->registerService('EncryptionController', function(IContainer $c) { - return new EncryptionController( - $c->query('AppName'), - $c->query('Request'), - $c->query('L10N'), - $c->query('Config'), - $c->query('DatabaseConnection'), - $c->query('UserManager'), - new View(), - $c->query('Logger') - ); - }); - - $container->registerService('AppSettingsController', function(IContainer $c) { - return new AppSettingsController( - $c->query('AppName'), - $c->query('Request'), - $c->query('L10N'), - $c->query('Config'), - $c->query('INavigationManager'), - $c->query('IAppManager'), - $c->query('CategoryFetcher'), - $c->query('AppFetcher'), - \OC::$server->getL10NFactory() - ); - }); - $container->registerService('AuthSettingsController', function(IContainer $c) { - return new AuthSettingsController( - $c->query('AppName'), - $c->query('Request'), - $c->query('ServerContainer')->query('OC\Authentication\Token\IProvider'), - $c->query('UserManager'), - $c->query('ServerContainer')->getSession(), - $c->query('ServerContainer')->getSecureRandom(), - $c->query('UserId') - ); - }); - $container->registerService('SecuritySettingsController', function(IContainer $c) { - return new SecuritySettingsController( - $c->query('AppName'), - $c->query('Request'), - $c->query('Config') - ); - }); - $container->registerService('AccountManager', function(IAppContainer $c) { - return new AccountManager($c->getServer()->getDatabaseConnection()); - }); - $container->registerService('CertificateController', function(IContainer $c) { - return new CertificateController( - $c->query('AppName'), - $c->query('Request'), - $c->query('CertificateManager'), - $c->query('SystemCertificateManager'), - $c->query('L10N'), - $c->query('IAppManager') - ); - }); - $container->registerService('GroupsController', function(IContainer $c) { - return new GroupsController( - $c->query('AppName'), - $c->query('Request'), - $c->query('GroupManager'), - $c->query('UserSession'), - $c->query('IsAdmin'), - $c->query('L10N') - ); - }); - $container->registerService('UsersController', function(IContainer $c) { - return new UsersController( - $c->query('AppName'), - $c->query('Request'), - $c->query('UserManager'), - $c->query('GroupManager'), - $c->query('UserSession'), - $c->query('Config'), - $c->query('IsAdmin'), - $c->query('L10N'), - $c->query('Logger'), - $c->query('Defaults'), - $c->query('Mailer'), - $c->query('DefaultMailAddress'), - $c->query('URLGenerator'), - $c->query('OCP\\App\\IAppManager'), - $c->query('OCP\\IAvatarManager'), - $c->query('AccountManager') - ); - }); - $container->registerService('LogSettingsController', function(IContainer $c) { - return new LogSettingsController( - $c->query('AppName'), - $c->query('Request'), - $c->query('Config'), - $c->query('L10N') - ); - }); - $container->registerService('CheckSetupController', function(IContainer $c) { - return new CheckSetupController( - $c->query('AppName'), - $c->query('Request'), - $c->query('Config'), - $c->query('ClientService'), - $c->query('URLGenerator'), - $c->query('Util'), - $c->query('L10N'), - $c->query('Checker') - ); - }); - - - /** * Core class wrappers */ /** FIXME: Remove once OC_User is non-static and mockable */ diff --git a/settings/js/users/users.js b/settings/js/users/users.js index 7e70d98f091..71defeaa18a 100644 --- a/settings/js/users/users.js +++ b/settings/js/users/users.js @@ -497,7 +497,7 @@ var UserList = { group: group }, function (response) { - if (response.data.message) { + if (response.data !== undefined && response.data.message) { OC.Notification.show(response.data.message); } } diff --git a/settings/templates/personal.php b/settings/templates/personal.php index b81b19d9060..2ae6c1dcdf2 100644 --- a/settings/templates/personal.php +++ b/settings/templates/personal.php @@ -157,34 +157,6 @@ if($_['displayNameChangeSupported']) { <?php } else { ?> -<div id="displaynameform" class="section"> - <h2><?php echo $l->t('Full name');?></h2> - <span><?php if(isset($_['displayName'][0])) { p($_['displayName']); } else { p($l->t('No display name set')); } ?></span> -</div> -<?php -} -?> - -<?php -if($_['displayNameChangeSupported']) { -?> -<form id="lostpassword" class="section"> - <h2> - <label for="email"><?php p($l->t('Email'));?></label> - </h2> - <input type="email" name="email" id="email" value="<?php p($_['email']); ?>" - placeholder="<?php p($l->t('Your email address'));?>" - class="password-confirm-required" - autocomplete="on" autocapitalize="off" autocorrect="off" /> - <span class="msg"></span><br /> - <em><?php p($l->t('For password recovery and notifications'));?></em> -</form> -<?php -} else { -?> -<div id="lostpassword" class="section"> - <h2><?php echo $l->t('Email'); ?></h2> - <span><?php if(isset($_['email'][0])) { p($_['email']); } else { p($l->t('No email address set')); }?></span> <div id="personal-settings-container" class="no-edit"> <div id="displaynameform" class="section"> <h2><?php p($l->t('Full name'));?></h2> diff --git a/tests/lib/AppFramework/Http/RequestTest.php b/tests/lib/AppFramework/Http/RequestTest.php index 1ba20869439..b1515b0efb5 100644 --- a/tests/lib/AppFramework/Http/RequestTest.php +++ b/tests/lib/AppFramework/Http/RequestTest.php @@ -1500,6 +1500,76 @@ class RequestTest extends \Test\TestCase { $this->assertFalse($request->passesCSRFCheck()); } + public function testPassesStrictCookieCheckWithAllCookiesAndStrict() { + /** @var Request $request */ + $request = $this->getMockBuilder('\OC\AppFramework\Http\Request') + ->setMethods(['getScriptName', 'getCookieParams']) + ->setConstructorArgs([ + [ + 'server' => [ + 'HTTP_REQUESTTOKEN' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds', + ], + 'cookies' => [ + session_name() => 'asdf', + '__Host-nc_sameSiteCookiestrict' => 'true', + '__Host-nc_sameSiteCookielax' => 'true', + ], + ], + $this->secureRandom, + $this->config, + $this->csrfTokenManager, + $this->stream + ]) + ->getMock(); + $request + ->expects($this->any()) + ->method('getCookieParams') + ->willReturn([ + 'secure' => true, + 'path' => '/', + ]); + + $this->assertTrue($request->passesStrictCookieCheck()); + } + + public function testFailsStrictCookieCheckWithAllCookiesAndMissingStrict() { + /** @var Request $request */ + $request = $this->getMockBuilder('\OC\AppFramework\Http\Request') + ->setMethods(['getScriptName', 'getCookieParams']) + ->setConstructorArgs([ + [ + 'server' => [ + 'HTTP_REQUESTTOKEN' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds', + ], + 'cookies' => [ + session_name() => 'asdf', + 'nc_sameSiteCookiestrict' => 'true', + 'nc_sameSiteCookielax' => 'true', + ], + ], + $this->secureRandom, + $this->config, + $this->csrfTokenManager, + $this->stream + ]) + ->getMock(); + $request + ->expects($this->any()) + ->method('getCookieParams') + ->willReturn([ + 'secure' => true, + 'path' => '/', + ]); + + $this->assertFalse($request->passesStrictCookieCheck()); + } + + public function testGetCookieParams() { + $request = $this->createMock(Request::class); + $actual = $this->invokePrivate($request, 'getCookieParams'); + $this->assertSame(session_get_cookie_params(), $actual); + } + public function testPassesStrictCookieCheckWithAllCookies() { /** @var Request $request */ $request = $this->getMockBuilder('\OC\AppFramework\Http\Request') diff --git a/version.php b/version.php index 0eb9f3de72a..4aef5b12d77 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ $OC_Version = array(11, 0, 0, 2); // The human readable string -$OC_VersionString = '11.0 alpha'; +$OC_VersionString = '11.0 beta'; $OC_VersionCanBeUpgradedFrom = array(9, 1); |