diff options
44 files changed, 326 insertions, 37 deletions
diff --git a/.htaccess b/.htaccess index 35c478860d5..392b9b41559 100644 --- a/.htaccess +++ b/.htaccess @@ -28,7 +28,7 @@ php_value mbstring.func_overload 0 php_value always_populate_raw_post_data -1 php_value default_charset 'UTF-8' - php_value output_buffering off + php_value output_buffering 0 <IfModule mod_env.c> SetEnv htaccessWorking true </IfModule> diff --git a/.user.ini b/.user.ini index 66bf6484fe2..68ef3e8672c 100644 --- a/.user.ini +++ b/.user.ini @@ -4,4 +4,4 @@ memory_limit=512M mbstring.func_overload=0 always_populate_raw_post_data=-1 default_charset='UTF-8' -output_buffering=off
\ No newline at end of file +output_buffering=0 diff --git a/apps/files/css/detailsView.css b/apps/files/css/detailsView.css index faa26678562..485c20e6865 100644 --- a/apps/files/css/detailsView.css +++ b/apps/files/css/detailsView.css @@ -40,7 +40,7 @@ height: auto; } -#app-sidebar .image.landscape .thumbnail::before { +#app-sidebar .image .thumbnail .stretcher { content: ''; display: block; padding-bottom: 56.25%; /* sets height of .thumbnail to 9/16 of the width */ diff --git a/apps/files/css/files.css b/apps/files/css/files.css index c0701fb18b8..1d4d0774482 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -186,9 +186,15 @@ table th .sort-indicator { filter: alpha(opacity=30); opacity: .3; } -.sort-indicator.hidden { +.sort-indicator.hidden, +.multiselect .sort-indicator, +table.multiselect th:hover .sort-indicator.hidden, +table.multiselect th:focus .sort-indicator.hidden { visibility: hidden; } +.multiselect .sort, .multiselect .sort span { + cursor: default; +} table th:hover .sort-indicator.hidden, table th:focus .sort-indicator.hidden { visibility: visible; @@ -574,6 +580,9 @@ a.action > img { #fileList .popovermenu { margin-right: 21px; } +.ie8 #fileList .popovermenu { + margin-top: -10px; +} .ie8 #fileList a.action img, #fileList tr:hover a.action, @@ -746,6 +755,12 @@ table.dragshadow td.size { margin: 0; } +.newFileMenu.popovermenu a.menuitem.active { + opacity: 1; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; + filter: alpha(opacity=100); +} + .newFileMenu.bubble:after { left: 75px; right: auto; diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 16aa643d11b..9c4e43b3b8b 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -628,6 +628,9 @@ * Event handler when clicking on a table header */ _onClickHeader: function(e) { + if (this.$table.hasClass('multiselect')) { + return; + } var $target = $(e.target); var sort; if (!$target.is('a')) { diff --git a/apps/files/js/mainfileinfodetailview.js b/apps/files/js/mainfileinfodetailview.js index 82cca0d0fb3..b50e92dea8c 100644 --- a/apps/files/js/mainfileinfodetailview.js +++ b/apps/files/js/mainfileinfodetailview.js @@ -10,7 +10,7 @@ (function() { var TEMPLATE = - '<div class="thumbnailContainer"><a href="#" class="thumbnail action-default"></a></div>' + + '<div class="thumbnailContainer"><a href="#" class="thumbnail action-default"><div class="stretcher"/></a></div>' + '<div class="file-details-container">' + '<div class="fileName"><h3 title="{{name}}" class="ellipsis">{{name}}</h3></div>' + ' <div class="file-details ellipsis">' + @@ -131,6 +131,7 @@ } else { // TODO: special icons / shared / external $iconDiv.css('background-image', 'url("' + OC.MimeType.getIconUrl('dir') + '")'); + OC.Util.scaleFixForIE8($iconDiv); } this.$el.find('[title]').tooltip({placement: 'bottom'}); } else { @@ -140,13 +141,18 @@ }, loadPreview: function(path, mime, etag, $iconDiv, $container, isImage) { - var maxImageHeight = ($container.parent().width() + 50) / (16/9); // 30px for negative margin + var maxImageWidth = $container.parent().width() + 50; // 50px for negative margins + var maxImageHeight = maxImageWidth / (16/9); var smallPreviewSize = 75; var isLandscape = function(img) { return img.width > (img.height * 1.2); }; + var isSmall = function(img) { + return (img.width * 1.1) < (maxImageWidth * window.devicePixelRatio); + }; + var getTargetHeight = function(img) { if(isImage) { var targetHeight = img.height / window.devicePixelRatio; @@ -159,13 +165,23 @@ } }; + var getTargetRatio = function(img){ + var ratio = img.width / img.height; + if (ratio > 16/9) { + return ratio; + } else { + return 16/9; + } + }; + this._fileList.lazyLoadPreview({ path: path, mime: mime, etag: etag, y: isImage ? maxImageHeight : smallPreviewSize, - x: isImage ? 99999 /* only limit on y */ : smallPreviewSize, + x: isImage ? maxImageWidth : smallPreviewSize, a: isImage ? 1 : null, + mode: isImage ? 'cover' : null, callback: function (previewUrl, img) { $iconDiv.previewImg = previewUrl; @@ -176,7 +192,7 @@ $iconDiv.removeClass('icon-loading icon-32'); var targetHeight = getTargetHeight(img); if (this.model.isImage() && targetHeight > smallPreviewSize) { - $container.addClass(isLandscape(img)? 'landscape': 'portrait'); + $container.addClass((isLandscape(img) && !isSmall(img))? 'landscape': 'portrait'); $container.addClass('image'); } @@ -184,7 +200,13 @@ // when we dont have a preview we show the mime icon in the error handler $iconDiv.css({ 'background-image': 'url("' + previewUrl + '")', - height: (isLandscape(img) && targetHeight > smallPreviewSize)? 'auto': targetHeight + height: (targetHeight > smallPreviewSize)? 'auto': targetHeight, + 'max-height': isSmall(img)? targetHeight: null + }); + + var targetRatio = getTargetRatio(img); + $iconDiv.find('.stretcher').css({ + 'padding-bottom': (100 / targetRatio) + '%' }); }.bind(this), error: function () { @@ -193,6 +215,7 @@ $iconDiv.css({ 'background-image': 'url("' + $iconDiv.previewImg + '")' }); + OC.Util.scaleFixForIE8($iconDiv); }.bind(this) }); } diff --git a/apps/files/js/newfilemenu.js b/apps/files/js/newfilemenu.js index 4c021e6b873..0a67aba202b 100644 --- a/apps/files/js/newfilemenu.js +++ b/apps/files/js/newfilemenu.js @@ -84,6 +84,8 @@ OC.hideMenus(); } else { event.preventDefault(); + this.$el.find('.menuitem.active').removeClass('active'); + $target.addClass('active'); this._promptFileName($target); } }, @@ -210,6 +212,7 @@ fileType: 'folder' }] })); + OC.Util.scaleFixForIE8(this.$('.svg')); }, /** diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js index b3d85cf08fa..96018917c85 100644 --- a/apps/files/tests/js/filelistSpec.js +++ b/apps/files/tests/js/filelistSpec.js @@ -2188,6 +2188,25 @@ describe('OCA.Files.FileList tests', function() { expect(fileList.files.length).toEqual(5); expect(fileList.$fileList.find('tr').length).toEqual(5); }); + it('does not sort when clicking on header whenever multiselect is enabled', function() { + var sortStub = sinon.stub(OCA.Files.FileList.prototype, 'setSort'); + + fileList.setFiles(testFiles); + fileList.findFileEl('One.txt').find('input:checkbox:first').click(); + + fileList.$el.find('.column-size .columntitle').click(); + + expect(sortStub.notCalled).toEqual(true); + + // can sort again after deselecting + fileList.findFileEl('One.txt').find('input:checkbox:first').click(); + + fileList.$el.find('.column-size .columntitle').click(); + + expect(sortStub.calledOnce).toEqual(true); + + sortStub.restore(); + }); }); describe('create file', function() { var deferredCreate; diff --git a/apps/files_sharing/lib/controllers/sharecontroller.php b/apps/files_sharing/lib/controllers/sharecontroller.php index ecf3ee853ee..28feb3110b4 100644 --- a/apps/files_sharing/lib/controllers/sharecontroller.php +++ b/apps/files_sharing/lib/controllers/sharecontroller.php @@ -46,6 +46,7 @@ use OCA\Files_Sharing\Helper; use OCP\User; use OCP\Util; use OCA\Files_Sharing\Activity; +use \OCP\Files\NotFoundException; /** * Class ShareController @@ -148,6 +149,7 @@ class ShareController extends Controller { * @param string $token * @param string $path * @return TemplateResponse|RedirectResponse + * @throws NotFoundException */ public function showShare($token, $path = '') { \OC_User::setIncognitoMode(true); @@ -171,7 +173,7 @@ class ShareController extends Controller { $getPath = Filesystem::normalizePath($path); $originalSharePath .= $path; } else { - throw new OCP\Files\NotFoundException(); + throw new NotFoundException(); } $file = basename($originalSharePath); @@ -303,7 +305,7 @@ class ShareController extends Controller { /** * @param string $token * @return string Resolved file path of the token - * @throws \Exception In case share could not get properly resolved + * @throws NotFoundException In case share could not get properly resolved */ private function getPath($token) { $linkItem = Share::getShareByToken($token, false); @@ -312,7 +314,7 @@ class ShareController extends Controller { $rootLinkItem = Share::resolveReShare($linkItem); if (isset($rootLinkItem['uid_owner'])) { if(!$this->userManager->userExists($rootLinkItem['uid_owner'])) { - throw new \Exception('Owner of the share does not exist anymore'); + throw new NotFoundException('Owner of the share does not exist anymore'); } OC_Util::tearDownFS(); OC_Util::setupFS($rootLinkItem['uid_owner']); @@ -324,6 +326,6 @@ class ShareController extends Controller { } } - throw new \Exception('No file found belonging to file.'); + throw new NotFoundException('No file found belonging to file.'); } } diff --git a/apps/files_sharing/lib/middleware/sharingcheckmiddleware.php b/apps/files_sharing/lib/middleware/sharingcheckmiddleware.php index 1c29b1da736..61dfd914d0b 100644 --- a/apps/files_sharing/lib/middleware/sharingcheckmiddleware.php +++ b/apps/files_sharing/lib/middleware/sharingcheckmiddleware.php @@ -27,6 +27,7 @@ use OCP\App\IAppManager; use OCP\AppFramework\Http\NotFoundResponse; use OCP\AppFramework\Middleware; use OCP\AppFramework\Http\TemplateResponse; +use OCP\Files\NotFoundException; use OCP\IConfig; /** @@ -58,22 +59,32 @@ class SharingCheckMiddleware extends Middleware { /** * Check if sharing is enabled before the controllers is executed + * + * @param \OCP\AppFramework\Controller $controller + * @param string $methodName + * @throws NotFoundException */ public function beforeController($controller, $methodName) { if(!$this->isSharingEnabled()) { - throw new \Exception('Sharing is disabled.'); + throw new NotFoundException('Sharing is disabled.'); } } /** - * Return 404 page in case of an exception + * Return 404 page in case of a not found exception + * * @param \OCP\AppFramework\Controller $controller * @param string $methodName * @param \Exception $exception - * @return TemplateResponse + * @return NotFoundResponse + * @throws \Exception */ - public function afterException($controller, $methodName, \Exception $exception){ - return new NotFoundResponse(); + public function afterException($controller, $methodName, \Exception $exception) { + if(is_a($exception, '\OCP\Files\NotFoundException')) { + return new NotFoundResponse(); + } + + throw $exception; } /** diff --git a/apps/files_sharing/tests/middleware/sharingcheckmiddleware.php b/apps/files_sharing/tests/middleware/sharingcheckmiddleware.php index 58f4b841339..3171d45d331 100644 --- a/apps/files_sharing/tests/middleware/sharingcheckmiddleware.php +++ b/apps/files_sharing/tests/middleware/sharingcheckmiddleware.php @@ -23,7 +23,8 @@ */ namespace OCA\Files_Sharing\Middleware; - +use OCP\AppFramework\Http\NotFoundResponse; +use OCP\Files\NotFoundException; /** * @package OCA\Files_Sharing\Middleware\SharingCheckMiddleware @@ -36,12 +37,16 @@ class SharingCheckMiddlewareTest extends \Test\TestCase { private $appManager; /** @var SharingCheckMiddleware */ private $sharingCheckMiddleware; + /** @var \OCP\AppFramework\Controller */ + private $controllerMock; protected function setUp() { $this->config = $this->getMockBuilder('\OCP\IConfig') ->disableOriginalConstructor()->getMock(); $this->appManager = $this->getMockBuilder('\OCP\App\IAppManager') ->disableOriginalConstructor()->getMock(); + $this->controllerMock = $this->getMockBuilder('\OCP\AppFramework\Controller') + ->disableOriginalConstructor()->getMock(); $this->sharingCheckMiddleware = new SharingCheckMiddleware('files_sharing', $this->config, $this->appManager); } @@ -116,4 +121,52 @@ class SharingCheckMiddlewareTest extends \Test\TestCase { $this->assertFalse(self::invokePrivate($this->sharingCheckMiddleware, 'isSharingEnabled')); } + public function testBeforeControllerWithSharingEnabled() { + $this->appManager + ->expects($this->once()) + ->method('isEnabledForUser') + ->with('files_sharing') + ->will($this->returnValue(true)); + + $this->config + ->expects($this->at(0)) + ->method('getAppValue') + ->with('core', 'shareapi_enabled', 'yes') + ->will($this->returnValue('yes')); + + $this->config + ->expects($this->at(1)) + ->method('getAppValue') + ->with('core', 'shareapi_allow_links', 'yes') + ->will($this->returnValue('yes')); + + $this->sharingCheckMiddleware->beforeController($this->controllerMock, 'myMethod'); + } + + /** + * @expectedException \OCP\Files\NotFoundException + * @expectedExceptionMessage Sharing is disabled. + */ + public function testBeforeControllerWithSharingDisabled() { + $this->appManager + ->expects($this->once()) + ->method('isEnabledForUser') + ->with('files_sharing') + ->will($this->returnValue(false)); + + $this->sharingCheckMiddleware->beforeController($this->controllerMock, 'myMethod'); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage My Exception message + */ + public function testAfterExceptionWithRegularException() { + $this->sharingCheckMiddleware->afterException($this->controllerMock, 'myMethod', new \Exception('My Exception message')); + } + + public function testAfterExceptionWithNotFoundException() { + $this->assertEquals(new NotFoundResponse(), $this->sharingCheckMiddleware->afterException($this->controllerMock, 'myMethod', new NotFoundException('My Exception message'))); + } + } diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php index fe9eefb3116..2a605a2a0f0 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -215,7 +215,9 @@ class Access extends LDAPUtility implements user\IUserTools { $resemblingAttributes = array( 'dn', 'uniquemember', - 'member' + 'member', + // memberOf is an "operational" attribute, without a definition in any RFC + 'memberof' ); return in_array($attr, $resemblingAttributes); } diff --git a/apps/user_ldap/tests/access.php b/apps/user_ldap/tests/access.php index 5bf1a65bd51..cb6dbf0cd5d 100644 --- a/apps/user_ldap/tests/access.php +++ b/apps/user_ldap/tests/access.php @@ -260,4 +260,38 @@ class Test_Access extends \Test\TestCase { $access->batchApplyUserAttributes($data); } + + public function dNAttributeProvider() { + // corresponds to Access::resemblesDN() + return array( + 'dn' => array('dn'), + 'uniqueMember' => array('uniquemember'), + 'member' => array('member'), + 'memberOf' => array('memberof') + ); + } + + /** + * @dataProvider dNAttributeProvider + */ + public function testSanitizeDN($attribute) { + list($lw, $con, $um) = $this->getConnectorAndLdapMock(); + + + $dnFromServer = 'cn=Mixed Cases,ou=Are Sufficient To,ou=Test,dc=example,dc=org'; + + $lw->expects($this->any()) + ->method('isResource') + ->will($this->returnValue(true)); + + $lw->expects($this->any()) + ->method('getAttributes') + ->will($this->returnValue(array( + $attribute => array('count' => 1, $dnFromServer) + ))); + + $access = new Access($con, $lw, $um); + $values = $access->readAttribute('uid=whoever,dc=example,dc=org', $attribute); + $this->assertSame($values[0], strtolower($dnFromServer)); + } } diff --git a/core/css/apps.css b/core/css/apps.css index 23e0c519d00..3122a2b48a1 100644 --- a/core/css/apps.css +++ b/core/css/apps.css @@ -308,6 +308,13 @@ -o-filter: drop-shadow(0 0 5px rgba(150, 150, 150, 0.75)); filter: drop-shadow(0 0 5px rgba(150, 150, 150, 0.75)); } +.ie8 .bubble { + border: 1px solid #eee; + margin-top: 18px; +} +.ie8 .bubble:after { + display: none; +} /* miraculous border arrow stuff */ .bubble:after, #app-navigation .app-navigation-entry-menu:after { diff --git a/core/css/fixes.css b/core/css/fixes.css index 7ef44ba6909..54852eb9beb 100644 --- a/core/css/fixes.css +++ b/core/css/fixes.css @@ -38,6 +38,10 @@ select { background-image: url('../img/actions/settings.png'); } +/* IE8 needs PNG image for header logo */ +.ie8 #header .logo { + background-image: url(../img/logo-icon-175px.png); +} /* IE8 needs background to be set to same color to make transparency look good. */ .lte9 #body-login form input[type="text"] { @@ -51,6 +55,15 @@ select { border-bottom: 1px solid lightgrey; background-color: white; /* don't change background on hover */ } +.ie8 #body-login input[type="submit"] { + padding: 10px 5px; + margin-top: 3px; +} +/* for whatever unexplained reason */ +.ie8 #password { + width: 271px !important; + min-width: auto !important; +} /* disable opacity of info text on gradient since we cannot set a good backround color to use the filter&background hack as with the input labels */ diff --git a/core/img/filetypes/application-pdf.png b/core/img/filetypes/application-pdf.png Binary files differindex 4029f8aead1..c215094eaa7 100644 --- a/core/img/filetypes/application-pdf.png +++ b/core/img/filetypes/application-pdf.png diff --git a/core/img/filetypes/application.png b/core/img/filetypes/application.png Binary files differindex 9be7361d1b6..d9db3b9114c 100644 --- a/core/img/filetypes/application.png +++ b/core/img/filetypes/application.png diff --git a/core/img/filetypes/audio.png b/core/img/filetypes/audio.png Binary files differindex 4eb8ab78e3f..3d52756341a 100644 --- a/core/img/filetypes/audio.png +++ b/core/img/filetypes/audio.png diff --git a/core/img/filetypes/file.png b/core/img/filetypes/file.png Binary files differindex 3bd7463cfc9..74add13f276 100644 --- a/core/img/filetypes/file.png +++ b/core/img/filetypes/file.png diff --git a/core/img/filetypes/folder-drag-accept.png b/core/img/filetypes/folder-drag-accept.png Binary files differindex 80ab53b72b9..1124a02982f 100644 --- a/core/img/filetypes/folder-drag-accept.png +++ b/core/img/filetypes/folder-drag-accept.png diff --git a/core/img/filetypes/folder-external.png b/core/img/filetypes/folder-external.png Binary files differindex 5262d72e627..dd8343d245a 100644 --- a/core/img/filetypes/folder-external.png +++ b/core/img/filetypes/folder-external.png diff --git a/core/img/filetypes/folder-public.png b/core/img/filetypes/folder-public.png Binary files differindex 17c3ee2a8d9..3da67f85f79 100644 --- a/core/img/filetypes/folder-public.png +++ b/core/img/filetypes/folder-public.png diff --git a/core/img/filetypes/folder-shared.png b/core/img/filetypes/folder-shared.png Binary files differindex be5e59cbf28..d24e1d7af4e 100644 --- a/core/img/filetypes/folder-shared.png +++ b/core/img/filetypes/folder-shared.png diff --git a/core/img/filetypes/folder-starred.png b/core/img/filetypes/folder-starred.png Binary files differindex b083a9d2d11..4b847bf69ea 100644 --- a/core/img/filetypes/folder-starred.png +++ b/core/img/filetypes/folder-starred.png diff --git a/core/img/filetypes/folder.png b/core/img/filetypes/folder.png Binary files differindex 1dbb1154100..e811e9cdfdc 100644 --- a/core/img/filetypes/folder.png +++ b/core/img/filetypes/folder.png diff --git a/core/img/filetypes/image.png b/core/img/filetypes/image.png Binary files differindex 0feaecf2830..8ff5e6c119f 100644 --- a/core/img/filetypes/image.png +++ b/core/img/filetypes/image.png diff --git a/core/img/filetypes/package-x-generic.png b/core/img/filetypes/package-x-generic.png Binary files differindex 287a1f18869..68117e0d070 100644 --- a/core/img/filetypes/package-x-generic.png +++ b/core/img/filetypes/package-x-generic.png diff --git a/core/img/filetypes/text-calendar.png b/core/img/filetypes/text-calendar.png Binary files differindex ff3ced62531..f21c3a9951d 100644 --- a/core/img/filetypes/text-calendar.png +++ b/core/img/filetypes/text-calendar.png diff --git a/core/img/filetypes/text-code.png b/core/img/filetypes/text-code.png Binary files differindex 5505102f60e..69744e499e6 100644 --- a/core/img/filetypes/text-code.png +++ b/core/img/filetypes/text-code.png diff --git a/core/img/filetypes/text-vcard.png b/core/img/filetypes/text-vcard.png Binary files differindex 77ac138fe1c..087eadaabd1 100644 --- a/core/img/filetypes/text-vcard.png +++ b/core/img/filetypes/text-vcard.png diff --git a/core/img/filetypes/text.png b/core/img/filetypes/text.png Binary files differindex 5fca7cb69d7..d6bec70cf43 100644 --- a/core/img/filetypes/text.png +++ b/core/img/filetypes/text.png diff --git a/core/img/filetypes/video.png b/core/img/filetypes/video.png Binary files differindex 308e81cca83..7cc1ecdc46a 100644 --- a/core/img/filetypes/video.png +++ b/core/img/filetypes/video.png diff --git a/core/img/filetypes/x-office-document.png b/core/img/filetypes/x-office-document.png Binary files differindex d9c5b890583..3bc2f08d1f9 100644 --- a/core/img/filetypes/x-office-document.png +++ b/core/img/filetypes/x-office-document.png diff --git a/core/img/filetypes/x-office-presentation.png b/core/img/filetypes/x-office-presentation.png Binary files differindex 5b3733b7121..644fb852009 100644 --- a/core/img/filetypes/x-office-presentation.png +++ b/core/img/filetypes/x-office-presentation.png diff --git a/core/img/filetypes/x-office-spreadsheet.png b/core/img/filetypes/x-office-spreadsheet.png Binary files differindex 5a20026ebdd..8f79c32fe01 100644 --- a/core/img/filetypes/x-office-spreadsheet.png +++ b/core/img/filetypes/x-office-spreadsheet.png diff --git a/core/img/logo-icon-175px.png b/core/img/logo-icon-175px.png Binary files differnew file mode 100644 index 00000000000..67e76498670 --- /dev/null +++ b/core/img/logo-icon-175px.png diff --git a/core/js/js.js b/core/js/js.js index 397fea8e3c5..e40141ac617 100644 --- a/core/js/js.js +++ b/core/js/js.js @@ -1597,6 +1597,46 @@ OC.Util = { }, /** + * Fix image scaling for IE8, since background-size is not supported. + * + * This scales the image to the element's actual size, the URL is + * taken from the "background-image" CSS attribute. + * + * @param {Object} $el image element + */ + scaleFixForIE8: function($el) { + if (!this.isIE8()) { + return; + } + var self = this; + $($el).each(function() { + var url = $(this).css('background-image'); + var r = url.match(/url\(['"]?([^'")]*)['"]?\)/); + if (!r) { + return; + } + url = r[1]; + url = self.replaceSVGIcon(url); + // TODO: escape + url = url.replace(/'/g, '%27'); + $(this).css({ + 'filter': 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + url + '\', sizingMethod=\'scale\')', + 'background-image': '' + }); + }); + return $el; + }, + + /** + * Returns whether this is IE8 + * + * @return {bool} true if this is IE8, false otherwise + */ + isIE8: function() { + return $('html').hasClass('ie8'); + }, + + /** * Remove the time component from a given date * * @param {Date} date date diff --git a/core/js/sharedialoglinkshareview.js b/core/js/sharedialoglinkshareview.js index cb9325231dd..3d8fb461461 100644 --- a/core/js/sharedialoglinkshareview.js +++ b/core/js/sharedialoglinkshareview.js @@ -144,17 +144,33 @@ }, onPasswordEntered: function() { - var password = this.$el.find('#linkPassText').val(); + var self = this; + var $loading = this.$el.find('#linkPass .icon-loading-small'); + if (!$loading.hasClass('hidden')) { + // still in process + return; + } + var $input = this.$el.find('#linkPassText'); + $input.removeClass('error'); + var password = $input.val(); if(password === '') { return; } - this.$el.find('#linkPass .icon-loading-small') + $loading .removeClass('hidden') .addClass('inlineblock'); this.model.setPassword(password); - this.model.saveLinkShare(); + this.model.saveLinkShare({}, { + error: function(model, msg) { + $loading.removeClass('inlineblock').addClass('hidden'); + $input.addClass('error'); + $input.attr('title', msg); + $input.tooltip({placement: 'bottom', trigger: 'manual'}); + $input.tooltip('show'); + } + }); }, onAllowPublicUploadChange: function() { diff --git a/core/templates/login.php b/core/templates/login.php index db77f63bbd0..6751d92f656 100644 --- a/core/templates/login.php +++ b/core/templates/login.php @@ -55,7 +55,7 @@ script('core', [ autocomplete="on" autocapitalize="off" autocorrect="off" required> <label for="password" class="infield"><?php p($l->t('Password')); ?></label> <img class="svg" id="password-icon" src="<?php print_unescaped(image_path('', 'actions/password.svg')); ?>" alt=""/> - <input type="submit" id="submit" class="login primary icon-confirm" title="<?php p($l->t('Log in')); ?>" value="" disabled="disabled"/> + <input type="submit" id="submit" class="login primary icon-confirm svg" title="<?php p($l->t('Log in')); ?>" value="" disabled="disabled"/> </p> <?php if (isset($_['invalidpassword']) && ($_['invalidpassword'])): ?> diff --git a/lib/private/files/cache/scanner.php b/lib/private/files/cache/scanner.php index fb60ee5aa53..bfdab16b645 100644 --- a/lib/private/files/cache/scanner.php +++ b/lib/private/files/cache/scanner.php @@ -186,9 +186,9 @@ class Scanner extends BasicEmitter { } if (!empty($newData)) { $data['fileid'] = $this->addToCache($file, $newData, $fileId); - $this->emit('\OC\Files\Cache\Scanner', 'postScanFile', array($file, $this->storageId)); - \OC_Hook::emit('\OC\Files\Cache\Scanner', 'post_scan_file', array('path' => $file, 'storage' => $this->storageId)); } + $this->emit('\OC\Files\Cache\Scanner', 'postScanFile', array($file, $this->storageId)); + \OC_Hook::emit('\OC\Files\Cache\Scanner', 'post_scan_file', array('path' => $file, 'storage' => $this->storageId)); } else { $this->removeFromCache($file); } diff --git a/lib/private/files/utils/scanner.php b/lib/private/files/utils/scanner.php index c70f4beb31d..558a1fba028 100644 --- a/lib/private/files/utils/scanner.php +++ b/lib/private/files/utils/scanner.php @@ -99,7 +99,12 @@ class Scanner extends PublicEmitter { $scanner->listen('\OC\Files\Cache\Scanner', 'scanFolder', function ($path) use ($mount, $emitter) { $emitter->emit('\OC\Files\Utils\Scanner', 'scanFolder', array($mount->getMountPoint() . $path)); }); - + $scanner->listen('\OC\Files\Cache\Scanner', 'postScanFile', function ($path) use ($mount, $emitter) { + $emitter->emit('\OC\Files\Utils\Scanner', 'postScanFile', array($mount->getMountPoint() . $path)); + }); + $scanner->listen('\OC\Files\Cache\Scanner', 'postScanFolder', function ($path) use ($mount, $emitter) { + $emitter->emit('\OC\Files\Utils\Scanner', 'postScanFolder', array($mount->getMountPoint() . $path)); + }); // propagate etag and mtimes when files are changed or removed $propagator = $this->propagator; $propagatorListener = function ($path) use ($mount, $propagator) { diff --git a/lib/private/preview.php b/lib/private/preview.php index de964b72df2..1127048b7fd 100644 --- a/lib/private/preview.php +++ b/lib/private/preview.php @@ -837,6 +837,11 @@ class Preview { $askedWidth = $this->getMaxX(); $askedHeight = $this->getMaxY(); + if ($this->mode === self::MODE_COVER) { + list($askedWidth, $askedHeight) = + $this->applyCover($askedWidth, $askedHeight, $previewWidth, $previewHeight); + } + /** * Phase 1: If required, adjust boundaries to keep aspect ratio */ @@ -845,20 +850,12 @@ class Preview { $this->applyAspectRatio($askedWidth, $askedHeight, $previewWidth, $previewHeight); } - if ($this->mode === self::MODE_COVER) { - list($scaleWidth, $scaleHeight) = - $this->applyCover($askedWidth, $askedHeight, $previewWidth, $previewHeight); - } else { - $scaleWidth = $askedWidth; - $scaleHeight = $askedHeight; - } - /** * Phase 2: Resizes preview to try and match requirements. * Takes the scaling ratio into consideration */ list($newPreviewWidth, $newPreviewHeight) = $this->scale( - $image, $scaleWidth, $scaleHeight, $previewWidth, $previewHeight + $image, $askedWidth, $askedHeight, $previewWidth, $previewHeight ); // The preview has been resized and should now have the asked dimensions @@ -890,6 +887,7 @@ class Preview { return; } + // The preview is smaller, but we can't touch it $this->storePreview($fileId, $newPreviewWidth, $newPreviewHeight); } diff --git a/lib/private/preview/image.php b/lib/private/preview/image.php index f9c27e690f6..fd90b15eb0c 100644 --- a/lib/private/preview/image.php +++ b/lib/private/preview/image.php @@ -46,12 +46,16 @@ abstract class Image extends Provider { $image = new \OC_Image(); - if ($fileInfo['encrypted'] === true) { + $useTempFile = $fileInfo->isEncrypted() || !$fileInfo->getStorage()->isLocal(); + if ($useTempFile) { $fileName = $fileview->toTmpFile($path); } else { $fileName = $fileview->getLocalFile($path); } $image->loadFromFile($fileName); + if ($useTempFile) { + unlink($fileName); + } $image->fixOrientation(); if ($image->valid()) { $image->scaleDownToFit($maxX, $maxY); diff --git a/tests/lib/preview.php b/tests/lib/preview.php index de1669cbf85..9374cf2393f 100644 --- a/tests/lib/preview.php +++ b/tests/lib/preview.php @@ -874,4 +874,45 @@ class Preview extends TestCase { return [(int)$askedWidth, (int)$askedHeight]; } + + public function testKeepAspectRatio() { + $originalWidth = 1680; + $originalHeight = 1050; + $originalAspectRation = $originalWidth / $originalHeight; + + $preview = new \OC\Preview( + self::TEST_PREVIEW_USER1, 'files/', 'testimage.jpg', + 150, + 150 + ); + $preview->setKeepAspect(true); + $image = $preview->getPreview(); + + $aspectRatio = $image->width() / $image->height(); + $this->assertEquals(round($originalAspectRation, 2), round($aspectRatio, 2)); + + $this->assertLessThanOrEqual(150, $image->width()); + $this->assertLessThanOrEqual(150, $image->height()); + } + + public function testKeepAspectRatioCover() { + $originalWidth = 1680; + $originalHeight = 1050; + $originalAspectRation = $originalWidth / $originalHeight; + + $preview = new \OC\Preview( + self::TEST_PREVIEW_USER1, 'files/', 'testimage.jpg', + 150, + 150 + ); + $preview->setKeepAspect(true); + $preview->setMode(\OC\Preview::MODE_COVER); + $image = $preview->getPreview(); + + $aspectRatio = $image->width() / $image->height(); + $this->assertEquals(round($originalAspectRation, 2), round($aspectRatio, 2)); + + $this->assertGreaterThanOrEqual(150, $image->width()); + $this->assertGreaterThanOrEqual(150, $image->height()); + } } |