diff options
-rw-r--r-- | apps/dav/lib/Connector/Sabre/ServerFactory.php | 7 | ||||
-rw-r--r-- | apps/theming/js/settings-admin.js | 8 | ||||
-rw-r--r-- | apps/theming/lib/Controller/ThemingController.php | 44 | ||||
-rw-r--r-- | apps/theming/tests/Controller/ThemingControllerTest.php | 65 | ||||
-rw-r--r-- | core/css/styles.css | 15 | ||||
-rw-r--r-- | core/js/js.js | 33 | ||||
-rw-r--r-- | core/templates/twofactorselectchallenge.php | 44 | ||||
-rw-r--r-- | core/templates/twofactorshowchallenge.php | 17 | ||||
-rw-r--r-- | lib/private/Files/Mount/MountPoint.php | 6 | ||||
-rw-r--r-- | lib/private/Files/Node/Root.php | 37 | ||||
-rw-r--r-- | lib/private/legacy/util.php | 1 | ||||
-rw-r--r-- | tests/lib/TestCase.php | 1 |
12 files changed, 211 insertions, 67 deletions
diff --git a/apps/dav/lib/Connector/Sabre/ServerFactory.php b/apps/dav/lib/Connector/Sabre/ServerFactory.php index 55b967619d6..644f0f28f57 100644 --- a/apps/dav/lib/Connector/Sabre/ServerFactory.php +++ b/apps/dav/lib/Connector/Sabre/ServerFactory.php @@ -29,6 +29,7 @@ namespace OCA\DAV\Connector\Sabre; +use OC\Files\Node\Folder; use OCA\DAV\Files\BrowserErrorPagePlugin; use OCP\Files\Mount\IMountManager; use OCP\IConfig; @@ -135,7 +136,11 @@ class ServerFactory { /** @var \OC\Files\View $view */ $view = $viewCallBack($server); - $rootInfo = $view->getFileInfo(''); + if ($userFolder instanceof Folder && $userFolder->getPath() === $view->getRoot()) { + $rootInfo = $userFolder; + } else { + $rootInfo = $view->getFileInfo(''); + } // Create ownCloud Dir if ($rootInfo->getType() === 'dir') { diff --git a/apps/theming/js/settings-admin.js b/apps/theming/js/settings-admin.js index 0de3b28bab0..c896da321c8 100644 --- a/apps/theming/js/settings-admin.js +++ b/apps/theming/js/settings-admin.js @@ -157,8 +157,8 @@ $(document).ready(function () { submit: function(e, response) { OC.msg.startSaving('#theming_settings_msg'); }, - fail: function (e, data){ - OC.msg.finishedSaving('#theming_settings_msg', response); + fail: function (e, response){ + OC.msg.finishedError('#theming_settings_msg', response._response.jqXHR.responseJSON.data.message); } }; var uploadParamsLogin = { @@ -171,8 +171,8 @@ $(document).ready(function () { submit: function(e, response) { OC.msg.startSaving('#theming_settings_msg'); }, - fail: function (e, data){ - OC.msg.finishedSaving('#theming_settings_msg', response); + fail: function (e, response){ + OC.msg.finishedError('#theming_settings_msg', response._response.jqXHR.responseJSON.data.message); } }; diff --git a/apps/theming/lib/Controller/ThemingController.php b/apps/theming/lib/Controller/ThemingController.php index 8a7aaec6b5e..fbb4c904773 100644 --- a/apps/theming/lib/Controller/ThemingController.php +++ b/apps/theming/lib/Controller/ThemingController.php @@ -39,6 +39,7 @@ use OCP\IConfig; use OCP\IL10N; use OCP\IRequest; use OCA\Theming\Util; +use OCP\ITempManager; /** * Class ThemingController @@ -60,6 +61,8 @@ class ThemingController extends Controller { private $config; /** @var IRootFolder */ private $rootFolder; + /** @var ITempManager */ + private $tempManager; /** * ThemingController constructor. @@ -72,6 +75,7 @@ class ThemingController extends Controller { * @param ITimeFactory $timeFactory * @param IL10N $l * @param IRootFolder $rootFolder + * @param ITempManager $tempManager */ public function __construct( $appName, @@ -81,7 +85,8 @@ class ThemingController extends Controller { Util $util, ITimeFactory $timeFactory, IL10N $l, - IRootFolder $rootFolder + IRootFolder $rootFolder, + ITempManager $tempManager ) { parent::__construct($appName, $request); @@ -91,6 +96,7 @@ class ThemingController extends Controller { $this->l = $l; $this->config = $config; $this->rootFolder = $rootFolder; + $this->tempManager = $tempManager; } /** @@ -171,7 +177,8 @@ class ThemingController extends Controller { 'message' => $this->l->t('No file uploaded') ] ], - Http::STATUS_UNPROCESSABLE_ENTITY); + Http::STATUS_UNPROCESSABLE_ENTITY + ); } $name = ''; if(!empty($newLogo)) { @@ -182,7 +189,32 @@ class ThemingController extends Controller { } if(!empty($newBackgroundLogo)) { $target = $this->rootFolder->newFile('themedbackgroundlogo'); - stream_copy_to_stream(fopen($newBackgroundLogo['tmp_name'], 'r'), $target->fopen('w')); + + $image = @imagecreatefromstring(file_get_contents($newBackgroundLogo['tmp_name'], 'r')); + if($image === false) { + return new DataResponse( + [ + 'data' => [ + 'message' => $this->l->t('Unsupported image type'), + ], + 'status' => 'failure', + ], + Http::STATUS_UNPROCESSABLE_ENTITY + ); + } + + // Optimize the image since some people may upload images that will be + // either to big or are not progressive rendering. + $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); + } + imageinterlace($image, 1); + imagejpeg($image, $tmpFile, 75); + imagedestroy($image); + + stream_copy_to_stream(fopen($tmpFile, 'r'), $target->fopen('w')); $this->template->set('backgroundMime', $newBackgroundLogo['type']); $name = $newBackgroundLogo['name']; } @@ -236,6 +268,7 @@ class ThemingController extends Controller { $response->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime())); $response->addHeader('Content-Disposition', 'attachment'); $response->addHeader('Content-Type', $this->config->getAppValue($this->appName, 'logoMime', '')); + $response->addHeader('Pragma', 'cache'); return $response; } @@ -256,6 +289,7 @@ class ThemingController extends Controller { $response->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime())); $response->addHeader('Content-Disposition', 'attachment'); $response->addHeader('Content-Type', $this->config->getAppValue($this->appName, 'backgroundMime', '')); + $response->addHeader('Pragma', 'cache'); return $response; } @@ -358,6 +392,7 @@ class ThemingController extends Controller { $response = new DataDownloadResponse($responseCss, 'style', 'text/css'); $response->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime())); + $response->addHeader('Pragma', 'cache'); $response->cacheFor(3600); return $response; } @@ -378,8 +413,9 @@ class ThemingController extends Controller { }; })();'; $response = new Http\DataDisplayResponse($responseJS); - $response->addHeader("Content-type","text/javascript"); + $response->addHeader('Content-type', 'text/javascript'); $response->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime())); + $response->addHeader('Pragma', 'cache'); $response->cacheFor(3600); return $response; } diff --git a/apps/theming/tests/Controller/ThemingControllerTest.php b/apps/theming/tests/Controller/ThemingControllerTest.php index da2137e9da0..d053d8c1a1c 100644 --- a/apps/theming/tests/Controller/ThemingControllerTest.php +++ b/apps/theming/tests/Controller/ThemingControllerTest.php @@ -32,6 +32,7 @@ use OCP\Files\IRootFolder; use OCP\IConfig; use OCP\IL10N; use OCP\IRequest; +use OCP\ITempManager; use Test\TestCase; use OCA\Theming\ThemingDefaults; @@ -52,6 +53,8 @@ class ThemingControllerTest extends TestCase { private $themingController; /** @var IRootFolder|\PHPUnit_Framework_MockObject_MockObject */ private $rootFolder; + /** @var ITempManager */ + private $tempManager; public function setUp() { $this->request = $this->getMockBuilder('OCP\IRequest')->getMock(); @@ -64,10 +67,10 @@ class ThemingControllerTest extends TestCase { ->getMock(); $this->l10n = $this->getMockBuilder('OCP\IL10N')->getMock(); $this->rootFolder = $this->getMockBuilder('OCP\Files\IRootFolder')->getMock(); - $this->timeFactory->expects($this->any()) ->method('getTime') ->willReturn(123); + $this->tempManager = \OC::$server->getTempManager(); $this->themingController = new ThemingController( 'theming', @@ -77,7 +80,8 @@ class ThemingControllerTest extends TestCase { $this->util, $this->timeFactory, $this->l10n, - $this->rootFolder + $this->rootFolder, + $this->tempManager ); return parent::setUp(); @@ -214,6 +218,7 @@ class ThemingControllerTest extends TestCase { $destination = \OC::$server->getTempManager()->getTemporaryFolder(); touch($tmpLogo); + file_put_contents($tmpLogo, file_get_contents(__DIR__ . '/../../../../tests/data/desktopapp.png')); $this->request ->expects($this->at(0)) ->method('getUploadedFile') @@ -261,6 +266,52 @@ class ThemingControllerTest extends TestCase { $this->assertEquals($expected, $this->themingController->updateLogo()); } + public function testUpdateLogoLoginScreenUploadWithInvalidImage() { + $tmpLogo = \OC::$server->getTempManager()->getTemporaryFolder() . '/logo.svg'; + $destination = \OC::$server->getTempManager()->getTemporaryFolder(); + + touch($tmpLogo); + file_put_contents($tmpLogo, file_get_contents(__DIR__ . '/../../../../tests/data/data.zip')); + $this->request + ->expects($this->at(0)) + ->method('getUploadedFile') + ->with('uploadlogo') + ->willReturn(null); + $this->request + ->expects($this->at(1)) + ->method('getUploadedFile') + ->with('upload-login-background') + ->willReturn([ + 'tmp_name' => $tmpLogo, + 'type' => 'text/svg', + 'name' => 'logo.svg', + ]); + $this->l10n + ->expects($this->once()) + ->method('t') + ->with('Unsupported image type') + ->willReturn('Unsupported image type'); + $file = $this->getMockBuilder('\\OCP\\Files\\File') + ->disableOriginalConstructor() + ->getMock(); + $this->rootFolder + ->expects($this->once()) + ->method('newFile') + ->with('themedbackgroundlogo') + ->willReturn($file); + $expected = new DataResponse( + [ + 'data' => + [ + 'message' => 'Unsupported image type', + ], + 'status' => 'failure' + ], + Http::STATUS_UNPROCESSABLE_ENTITY + ); + $this->assertEquals($expected, $this->themingController->updateLogo()); + } + public function testUndo() { $this->l10n ->expects($this->once()) @@ -311,6 +362,7 @@ class ThemingControllerTest extends TestCase { $expected->addHeader('Expires', date(\DateTime::RFC2822, 123)); $expected->addHeader('Content-Disposition', 'attachment'); $expected->addHeader('Content-Type', 'text/svg'); + $expected->addHeader('Pragma', 'cache'); @$this->assertEquals($expected, $this->themingController->getLogo()); } @@ -340,6 +392,7 @@ class ThemingControllerTest extends TestCase { $expected->addHeader('Expires', date(\DateTime::RFC2822, 123)); $expected->addHeader('Content-Disposition', 'attachment'); $expected->addHeader('Content-Type', 'image/png'); + $expected->addHeader('Pragma', 'cache'); @$this->assertEquals($expected, $this->themingController->getLoginBackground()); } @@ -422,6 +475,7 @@ class ThemingControllerTest extends TestCase { $expected->cacheFor(3600); $expected->addHeader('Expires', date(\DateTime::RFC2822, 123)); + $expected->addHeader('Pragma', 'cache'); @$this->assertEquals($expected, $this->themingController->getStylesheet()); } @@ -510,6 +564,7 @@ class ThemingControllerTest extends TestCase { $expected->cacheFor(3600); $expected->addHeader('Expires', date(\DateTime::RFC2822, 123)); + $expected->addHeader('Pragma', 'cache'); @$this->assertEquals($expected, $this->themingController->getStylesheet()); } @@ -553,6 +608,7 @@ class ThemingControllerTest extends TestCase { $expected->cacheFor(3600); $expected->addHeader('Expires', date(\DateTime::RFC2822, 123)); + $expected->addHeader('Pragma', 'cache'); @$this->assertEquals($expected, $this->themingController->getStylesheet()); } @@ -588,6 +644,7 @@ class ThemingControllerTest extends TestCase { $expected->cacheFor(3600); $expected->addHeader('Expires', date(\DateTime::RFC2822, 123)); + $expected->addHeader('Pragma', 'cache'); @$this->assertEquals($expected, $this->themingController->getStylesheet()); } @@ -687,6 +744,7 @@ class ThemingControllerTest extends TestCase { $expected->cacheFor(3600); $expected->addHeader('Expires', date(\DateTime::RFC2822, 123)); + $expected->addHeader('Pragma', 'cache'); @$this->assertEquals($expected, $this->themingController->getStylesheet()); } @@ -791,6 +849,7 @@ class ThemingControllerTest extends TestCase { $expected = new Http\DataDownloadResponse($expectedData, 'style', 'text/css'); $expected->cacheFor(3600); $expected->addHeader('Expires', date(\DateTime::RFC2822, 123)); + $expected->addHeader('Pragma', 'cache'); @$this->assertEquals($expected, $this->themingController->getStylesheet()); } @@ -825,6 +884,7 @@ class ThemingControllerTest extends TestCase { $expected = new Http\DataDisplayResponse($expectedResponse); $expected->addHeader("Content-type","text/javascript"); $expected->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime())); + $expected->addHeader('Pragma', 'cache'); $expected->cacheFor(3600); @$this->assertEquals($expected, $this->themingController->getJavascript()); } @@ -858,6 +918,7 @@ class ThemingControllerTest extends TestCase { $expected = new Http\DataDisplayResponse($expectedResponse); $expected->addHeader("Content-type","text/javascript"); $expected->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime())); + $expected->addHeader('Pragma', 'cache'); $expected->cacheFor(3600); @$this->assertEquals($expected, $this->themingController->getJavascript()); } diff --git a/core/css/styles.css b/core/css/styles.css index 428688060b7..c2b883e4a36 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -32,14 +32,23 @@ body { background-size: cover; } +.two-factor-header { + text-align: center; +} + .two-factor-provider { text-align: center; - width: 100%; + width: 258px !important; display: inline-block; + margin-bottom: 0 !important; + background-color: rgba(0,0,0,0.3) !important; + border: none !important; } -a.two-factor-cancel { - color: #fff; +.two-factor-cancel { + display: inline-block; + padding: 12px; + color: rgba(255, 255, 255, .75); } .float-spinner { diff --git a/core/js/js.js b/core/js/js.js index 4e8d3a01416..799d2ba0b24 100644 --- a/core/js/js.js +++ b/core/js/js.js @@ -1506,12 +1506,20 @@ function initCore() { if(!$app.is('a')) { $app = $app.closest('a'); } - if(!event.ctrlKey) { + if(event.which === 1 && !event.ctrlKey && !event.metaKey) { $app.addClass('app-loading'); } else { // Close navigation when opening app in // a new tab - OC.hideMenus(); + OC.hideMenus(function(){return false}); + } + }); + + $navigation.delegate('a', 'mouseup', function(event) { + if(event.which === 2) { + // Close navigation when opening app in + // a new tab via middle click + OC.hideMenus(function(){return false}); } }); } @@ -1519,14 +1527,29 @@ function initCore() { function setupUserMenu() { var $menu = $('#header #settings'); + // show loading feedback $menu.delegate('a', 'click', function(event) { var $page = $(event.target); if (!$page.is('a')) { $page = $page.closest('a'); } - $page.find('img').remove(); - $page.find('div').remove(); // prevent odd double-clicks - $page.prepend($('<div/>').addClass('icon-loading-small-dark')); + if(event.which === 1 && !event.ctrlKey && !event.metaKey) { + $page.find('img').remove(); + $page.find('div').remove(); // prevent odd double-clicks + $page.prepend($('<div/>').addClass('icon-loading-small-dark')); + } else { + // Close navigation when opening menu entry in + // a new tab + OC.hideMenus(function(){return false}); + } + }); + + $menu.delegate('a', 'mouseup', function(event) { + if(event.which === 2) { + // Close navigation when opening app in + // a new tab via middle click + OC.hideMenus(function(){return false}); + } }); } diff --git a/core/templates/twofactorselectchallenge.php b/core/templates/twofactorselectchallenge.php index 4209beac4e6..1948499e604 100644 --- a/core/templates/twofactorselectchallenge.php +++ b/core/templates/twofactorselectchallenge.php @@ -1,22 +1,22 @@ -<fieldset class="warning"> - <legend><strong><?php p($l->t('Two-step verification')) ?></strong></legend> - <p><?php p($l->t('Enhanced security has been enabled for your account. Please authenticate using a second factor.')) ?></p> -</fieldset> -<fieldset class="warning"> -<ul> -<?php foreach ($_['providers'] as $provider): ?> - <li> - <a class="two-factor-provider" - href="<?php p(\OC::$server->getURLGenerator()->linkToRoute('core.TwoFactorChallenge.showChallenge', - [ - 'challengeProviderId' => $provider->getId(), - 'redirect_url' => $_['redirect_url'], - ] - )) ?>"> - <?php p($provider->getDescription()) ?> - </a> - </li> -<?php endforeach; ?> -</ul> -</fieldset> -<a class="two-factor-cancel" <?php print_unescaped($_['logout_attribute']); ?>><?php p($l->t('Cancel login')) ?></a> +<div class="warning"> + <h2 class="two-factor-header"><?php p($l->t('Two-factor authentication')) ?></h2> + <p><?php p($l->t('Enhanced security is enabled for your account. Please authenticate using a second factor.')) ?></p> + <p> + <ul> + <?php foreach ($_['providers'] as $provider): ?> + <li> + <a class="button two-factor-provider" + href="<?php p(\OC::$server->getURLGenerator()->linkToRoute('core.TwoFactorChallenge.showChallenge', + [ + 'challengeProviderId' => $provider->getId(), + 'redirect_url' => $_['redirect_url'], + ] + )) ?>"> + <?php p($provider->getDescription()) ?> + </a> + </li> + <?php endforeach; ?> + </ul> + </p> +</div> +<a class="two-factor-cancel" <?php print_unescaped($_['logout_attribute']); ?>><?php p($l->t('Cancel log in')) ?></a> diff --git a/core/templates/twofactorshowchallenge.php b/core/templates/twofactorshowchallenge.php index c5ee9aca4b4..fb161921675 100644 --- a/core/templates/twofactorshowchallenge.php +++ b/core/templates/twofactorshowchallenge.php @@ -9,12 +9,11 @@ $provider = $_['provider']; $template = $_['template']; ?> -<fieldset class="warning"> - <legend><strong><?php p($provider->getDisplayName()); ?></strong></legend> - <p><?php p($l->t('Please authenticate using the selected factor.')) ?></p> -</fieldset> -<?php if ($error): ?> -<span class="warning"><?php p($l->t('An error occured while verifying the token')); ?></span> -<?php endif; ?> -<?php print_unescaped($template); ?> -<a class="two-factor-cancel" <?php print_unescaped($_['logout_attribute']); ?>><?php p($l->t('Cancel login')) ?></a> +<div class="warning"> + <h2 class="two-factor-header"><?php p($provider->getDisplayName()); ?></h2> + <?php if ($error): ?> + <p><strong><?php p($l->t('Error while validating your second factor')); ?></strong></p> + <?php endif; ?> + <?php print_unescaped($template); ?> +</div> +<a class="two-factor-cancel" <?php print_unescaped($_['logout_attribute']); ?>><?php p($l->t('Cancel log in')) ?></a> diff --git a/lib/private/Files/Mount/MountPoint.php b/lib/private/Files/Mount/MountPoint.php index 4aef340149c..42b79596c98 100644 --- a/lib/private/Files/Mount/MountPoint.php +++ b/lib/private/Files/Mount/MountPoint.php @@ -41,6 +41,7 @@ class MountPoint implements IMountPoint { protected $storage = null; protected $class; protected $storageId; + protected $rootId = null; /** * Configuration options for the storage backend @@ -264,7 +265,10 @@ class MountPoint implements IMountPoint { * @return int */ public function getStorageRootId() { - return (int)$this->getStorage()->getCache()->getId(''); + if (is_null($this->rootId)) { + $this->rootId = (int)$this->getStorage()->getCache()->getId(''); + } + return $this->rootId; } public function getMountId() { diff --git a/lib/private/Files/Node/Root.php b/lib/private/Files/Node/Root.php index bad865a7987..007847fb513 100644 --- a/lib/private/Files/Node/Root.php +++ b/lib/private/Files/Node/Root.php @@ -28,6 +28,7 @@ namespace OC\Files\Node; +use OC\Cache\CappedMemoryCache; use OC\Files\Mount\Manager; use OC\Files\Mount\MountPoint; use OCP\Files\NotFoundException; @@ -71,6 +72,8 @@ class Root extends Folder implements IRootFolder { */ private $user; + private $userFolderCache; + /** * @param \OC\Files\Mount\Manager $manager * @param \OC\Files\View $view @@ -81,6 +84,7 @@ class Root extends Folder implements IRootFolder { $this->mountManager = $manager; $this->user = $user; $this->emitter = new PublicEmitter(); + $this->userFolderCache = new CappedMemoryCache(); } /** @@ -335,25 +339,26 @@ class Root extends Folder implements IRootFolder { * @return \OCP\Files\Folder */ public function getUserFolder($userId) { - \OC\Files\Filesystem::initMountPoints($userId); - $dir = '/' . $userId; - $folder = null; - - try { - $folder = $this->get($dir); - } catch (NotFoundException $e) { - $folder = $this->newFolder($dir); - } + if (!$this->userFolderCache->hasKey($userId)) { + \OC\Files\Filesystem::initMountPoints($userId); + + try { + $folder = $this->get('/' . $userId . '/files'); + } catch (NotFoundException $e) { + if (!$this->nodeExists('/' . $userId)) { + $this->newFolder('/' . $userId); + } + $folder = $this->newFolder('/' . $userId . '/files'); + \OC_Util::copySkeleton($userId, $folder); + } - $dir = '/files'; - try { - $folder = $folder->get($dir); - } catch (NotFoundException $e) { - $folder = $folder->newFolder($dir); - \OC_Util::copySkeleton($userId, $folder); + $this->userFolderCache->set($userId, $folder); } - return $folder; + return $this->userFolderCache->get($userId); + } + public function clearCache() { + $this->userFolderCache = new CappedMemoryCache(); } } diff --git a/lib/private/legacy/util.php b/lib/private/legacy/util.php index 7341331518d..648be70cf0d 100644 --- a/lib/private/legacy/util.php +++ b/lib/private/legacy/util.php @@ -356,6 +356,7 @@ class OC_Util { */ public static function tearDownFS() { \OC\Files\Filesystem::tearDown(); + \OC::$server->getRootFolder()->clearCache(); self::$fsSetup = false; self::$rootMounted = false; } diff --git a/tests/lib/TestCase.php b/tests/lib/TestCase.php index 514cb6ea3a5..b9b18c644fd 100644 --- a/tests/lib/TestCase.php +++ b/tests/lib/TestCase.php @@ -24,6 +24,7 @@ namespace Test; use DOMDocument; use DOMNode; +use OC\Cache\CappedMemoryCache; use OC\Command\QueueBus; use OC\Files\Filesystem; use OC\Template\Base; |