diff --git a/.scrutinizer.yml b/.scrutinizer.yml new file mode 100644 index 0000000000..4473cf9056 --- /dev/null +++ b/.scrutinizer.yml @@ -0,0 +1,23 @@ +filter: + excluded_paths: + - '3rdparty/*' + - 'apps/*/3rdparty/*' + - 'l10n/*' + - 'core/l10n/*' + - 'apps/*/l10n/*' + - 'lib/l10n/*' + - 'core/js/tests/lib/*.js' + - 'core/js/jquery-1.10.0.min.js' + - 'core/js/jquery-migrate-1.2.1.min.js' + - 'core/js/jquery-showpassword.js' + - 'core/js/jquery-tipsy.js' + - 'core/js/jquery.infieldlabel.js' + - 'core/js/jquery-ui-1.10.0.custom.js' + - 'core/js/jquery.inview.js' + - 'core/js/jquery.placeholder.js' + + +imports: + - javascript + - php + diff --git a/3rdparty b/3rdparty index c77c4ddbd4..184f0a59f8 160000 --- a/3rdparty +++ b/3rdparty @@ -1 +1 @@ -Subproject commit c77c4ddbd4ae86a307d073647e76d602eafd0c64 +Subproject commit 184f0a59f87c590ee7e89ced401205a87f213954 diff --git a/apps/files/ajax/move.php b/apps/files/ajax/move.php index 93063e52eb..04a260265c 100644 --- a/apps/files/ajax/move.php +++ b/apps/files/ajax/move.php @@ -18,7 +18,7 @@ if(\OC\Files\Filesystem::file_exists($target . '/' . $file)) { exit; } -if ($dir != '' || $file != 'Shared') { +if ($target != '' || strtolower($file) != 'shared') { $targetFile = \OC\Files\Filesystem::normalizePath($target . '/' . $file); $sourceFile = \OC\Files\Filesystem::normalizePath($dir . '/' . $file); if(\OC\Files\Filesystem::rename($sourceFile, $targetFile)) { diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js index f962a7044a..aa85644cef 100644 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -82,7 +82,7 @@ OC.Upload = { */ isProcessing:function() { var count = 0; - + jQuery.each(this._uploads,function(i, data) { if (data.state() === 'pending') { count++; @@ -208,13 +208,13 @@ $(document).ready(function() { add: function(e, data) { OC.Upload.log('add', e, data); var that = $(this); - + // we need to collect all data upload objects before starting the upload so we can check their existence // and set individual conflict actions. unfortunately there is only one variable that we can use to identify // the selection a data upload is part of, so we have to collect them in data.originalFiles // turning singleFileUploads off is not an option because we want to gracefully handle server errors like // already exists - + // create a container where we can store the data objects if ( ! data.originalFiles.selection ) { // initialize selection and remember number of files to upload @@ -225,34 +225,34 @@ $(document).ready(function() { }; } var selection = data.originalFiles.selection; - + // add uploads if ( selection.uploads.length < selection.filesToUpload ) { // remember upload selection.uploads.push(data); } - + //examine file var file = data.files[0]; try { // FIXME: not so elegant... need to refactor that method to return a value - Files.isFileNameValid(file.name); + Files.isFileNameValid(file.name, FileList.getCurrentDirectory()); } catch (errorMessage) { data.textStatus = 'invalidcharacters'; data.errorThrown = errorMessage; } - + if (file.type === '' && file.size === 4096) { data.textStatus = 'dirorzero'; data.errorThrown = t('files', 'Unable to upload {filename} as it is a directory or has 0 bytes', {filename: file.name} ); } - + // add size selection.totalBytes += file.size; - + // check PHP upload limit if (selection.totalBytes > $('#upload_limit').val()) { data.textStatus = 'sizeexceedlimit'; @@ -270,7 +270,7 @@ $(document).ready(function() { 'size2': humanFileSize($('#free_space').val()) }); } - + // end upload for whole selection on error if (data.errorThrown) { // trigger fileupload fail @@ -281,12 +281,12 @@ $(document).ready(function() { // check existing files when all is collected if ( selection.uploads.length >= selection.filesToUpload ) { - + //remove our selection hack: delete data.originalFiles.selection; var callbacks = { - + onNoConflicts: function (selection) { $.each(selection.uploads, function(i, upload) { upload.submit(); @@ -309,7 +309,7 @@ $(document).ready(function() { }; OC.Upload.checkExistingFiles(selection, callbacks); - + } return true; // continue adding files @@ -439,7 +439,7 @@ $(document).ready(function() { }); fileupload.on('fileuploadstop', function(e, data) { OC.Upload.log('progress handle fileuploadstop', e, data); - + $('#uploadprogresswrapper input.stop').fadeOut(); $('#uploadprogressbar').fadeOut(); Files.updateStorageStatistics(); @@ -531,7 +531,7 @@ $(document).ready(function() { if ($(this).children('p').length === 0) { return; } - + $('#new .error').tipsy('hide'); $('#new li').each(function(i,element) { @@ -545,7 +545,7 @@ $(document).ready(function() { var text=$(this).children('p').text(); $(this).data('text',text); $(this).children('p').remove(); - + // add input field var form = $('
'); var input = $(''); @@ -562,7 +562,7 @@ $(document).ready(function() { throw t('files', 'URL cannot be empty'); } else if (type !== 'web' && !Files.isFileNameValid(filename)) { // Files.isFileNameValid(filename) throws an exception itself - } else if ($('#dir').val() === '/' && filename === 'Shared') { + } else if (FileList.getCurrentDirectory() === '/' && filename.toLowerCase() === 'shared') { throw t('files', 'In the home folder \'Shared\' is a reserved filename'); } else if (FileList.inList(filename)) { throw t('files', '{new_name} already exists', {new_name: filename}); diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index d6a4ae9976..503bf68113 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -421,15 +421,12 @@ window.FileList={ len = input.val().length; } input.selectRange(0, len); - var checkInput = function () { var filename = input.val(); if (filename !== oldname) { - if (!Files.isFileNameValid(filename)) { - // Files.isFileNameValid(filename) throws an exception itself - } else if($('#dir').val() === '/' && filename === 'Shared') { - throw t('files','In the home folder \'Shared\' is a reserved filename'); - } else if (FileList.inList(filename)) { + // Files.isFileNameValid(filename) throws an exception itself + Files.isFileNameValid(filename, FileList.getCurrentDirectory()); + if (FileList.inList(filename)) { throw t('files', '{new_name} already exists', {new_name: filename}); } } @@ -1158,9 +1155,9 @@ $(document).ready(function() { // need to initially switch the dir to the one from the hash (IE8) FileList.changeDirectory(parseCurrentDirFromUrl(), false, true); } - } - FileList.setCurrentDir(parseCurrentDirFromUrl(), false); + FileList.setCurrentDir(parseCurrentDirFromUrl(), false); + } FileList.createFileSummary(); }); diff --git a/apps/files/js/files.js b/apps/files/js/files.js index c93862e85d..1186a72a44 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -87,9 +87,12 @@ var Files = { * Throws a string exception with an error message if * the file name is not valid */ - isFileNameValid: function (name) { + isFileNameValid: function (name, root) { var trimmedName = name.trim(); - if (trimmedName === '.' || trimmedName === '..') { + if (trimmedName === '.' + || trimmedName === '..' + || (root === '/' && trimmedName.toLowerCase() === 'shared')) + { throw t('files', '"{name}" is an invalid file name.', {name: name}); } else if (trimmedName.length === 0) { throw t('files', 'File name cannot be empty.'); diff --git a/apps/files/templates/part.list.php b/apps/files/templates/part.list.php index f4fb96a7a7..8a7a1e370e 100644 --- a/apps/files/templates/part.list.php +++ b/apps/files/templates/part.list.php @@ -17,7 +17,13 @@ $totalsize = 0; ?> data-mime="" data-size="" data-etag="" - data-permissions=""> + data-permissions="" + + + data-share-owner="" + + > + @@ -34,17 +40,15 @@ $totalsize = 0; ?> + + + - - - - - diff --git a/apps/files/tests/js/filesSpec.js b/apps/files/tests/js/filesSpec.js index 018c8ef0f3..95bf87e03e 100644 --- a/apps/files/tests/js/filesSpec.js +++ b/apps/files/tests/js/filesSpec.js @@ -48,6 +48,41 @@ describe('Files tests', function() { expect(error).toEqual(false); } }); + it('Validates correct file names do not create Shared folder in root', function() { + // create shared file in subfolder + var error = false; + try { + expect(Files.isFileNameValid('shared', '/foo')).toEqual(true); + expect(Files.isFileNameValid('Shared', '/foo')).toEqual(true); + } + catch (e) { + error = e; + } + expect(error).toEqual(false); + + // create shared file in root + var threwException = false; + try { + Files.isFileNameValid('Shared', '/'); + console.error('Invalid file name not detected'); + } + catch (e) { + threwException = true; + } + expect(threwException).toEqual(true); + + // create shared file in root + var threwException = false; + try { + Files.isFileNameValid('shared', '/'); + console.error('Invalid file name not detected'); + } + catch (e) { + threwException = true; + } + expect(threwException).toEqual(true); + + }); it('Detects invalid file names', function() { var fileNames = [ '', diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 6bf69cd8ee..3db5a42347 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -135,7 +135,6 @@ class Util { // Set directories to check / create $setUpDirs = array( $this->userDir, - $this->userFilesDir, $this->publicKeyDir, $this->encryptionDir, $this->keyfilesPath, diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js index 895f97bd2c..cd2a3103eb 100644 --- a/apps/files_external/js/settings.js +++ b/apps/files_external/js/settings.js @@ -264,7 +264,7 @@ $(document).ready(function() { OC.MountConfig.saveStorage($(this).parent().parent()); }); - $('#sslCertificate').on('click', 'td.remove>img', function() { + $('#sslCertificate').on('click', 'td.remove>img', function() { var $tr = $(this).parent().parent(); var row = this.parentNode.parentNode; $.post(OC.filePath('files_external', 'ajax', 'removeRootCertificate.php'), {cert: row.id}); @@ -302,13 +302,23 @@ $(document).ready(function() { }); $('#allowUserMounting').bind('change', function() { + OC.msg.startSaving('#userMountingMsg'); if (this.checked) { OC.AppConfig.setValue('files_external', 'allow_user_mounting', 'yes'); + $('#userMountingBackups').removeClass('hidden'); } else { OC.AppConfig.setValue('files_external', 'allow_user_mounting', 'no'); + $('#userMountingBackups').addClass('hidden'); } + OC.msg.finishedSaving('#userMountingMsg', {status: 'success', data: {message: t('settings', 'Saved')}}); }); + $('input[name="allowUserMountingBackends\\[\\]"]').bind('change', function() { + OC.msg.startSaving('#userMountingMsg'); + var user_mounting_backends = $('input[name="allowUserMountingBackends\\[\\]"]:checked').map(function(){return $(this).val();}).get(); + OC.AppConfig.setValue('files_external', 'user_mounting_backends', user_mounting_backends.join()); + OC.msg.finishedSaving('#userMountingMsg', {status: 'success', data: {message: t('settings', 'Saved')}}); + }); }); })(); diff --git a/apps/files_external/lib/config.php b/apps/files_external/lib/config.php index 43275d36c0..2767076eef 100755 --- a/apps/files_external/lib/config.php +++ b/apps/files_external/lib/config.php @@ -45,7 +45,7 @@ class OC_Mount_Config { 'datadir' => 'Location')); $backends['\OC\Files\Storage\AmazonS3']=array( - 'backend' => 'Amazon S3', + 'backend' => 'Amazon S3 and compliant', 'configuration' => array( 'key' => 'Access Key', 'secret' => '*Secret Key', @@ -155,6 +155,35 @@ class OC_Mount_Config { return($backends); } + /** + * Get details on each of the external storage backends, used for the mount config UI + * Some backends are not available as a personal backend, f.e. Local and such that have + * been disabled by the admin. + * + * If a custom UI is needed, add the key 'custom' and a javascript file with that name will be loaded + * If the configuration parameter should be secret, add a '*' to the beginning of the value + * If the configuration parameter is a boolean, add a '!' to the beginning of the value + * If the configuration parameter is optional, add a '&' to the beginning of the value + * If the configuration parameter is hidden, add a '#' to the beginning of the value + * @return array + */ + public static function getPersonalBackends() { + + $backends = self::getBackends(); + + // Remove local storage and other disabled storages + unset($backends['\OC\Files\Storage\Local']); + + $allowed_backends = explode(',', OCP\Config::getAppValue('files_external', 'user_mounting_backends', '')); + foreach ($backends as $backend => $null) { + if (!in_array($backend, $allowed_backends)) { + unset($backends[$backend]); + } + } + + return $backends; + } + /** * Get the system mount points * The returned array is not in the same format as getUserMountPoints() @@ -287,11 +316,12 @@ class OC_Mount_Config { if (!isset($backends[$class])) { // invalid backend return false; - } + } if ($isPersonal) { // Verify that the mount point applies for the current user - // Prevent non-admin users from mounting local storage - if ($applicable !== OCP\User::getUser() || strtolower($class) === '\oc\files\storage\local') { + // Prevent non-admin users from mounting local storage and other disabled backends + $allowed_backends = self::getPersonalBackends(); + if ($applicable != OCP\User::getUser() || !in_array($class, $allowed_backends)) { return false; } $mountPoint = '/'.$applicable.'/files/'.ltrim($mountPoint, '/'); @@ -446,7 +476,7 @@ class OC_Mount_Config { */ public static function checksmbclient() { if(function_exists('shell_exec')) { - $output=shell_exec('which smbclient 2> /dev/null'); + $output=shell_exec('command -v smbclient 2> /dev/null'); return !empty($output); }else{ return false; diff --git a/apps/files_external/personal.php b/apps/files_external/personal.php index 90f5e15953..90d7afed28 100755 --- a/apps/files_external/personal.php +++ b/apps/files_external/personal.php @@ -22,9 +22,8 @@ OCP\Util::addScript('files_external', 'settings'); OCP\Util::addStyle('files_external', 'settings'); -$backends = OC_Mount_Config::getBackends(); -// Remove local storage -unset($backends['\OC\Files\Storage\Local']); +$backends = OC_Mount_Config::getPersonalBackends(); + $tmpl = new OCP\Template('files_external', 'settings'); $tmpl->assign('isAdminPage', false); $tmpl->assign('mounts', OC_Mount_Config::getPersonalMountPoints()); diff --git a/apps/files_external/settings.php b/apps/files_external/settings.php index 31183409e3..5b62b54220 100644 --- a/apps/files_external/settings.php +++ b/apps/files_external/settings.php @@ -26,10 +26,26 @@ OCP\Util::addScript('files_external', 'settings'); OCP\Util::addscript('3rdparty', 'chosen/chosen.jquery.min'); OCP\Util::addStyle('files_external', 'settings'); OCP\Util::addStyle('3rdparty', 'chosen/chosen'); + +$backends = OC_Mount_Config::getBackends(); +$personal_backends = array(); +$enabled_backends = explode(',', OCP\Config::getAppValue('files_external', 'user_mounting_backends', '')); +foreach ($backends as $class => $backend) +{ + if ($class != '\OC\Files\Storage\Local') + { + $personal_backends[$class] = array( + 'backend' => $backend['backend'], + 'enabled' => in_array($class, $enabled_backends), + ); + } +} + $tmpl = new OCP\Template('files_external', 'settings'); $tmpl->assign('isAdminPage', true); $tmpl->assign('mounts', OC_Mount_Config::getSystemMountPoints()); -$tmpl->assign('backends', OC_Mount_Config::getBackends()); +$tmpl->assign('backends', $backends); +$tmpl->assign('personal_backends', $personal_backends); $tmpl->assign('groups', OC_Group::getGroups()); $tmpl->assign('users', OCP\User::getUsers()); $tmpl->assign('userDisplayNames', OC_User::getDisplayNames()); diff --git a/apps/files_external/templates/settings.php b/apps/files_external/templates/settings.php index 3ca16c3c7a..de44d3c864 100644 --- a/apps/files_external/templates/settings.php +++ b/apps/files_external/templates/settings.php @@ -122,12 +122,18 @@
- /> -
- t('Allow users to mount their own external storage')); ?> + /> + + +

class="hidden"> + t('Allow users to mount the following external storage')); ?>
+ $backend): ?> + /> +
+ + +

diff --git a/apps/files_sharing/js/share.js b/apps/files_sharing/js/share.js index 36de452a55..9f0ed12f93 100644 --- a/apps/files_sharing/js/share.js +++ b/apps/files_sharing/js/share.js @@ -5,6 +5,14 @@ $(document).ready(function() { if (typeof OC.Share !== 'undefined' && typeof FileActions !== 'undefined' && !disableSharing) { $('#fileList').on('fileActionsReady',function(){ + + var allShared = $('#fileList').find('[data-share-owner]').find('[data-Action="Share"]'); + allShared.addClass('permanent'); + allShared.find('span').text(function(){ + $owner = $(this).closest('tr').attr('data-share-owner'); + return ' ' + t('files_sharing', 'Shared by {owner}', {owner: $owner}); + }); + if (!sharesLoaded){ OC.Share.loadIcons('file'); // assume that we got all shares, so switching directories @@ -17,16 +25,15 @@ $(document).ready(function() { }); FileActions.register('all', 'Share', OC.PERMISSION_READ, OC.imagePath('core', 'actions/share'), function(filename) { - if ($('#dir').val() == '/') { - var item = $('#dir').val() + filename; - } else { - var item = $('#dir').val() + '/' + filename; + var dir = $('#dir').val(); + var item = dir + '/' + filename; + if (dir == '/') { + item = dir + filename; } var tr = FileList.findFileEl(filename); + var itemType = 'file'; if ($(tr).data('type') == 'dir') { - var itemType = 'folder'; - } else { - var itemType = 'file'; + itemType = 'folder'; } var possiblePermissions = $(tr).data('permissions'); var appendTo = $(tr).find('td.filename'); diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php index 4b0da0b002..10f2182655 100644 --- a/apps/files_sharing/lib/cache.php +++ b/apps/files_sharing/lib/cache.php @@ -137,9 +137,12 @@ class Shared_Cache extends Cache { } else { $cache = $this->getSourceCache($folder); if ($cache) { + $parent = $this->storage->getFile($folder); $sourceFolderContent = $cache->getFolderContents($this->files[$folder]); foreach ($sourceFolderContent as $key => $c) { $sourceFolderContent[$key]['usersPath'] = 'files/Shared/' . $folder . '/' . $c['name']; + $sourceFolderContent[$key]['uid_owner'] = $parent['uid_owner']; + $sourceFolderContent[$key]['displayname_owner'] = $parent['uid_owner']; } return $sourceFolderContent; diff --git a/apps/files_sharing/lib/share/file.php b/apps/files_sharing/lib/share/file.php index ec0f368386..5e00050fe1 100644 --- a/apps/files_sharing/lib/share/file.php +++ b/apps/files_sharing/lib/share/file.php @@ -94,6 +94,9 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent { $file['mtime'] = $item['mtime']; $file['encrypted'] = $item['encrypted']; $file['etag'] = $item['etag']; + $file['uid_owner'] = $item['uid_owner']; + $file['displayname_owner'] = $item['displayname_owner']; + $storage = \OC\Files\Filesystem::getStorage('/'); $cache = $storage->getCache(); if ($item['encrypted'] or ($item['unencrypted_size'] > 0 and $cache->getMimetype($item['mimetype']) === 'httpd/unix-directory')) { diff --git a/apps/user_ldap/lib/helper.php b/apps/user_ldap/lib/helper.php index 7de7fe8667..b5955cb2ab 100644 --- a/apps/user_ldap/lib/helper.php +++ b/apps/user_ldap/lib/helper.php @@ -120,7 +120,7 @@ class Helper { $saveOtherConfigurations = ''; if(empty($prefix)) { - $saveOtherConfigurations = 'AND `Configkey` NOT LIKE \'s%\''; + $saveOtherConfigurations = 'AND `configkey` NOT LIKE \'s%\''; } $query = \OCP\DB::prepare(' diff --git a/apps/user_ldap/user_proxy.php b/apps/user_ldap/user_proxy.php index 5ad127197f..2cb3dfb2c6 100644 --- a/apps/user_ldap/user_proxy.php +++ b/apps/user_ldap/user_proxy.php @@ -54,11 +54,15 @@ class User_Proxy extends lib\Proxy implements \OCP\UserInterface { protected function walkBackends($uid, $method, $parameters) { $cacheKey = $this->getUserCacheKey($uid); foreach($this->backends as $configPrefix => $backend) { -// print("walkBackend '$configPrefix'
"); - if($result = call_user_func_array(array($backend, $method), $parameters)) { + $instance = $backend; + if(!method_exists($instance, $method) + && method_exists($this->getAccess($configPrefix), $method)) { + $instance = $this->getAccess($configPrefix); + } + if($result = call_user_func_array(array($instance, $method), $parameters)) { $this->writeToCache($cacheKey, $configPrefix); return $result; - } + } } return false; } @@ -77,7 +81,12 @@ class User_Proxy extends lib\Proxy implements \OCP\UserInterface { //in case the uid has been found in the past, try this stored connection first if(!is_null($prefix)) { if(isset($this->backends[$prefix])) { - $result = call_user_func_array(array($this->backends[$prefix], $method), $parameters); + $instance = $this->backends[$prefix]; + if(!method_exists($instance, $method) + && method_exists($this->getAccess($prefix), $method)) { + $instance = $this->getAccess($prefix); + } + $result = call_user_func_array(array($instance, $method), $parameters); if($result === $passOnWhen) { //not found here, reset cache to null if user vanished //because sometimes methods return false with a reason diff --git a/config/config.sample.php b/config/config.sample.php index 9c5eca8a5e..987a866e49 100755 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -178,6 +178,9 @@ $CONFIG = array( /* Enable or disable the logging of IP addresses in case of webform auth failures */ "log_authfailip" => false, +/* Whether http-basic username must equal username to login */ +"basic_auth" => true, + /* * Configure the size in bytes log rotation should happen, 0 or false disables the rotation. * This rotates the current owncloud logfile to a new name, this way the total log usage diff --git a/core/css/icons.css b/core/css/icons.css index 027a3f8557..b41c733861 100644 --- a/core/css/icons.css +++ b/core/css/icons.css @@ -156,11 +156,15 @@ background-image: url('../img/actions/sound-off.svg'); } -.icon-star { +.icon-star, +.icon-starred:hover, +.icon-starred:focus { background-image: url('../img/actions/star.svg'); } -.icon-starred { +.icon-starred, +.icon-star:hover, +.icon-star:focus { background-image: url('../img/actions/starred.svg'); } diff --git a/core/css/styles.css b/core/css/styles.css index 082d2c714c..69cf6df07d 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -175,6 +175,7 @@ button, .button, border: 1px solid rgba(190,190,190,.9); cursor: pointer; border-radius: 3px; + outline: none; } input[type="submit"]:hover, input[type="submit"]:focus, input[type="button"]:hover, input[type="button"]:focus, @@ -204,18 +205,18 @@ textarea:disabled { /* Primary action button, use sparingly */ .primary, input[type="submit"].primary, input[type="button"].primary, button.primary, .button.primary { border: 1px solid #1d2d44; - background: #35537a; + background-color: #35537a; color: #ddd; } .primary:hover, input[type="submit"].primary:hover, input[type="button"].primary:hover, button.primary:hover, .button.primary:hover, .primary:focus, input[type="submit"].primary:focus, input[type="button"].primary:focus, button.primary:focus, .button.primary:focus { border: 1px solid #1d2d44; - background: #304d76; + background-color: #304d76; color: #fff; } .primary:active, input[type="submit"].primary:active, input[type="button"].primary:active, button.primary:active, .button.primary:active { border: 1px solid #1d2d44; - background: #1d2d44; + background-color: #1d2d44; color: #bbb; } @@ -233,7 +234,7 @@ textarea:disabled { } input[type="submit"].enabled { - background: #66f866; + background-color: #66f866; border: 1px solid #5e5; } diff --git a/core/img/logo-mail.gif b/core/img/logo-mail.gif index 6a1caaa918..f1dd108450 100644 Binary files a/core/img/logo-mail.gif and b/core/img/logo-mail.gif differ diff --git a/core/js/setup.js b/core/js/setup.js index 279b5fbebb..96719540f9 100644 --- a/core/js/setup.js +++ b/core/js/setup.js @@ -36,6 +36,7 @@ $(document).ready(function() { $('#showAdvanced').click(function() { $('#datadirContent').slideToggle(250); + $('#databaseBackend').slideToggle(250); $('#databaseField').slideToggle(250); }); $("form").submit(function(){ @@ -73,6 +74,7 @@ $(document).ready(function() { if (currentDbType === 'sqlite' || (dbtypes.sqlite && currentDbType === undefined)){ $('#datadirContent').hide(250); + $('#databaseBackend').hide(250); $('#databaseField').hide(250); } diff --git a/core/js/share.js b/core/js/share.js index 0939259b7d..129e50b22d 100644 --- a/core/js/share.js +++ b/core/js/share.js @@ -584,8 +584,8 @@ $(document).ready(function() { $(checkboxes).filter('input[name="edit"]').attr('checked', false); // Check Edit if Create, Update, or Delete is checked } else if (($(this).attr('name') == 'create' - || $(this).attr('name') == 'update' - || $(this).attr('name') == 'delete')) + || $(this).attr('name') == 'update' + || $(this).attr('name') == 'delete')) { $(checkboxes).filter('input[name="edit"]').attr('checked', true); } diff --git a/core/templates/installation.php b/core/templates/installation.php index d9f3c38ab1..e2d296a713 100644 --- a/core/templates/installation.php +++ b/core/templates/installation.php @@ -84,7 +84,7 @@ 0): ?> -
+
t( 'Configure the database' )); ?> @@ -100,8 +100,10 @@ +
+

@@ -141,8 +143,8 @@ autocomplete="off" autocapitalize="off" autocorrect="off" />

+
-
diff --git a/core/templates/mail.php b/core/templates/mail.php index b8b0a2bfe9..ae46eaca78 100644 --- a/core/templates/mail.php +++ b/core/templates/mail.php @@ -2,15 +2,15 @@ - - + - + - - + - + - - + - +
  -<?php p($theme->getName()); ?> +  +<?php p($theme->getName()); ?>
 
 
  +  t('Hey there,

just letting you know that %s shared %s with you.
View it!

', array($_['user_displayname'], $_['filename'], $_['link']))); if ( isset($_['expiration']) ) { @@ -21,17 +21,17 @@ p($l->t('Cheers!')); ?>
 
 
 --
+
 --
getName()); ?> - getSlogan()); ?> -
getBaseUrl());?> +
getBaseUrl());?>
  
diff --git a/lib/base.php b/lib/base.php index 7703e83ec2..a44db8fd4d 100644 --- a/lib/base.php +++ b/lib/base.php @@ -553,7 +553,8 @@ class OC { OC_User::useBackend(new OC_User_Database()); OC_Group::useBackend(new OC_Group_Database()); - if (isset($_SERVER['PHP_AUTH_USER']) && self::$session->exists('loginname') + $basic_auth = OC_Config::getValue('basic_auth', true); + if ($basic_auth && isset($_SERVER['PHP_AUTH_USER']) && self::$session->exists('loginname') && $_SERVER['PHP_AUTH_USER'] !== self::$session->get('loginname')) { $sessionUser = self::$session->get('loginname'); $serverUser = $_SERVER['PHP_AUTH_USER']; diff --git a/lib/private/app.php b/lib/private/app.php index 048d4d4aeb..58bf67c1d4 100644 --- a/lib/private/app.php +++ b/lib/private/app.php @@ -219,6 +219,8 @@ class OC_App{ $appdata=OC_OCSClient::getApplication($app); $download=OC_OCSClient::getApplicationDownload($app, 1); if(isset($download['downloadlink']) and $download['downloadlink']!='') { + // Replace spaces in download link without encoding entire URL + $download['downloadlink'] = str_replace(' ', '%20', $download['downloadlink']); $info = array('source'=>'http', 'href'=>$download['downloadlink'], 'appdata'=>$appdata); $app=OC_Installer::installApp($info); } diff --git a/lib/private/config.php b/lib/private/config.php index 3649da8497..56f4725613 100644 --- a/lib/private/config.php +++ b/lib/private/config.php @@ -77,7 +77,7 @@ class Config { /** * @brief Gets a value from config.php * @param string $key key - * @param string|null $default = null default value + * @param array|bool|string|null $default = null default value * @return string the value or $default * * This function gets the value from config.php. If it does not exist, diff --git a/lib/private/connector/sabre/directory.php b/lib/private/connector/sabre/directory.php index 02d1a9f4ba..3ed9e94d69 100644 --- a/lib/private/connector/sabre/directory.php +++ b/lib/private/connector/sabre/directory.php @@ -50,7 +50,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa */ public function createFile($name, $data = null) { - if ($name === 'Shared' && empty($this->path)) { + if (strtolower($name) === 'shared' && empty($this->path)) { throw new \Sabre_DAV_Exception_Forbidden(); } @@ -86,7 +86,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa */ public function createDirectory($name) { - if ($name === 'Shared' && empty($this->path)) { + if (strtolower($name) === 'shared' && empty($this->path)) { throw new \Sabre_DAV_Exception_Forbidden(); } diff --git a/lib/private/connector/sabre/objecttree.php b/lib/private/connector/sabre/objecttree.php index d2fa425b22..accf020daa 100644 --- a/lib/private/connector/sabre/objecttree.php +++ b/lib/private/connector/sabre/objecttree.php @@ -94,6 +94,9 @@ class ObjectTree extends \Sabre_DAV_ObjectTree { } if ($sourceDir !== $destinationDir) { // for a full move we need update privileges on sourcePath and sourceDir as well as destinationDir + if (ltrim($destinationDir, '/') === '' && strtolower($sourceNode->getName()) === 'shared') { + throw new \Sabre_DAV_Exception_Forbidden(); + } if (!$fs->isUpdatable($sourceDir)) { throw new \Sabre_DAV_Exception_Forbidden(); } diff --git a/lib/private/db/mdb2schemareader.php b/lib/private/db/mdb2schemareader.php index f9a76786c3..1c16d03eab 100644 --- a/lib/private/db/mdb2schemareader.php +++ b/lib/private/db/mdb2schemareader.php @@ -41,7 +41,9 @@ class MDB2SchemaReader { */ public function loadSchemaFromFile($file) { $schema = new \Doctrine\DBAL\Schema\Schema(); + $loadEntities = libxml_disable_entity_loader(false); $xml = simplexml_load_file($file); + libxml_disable_entity_loader($loadEntities); foreach ($xml->children() as $child) { /** * @var \SimpleXMLElement $child diff --git a/lib/private/defaults.php b/lib/private/defaults.php index 59630cda5c..79be211b82 100644 --- a/lib/private/defaults.php +++ b/lib/private/defaults.php @@ -21,6 +21,7 @@ class OC_Defaults { private $defaultDocBaseUrl; private $defaultSlogan; private $defaultLogoClaim; + private $defaultMailHeaderColor; function __construct() { $this->l = OC_L10N::get('core'); @@ -33,6 +34,7 @@ class OC_Defaults { $this->defaultDocBaseUrl = "http://doc.owncloud.org"; $this->defaultSlogan = $this->l->t("web services under your control"); $this->defaultLogoClaim = ""; + $this->defaultMailHeaderColor = "#1d2d44"; /* header color of mail notifications */ if (class_exists("OC_Theme")) { $this->theme = new OC_Theme(); @@ -181,4 +183,16 @@ class OC_Defaults { return $this->getDocBaseUrl() . '/server/6.0/go.php?to=' . $key; } + /** + * Returns mail header color + * @return mail header color + */ + public function getMailHeaderColor() { + if ($this->themeExist('getMailHeaderColor')) { + return $this->theme->getMailHeaderColor(); + } else { + return $this->defaultMailHeaderColor; + } + } + } diff --git a/lib/private/installer.php b/lib/private/installer.php index 11633a4d4a..64e8e3a5e7 100644 --- a/lib/private/installer.php +++ b/lib/private/installer.php @@ -464,7 +464,7 @@ class OC_Installer{ // is the code checker enabled? if(OC_Config::getValue('appcodechecker', true)) { // check if grep is installed - $grep = exec('which grep'); + $grep = exec('command -v grep'); if($grep=='') { OC_Log::write('core', 'grep not installed. So checking the code of the app "'.$appname.'" was not possible', diff --git a/lib/private/l10n.php b/lib/private/l10n.php index ad979a9287..197b2d6791 100644 --- a/lib/private/l10n.php +++ b/lib/private/l10n.php @@ -73,8 +73,8 @@ class OC_L10N implements \OCP\IL10N { /** * get an L10N instance - * @param $app string - * @param $lang string|null + * @param string $app + * @param string|null $lang * @return OC_L10N */ public static function get($app, $lang=null) { @@ -87,8 +87,8 @@ class OC_L10N implements \OCP\IL10N { /** * @brief The constructor - * @param $app string app requesting l10n - * @param $lang string default: null Language + * @param string $app app requesting l10n + * @param string $lang default: null Language * @returns OC_L10N-Object * * If language is not set, the constructor tries to find the right @@ -237,7 +237,7 @@ class OC_L10N implements \OCP\IL10N { /** * @brief Translating - * @param $text String The text we need a translation for + * @param string $text The text we need a translation for * @param array $parameters default:array() Parameters for sprintf * @return \OC_L10N_String Translation or the same text * @@ -250,9 +250,9 @@ class OC_L10N implements \OCP\IL10N { /** * @brief Translating - * @param $text_singular String the string to translate for exactly one object - * @param $text_plural String the string to translate for n objects - * @param $count Integer Number of objects + * @param string $text_singular the string to translate for exactly one object + * @param string $text_plural the string to translate for n objects + * @param integer $count Number of objects * @param array $parameters default:array() Parameters for sprintf * @return \OC_L10N_String Translation or the same text * @@ -351,7 +351,7 @@ class OC_L10N implements \OCP\IL10N { /** * @brief Localization - * @param $type Type of localization + * @param string $type Type of localization * @param $params parameters for this localization * @returns String or false * @@ -406,7 +406,7 @@ class OC_L10N implements \OCP\IL10N { /** * @brief Choose a language - * @param $texts Associative Array with possible strings + * @param array $text Associative Array with possible strings * @returns String * * $text is an array 'de' => 'hallo welt', 'en' => 'hello world', ... @@ -421,7 +421,7 @@ class OC_L10N implements \OCP\IL10N { /** * @brief find the best language - * @param $app Array or string, details below + * @param array|string $app details below * @returns string language * * If $app is an array, ownCloud assumes that these are the available @@ -494,7 +494,7 @@ class OC_L10N implements \OCP\IL10N { /** * @brief find the l10n directory - * @param $app App that needs to be translated + * @param string $app App that needs to be translated * @returns directory */ protected static function findI18nDir($app) { @@ -514,7 +514,7 @@ class OC_L10N implements \OCP\IL10N { /** * @brief find all available languages for an app - * @param $app App that needs to be translated + * @param string $app App that needs to be translated * @returns array an array of available languages */ public static function findAvailableLanguages($app=null) { @@ -533,7 +533,9 @@ class OC_L10N implements \OCP\IL10N { } /** + * @param string $app * @param string $lang + * @returns bool */ public static function languageExists($app, $lang) { if ($lang == 'en') {//english is always available diff --git a/lib/private/ocs/cloud.php b/lib/private/ocs/cloud.php index cbbf3b626f..06d6a8eb4b 100644 --- a/lib/private/ocs/cloud.php +++ b/lib/private/ocs/cloud.php @@ -61,17 +61,29 @@ class OC_OCS_Cloud { * the user from whom the information will be returned */ public static function getUser($parameters) { + $return = array(); // Check if they are viewing information on themselves if($parameters['userid'] === OC_User::getUser()) { // Self lookup $storage = OC_Helper::getStorageInfo('/'); - $quota = array( + $return['quota'] = array( 'free' => $storage['free'], 'used' => $storage['used'], 'total' => $storage['total'], 'relative' => $storage['relative'], ); - return new OC_OCS_Result(array('quota' => $quota)); + } + if(OC_User::isAdminUser(OC_User::getUser()) + || OC_Subadmin::isUserAccessible(OC_User::getUser(), $parameters['userid'])) { + if(OC_User::userExists($parameters['userid'])) { + // Is an admin/subadmin so can see display name + $return['displayname'] = OC_User::getDisplayName($parameters['userid']); + } else { + return new OC_OCS_Result(null, 101); + } + } + if(count($return)) { + return new OC_OCS_Result($return); } else { // No permission to view this user data return new OC_OCS_Result(null, 997); diff --git a/lib/private/preview.php b/lib/private/preview.php index 80fd003ed8..74051fbc2a 100755 --- a/lib/private/preview.php +++ b/lib/private/preview.php @@ -52,6 +52,11 @@ class Preview { static private $providers = array(); static private $registeredProviders = array(); + /** + * @var \OCP\Files\FileInfo + */ + protected $info; + /** * @brief check if thumbnail or bigger version of thumbnail of file is cached * @param string $user userid - if no user is given, OC_User::getUser will be used @@ -61,12 +66,12 @@ class Preview { * @param int $maxY The maximum Y size of the thumbnail. It can be smaller depending on the shape of the image * @param bool $scalingUp Disable/Enable upscaling of previews * @return mixed (bool / string) - * false if thumbnail does not exist - * path to thumbnail if thumbnail exists - */ - public function __construct($user='', $root='/', $file='', $maxX=1, $maxY=1, $scalingUp=true) { + * false if thumbnail does not exist + * path to thumbnail if thumbnail exists + */ + public function __construct($user = '', $root = '/', $file = '', $maxX = 1, $maxY = 1, $scalingUp = true) { //init fileviews - if($user === ''){ + if ($user === '') { $user = \OC_User::getUser(); } $this->fileView = new \OC\Files\View('/' . $user . '/' . $root); @@ -86,11 +91,11 @@ class Preview { $this->preview = null; //check if there are preview backends - if(empty(self::$providers)) { + if (empty(self::$providers)) { self::initProviders(); } - if(empty(self::$providers)) { + if (empty(self::$providers)) { \OC_Log::write('core', 'No preview providers exist', \OC_Log::ERROR); throw new \Exception('No preview providers'); } @@ -99,15 +104,15 @@ class Preview { /** * @brief returns the path of the file you want a thumbnail from * @return string - */ - public function getFile() { + */ + public function getFile() { return $this->file; } /** * @brief returns the max width of the preview * @return integer - */ + */ public function getMaxX() { return $this->maxX; } @@ -115,7 +120,7 @@ class Preview { /** * @brief returns the max height of the preview * @return integer - */ + */ public function getMaxY() { return $this->maxY; } @@ -123,7 +128,7 @@ class Preview { /** * @brief returns whether or not scalingup is enabled * @return bool - */ + */ public function getScalingUp() { return $this->scalingup; } @@ -131,7 +136,7 @@ class Preview { /** * @brief returns the name of the thumbnailfolder * @return string - */ + */ public function getThumbnailsFolder() { return self::THUMBNAILS_FOLDER; } @@ -139,7 +144,7 @@ class Preview { /** * @brief returns the max scale factor * @return string - */ + */ public function getMaxScaleFactor() { return $this->maxScaleFactor; } @@ -147,7 +152,7 @@ class Preview { /** * @brief returns the max width set in ownCloud's config * @return string - */ + */ public function getConfigMaxX() { return $this->configMaxX; } @@ -155,20 +160,28 @@ class Preview { /** * @brief returns the max height set in ownCloud's config * @return string - */ + */ public function getConfigMaxY() { return $this->configMaxY; } + protected function getFileInfo() { + if (!$this->info) { + $this->info = $this->fileView->getFileInfo($this->file); + } + return $this->info; + } + /** * @brief set the path of the file you want a thumbnail from * @param string $file * @return $this - */ + */ public function setFile($file) { $this->file = $file; + $this->info = null; if ($file !== '') { - $this->mimetype = $this->fileView->getMimeType($this->file); + $this->mimetype = $this->getFileInfo()->getMimetype(); } return $this; } @@ -185,14 +198,14 @@ class Preview { * @brief set the the max width of the preview * @param int $maxX * @return $this - */ - public function setMaxX($maxX=1) { - if($maxX <= 0) { + */ + public function setMaxX($maxX = 1) { + if ($maxX <= 0) { throw new \Exception('Cannot set width of 0 or smaller!'); } $configMaxX = $this->getConfigMaxX(); - if(!is_null($configMaxX)) { - if($maxX > $configMaxX) { + if (!is_null($configMaxX)) { + if ($maxX > $configMaxX) { \OC_Log::write('core', 'maxX reduced from ' . $maxX . ' to ' . $configMaxX, \OC_Log::DEBUG); $maxX = $configMaxX; } @@ -205,14 +218,14 @@ class Preview { * @brief set the the max height of the preview * @param int $maxY * @return $this - */ - public function setMaxY($maxY=1) { - if($maxY <= 0) { + */ + public function setMaxY($maxY = 1) { + if ($maxY <= 0) { throw new \Exception('Cannot set height of 0 or smaller!'); } $configMaxY = $this->getConfigMaxY(); - if(!is_null($configMaxY)) { - if($maxY > $configMaxY) { + if (!is_null($configMaxY)) { + if ($maxY > $configMaxY) { \OC_Log::write('core', 'maxX reduced from ' . $maxY . ' to ' . $configMaxY, \OC_Log::DEBUG); $maxY = $configMaxY; } @@ -225,9 +238,9 @@ class Preview { * @brief set whether or not scalingup is enabled * @param bool $scalingUp * @return $this - */ + */ public function setScalingup($scalingUp) { - if($this->getMaxScaleFactor() === 1) { + if ($this->getMaxScaleFactor() === 1) { $scalingUp = false; } $this->scalingup = $scalingUp; @@ -237,15 +250,15 @@ class Preview { /** * @brief check if all parameters are valid * @return bool - */ + */ public function isFileValid() { $file = $this->getFile(); - if($file === '') { + if ($file === '') { \OC_Log::write('core', 'No filename passed', \OC_Log::DEBUG); return false; } - if(!$this->fileView->file_exists($file)) { + if (!$this->fileView->file_exists($file)) { \OC_Log::write('core', 'File:"' . $file . '" not found', \OC_Log::DEBUG); return false; } @@ -256,40 +269,38 @@ class Preview { /** * @brief deletes previews of a file with specific x and y * @return bool - */ + */ public function deletePreview() { $file = $this->getFile(); - $fileInfo = $this->fileView->getFileInfo($file); - $fileId = $fileInfo['fileid']; + $fileInfo = $this->getFileInfo($file); + $fileId = $fileInfo->getId(); $previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/' . $this->getMaxX() . '-' . $this->getMaxY() . '.png'; - $this->userView->unlink($previewPath); - return !$this->userView->file_exists($previewPath); + return $this->userView->unlink($previewPath); } /** * @brief deletes all previews of a file * @return bool - */ + */ public function deleteAllPreviews() { $file = $this->getFile(); - $fileInfo = $this->fileView->getFileInfo($file); - $fileId = $fileInfo['fileid']; + $fileInfo = $this->getFileInfo($file); + $fileId = $fileInfo->getId(); $previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/'; $this->userView->deleteAll($previewPath); - $this->userView->rmdir($previewPath); - return !$this->userView->is_dir($previewPath); + return $this->userView->rmdir($previewPath); } /** * @brief check if thumbnail or bigger version of thumbnail of file is cached * @return mixed (bool / string) - * false if thumbnail does not exist - * path to thumbnail if thumbnail exists - */ + * false if thumbnail does not exist + * path to thumbnail if thumbnail exists + */ private function isCached() { $file = $this->getFile(); $maxX = $this->getMaxX(); @@ -297,75 +308,75 @@ class Preview { $scalingUp = $this->getScalingUp(); $maxScaleFactor = $this->getMaxScaleFactor(); - $fileInfo = $this->fileView->getFileInfo($file); - $fileId = $fileInfo['fileid']; + $fileInfo = $this->getFileInfo($file); + $fileId = $fileInfo->getId(); - if(is_null($fileId)) { + if (is_null($fileId)) { return false; } $previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/'; - if(!$this->userView->is_dir($previewPath)) { + if (!$this->userView->is_dir($previewPath)) { return false; } //does a preview with the wanted height and width already exist? - if($this->userView->file_exists($previewPath . $maxX . '-' . $maxY . '.png')) { + if ($this->userView->file_exists($previewPath . $maxX . '-' . $maxY . '.png')) { return $previewPath . $maxX . '-' . $maxY . '.png'; } - $wantedAspectRatio = (float) ($maxX / $maxY); + $wantedAspectRatio = (float)($maxX / $maxY); //array for usable cached thumbnails $possibleThumbnails = array(); $allThumbnails = $this->userView->getDirectoryContent($previewPath); - foreach($allThumbnails as $thumbnail) { + foreach ($allThumbnails as $thumbnail) { $name = rtrim($thumbnail['name'], '.png'); $size = explode('-', $name); - $x = (int) $size[0]; - $y = (int) $size[1]; + $x = (int)$size[0]; + $y = (int)$size[1]; - $aspectRatio = (float) ($x / $y); - if($aspectRatio !== $wantedAspectRatio) { + $aspectRatio = (float)($x / $y); + if ($aspectRatio !== $wantedAspectRatio) { continue; } - if($x < $maxX || $y < $maxY) { - if($scalingUp) { + if ($x < $maxX || $y < $maxY) { + if ($scalingUp) { $scalefactor = $maxX / $x; - if($scalefactor > $maxScaleFactor) { + if ($scalefactor > $maxScaleFactor) { continue; } - }else{ + } else { continue; } } $possibleThumbnails[$x] = $thumbnail['path']; } - if(count($possibleThumbnails) === 0) { + if (count($possibleThumbnails) === 0) { return false; } - if(count($possibleThumbnails) === 1) { + if (count($possibleThumbnails) === 1) { return current($possibleThumbnails); } ksort($possibleThumbnails); - if(key(reset($possibleThumbnails)) > $maxX) { + if (key(reset($possibleThumbnails)) > $maxX) { return current(reset($possibleThumbnails)); } - if(key(end($possibleThumbnails)) < $maxX) { + if (key(end($possibleThumbnails)) < $maxX) { return current(end($possibleThumbnails)); } - foreach($possibleThumbnails as $width => $path) { - if($width < $maxX) { + foreach ($possibleThumbnails as $width => $path) { + if ($width < $maxX) { continue; - }else{ + } else { return $path; } } @@ -374,9 +385,9 @@ class Preview { /** * @brief return a preview of a file * @return \OC_Image - */ + */ public function getPreview() { - if(!is_null($this->preview) && $this->preview->valid()){ + if (!is_null($this->preview) && $this->preview->valid()) { return $this->preview; } @@ -386,22 +397,25 @@ class Preview { $maxY = $this->getMaxY(); $scalingUp = $this->getScalingUp(); - $fileInfo = $this->fileView->getFileInfo($file); - $fileId = $fileInfo['fileid']; + $fileInfo = $this->getFileInfo($file); + $fileId = $fileInfo->getId(); $cached = $this->isCached(); - if($cached) { - $image = new \OC_Image($this->userView->file_get_contents($cached, 'r')); + if ($cached) { + $stream = $this->userView->fopen($cached, 'r'); + $image = new \OC_Image(); + $image->loadFromFileHandle($stream); $this->preview = $image->valid() ? $image : null; $this->resizeAndCrop(); + fclose($stream); } - if(is_null($this->preview)) { + if (is_null($this->preview)) { $preview = null; - foreach(self::$providers as $supportedMimetype => $provider) { - if(!preg_match($supportedMimetype, $this->mimetype)) { + foreach (self::$providers as $supportedMimetype => $provider) { + if (!preg_match($supportedMimetype, $this->mimetype)) { continue; } @@ -409,7 +423,7 @@ class Preview { $preview = $provider->getThumbnail($file, $maxX, $maxY, $scalingUp, $this->fileView); - if(!($preview instanceof \OC_Image)) { + if (!($preview instanceof \OC_Image)) { continue; } @@ -419,11 +433,11 @@ class Preview { $previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/'; $cachePath = $previewPath . $maxX . '-' . $maxY . '.png'; - if($this->userView->is_dir($this->getThumbnailsFolder() . '/') === false) { + if ($this->userView->is_dir($this->getThumbnailsFolder() . '/') === false) { $this->userView->mkdir($this->getThumbnailsFolder() . '/'); } - if($this->userView->is_dir($previewPath) === false) { + if ($this->userView->is_dir($previewPath) === false) { $this->userView->mkdir($previewPath); } @@ -433,7 +447,7 @@ class Preview { } } - if(is_null($this->preview)) { + if (is_null($this->preview)) { $this->preview = new \OC_Image(); } @@ -443,10 +457,10 @@ class Preview { /** * @brief show preview * @return void - */ + */ public function showPreview() { \OCP\Response::enableCaching(3600 * 24); // 24 hours - if(is_null($this->preview)) { + if (is_null($this->preview)) { $this->getPreview(); } $this->preview->show(); @@ -456,7 +470,7 @@ class Preview { /** * @brief show preview * @return void - */ + */ public function show() { $this->showPreview(); return; @@ -465,7 +479,7 @@ class Preview { /** * @brief resize, crop and fix orientation * @return void - */ + */ private function resizeAndCrop() { $image = $this->preview; $x = $this->getMaxX(); @@ -473,17 +487,17 @@ class Preview { $scalingUp = $this->getScalingUp(); $maxscalefactor = $this->getMaxScaleFactor(); - if(!($image instanceof \OC_Image)) { + if (!($image instanceof \OC_Image)) { \OC_Log::write('core', '$this->preview is not an instance of OC_Image', \OC_Log::DEBUG); return; } $image->fixOrientation(); - $realx = (int) $image->width(); - $realy = (int) $image->height(); + $realx = (int)$image->width(); + $realy = (int)$image->height(); - if($x === $realx && $y === $realy) { + if ($x === $realx && $y === $realy) { $this->preview = $image; return; } @@ -491,36 +505,36 @@ class Preview { $factorX = $x / $realx; $factorY = $y / $realy; - if($factorX >= $factorY) { + if ($factorX >= $factorY) { $factor = $factorX; - }else{ + } else { $factor = $factorY; } - if($scalingUp === false) { - if($factor > 1) { + if ($scalingUp === false) { + if ($factor > 1) { $factor = 1; } } - if(!is_null($maxscalefactor)) { - if($factor > $maxscalefactor) { + if (!is_null($maxscalefactor)) { + if ($factor > $maxscalefactor) { \OC_Log::write('core', 'scalefactor reduced from ' . $factor . ' to ' . $maxscalefactor, \OC_Log::DEBUG); $factor = $maxscalefactor; } } - $newXsize = (int) ($realx * $factor); - $newYsize = (int) ($realy * $factor); + $newXsize = (int)($realx * $factor); + $newYsize = (int)($realy * $factor); $image->preciseResize($newXsize, $newYsize); - if($newXsize === $x && $newYsize === $y) { + if ($newXsize === $x && $newYsize === $y) { $this->preview = $image; return; } - if($newXsize >= $x && $newYsize >= $y) { + if ($newXsize >= $x && $newYsize >= $y) { $cropX = floor(abs($x - $newXsize) * 0.5); //don't crop previews on the Y axis, this sucks if it's a document. //$cropY = floor(abs($y - $newYsize) * 0.5); @@ -532,19 +546,19 @@ class Preview { return; } - if($newXsize < $x || $newYsize < $y) { - if($newXsize > $x) { + if ($newXsize < $x || $newYsize < $y) { + if ($newXsize > $x) { $cropX = floor(($newXsize - $x) * 0.5); $image->crop($cropX, 0, $x, $newYsize); } - if($newYsize > $y) { + if ($newYsize > $y) { $cropY = floor(($newYsize - $y) * 0.5); $image->crop(0, $cropY, $newXsize, $y); } - $newXsize = (int) $image->width(); - $newYsize = (int) $image->height(); + $newXsize = (int)$image->width(); + $newYsize = (int)$image->height(); //create transparent background layer $backgroundlayer = imagecreatetruecolor($x, $y); @@ -573,8 +587,8 @@ class Preview { * @param array $options * @return void */ - public static function registerProvider($class, $options=array()) { - self::$registeredProviders[]=array('class'=>$class, 'options'=>$options); + public static function registerProvider($class, $options = array()) { + self::$registeredProviders[] = array('class' => $class, 'options' => $options); } /** @@ -582,19 +596,19 @@ class Preview { * @return void */ private static function initProviders() { - if(!\OC_Config::getValue('enable_previews', true)) { + if (!\OC_Config::getValue('enable_previews', true)) { $provider = new Preview\Unknown(array()); self::$providers = array($provider->getMimeType() => $provider); return; } - if(count(self::$providers)>0) { + if (count(self::$providers) > 0) { return; } - foreach(self::$registeredProviders as $provider) { - $class=$provider['class']; - $options=$provider['options']; + foreach (self::$registeredProviders as $provider) { + $class = $provider['class']; + $options = $provider['options']; $object = new $class($options); @@ -611,7 +625,7 @@ class Preview { public static function post_delete($args) { $path = $args['path']; - if(substr($path, 0, 1) === '/') { + if (substr($path, 0, 1) === '/') { $path = substr($path, 1); } $preview = new Preview(\OC_User::getUser(), 'files/', $path); @@ -622,19 +636,19 @@ class Preview { * @param string $mimetype */ public static function isMimeSupported($mimetype) { - if(!\OC_Config::getValue('enable_previews', true)) { + if (!\OC_Config::getValue('enable_previews', true)) { return false; } //check if there are preview backends - if(empty(self::$providers)) { + if (empty(self::$providers)) { self::initProviders(); } //remove last element because it has the mimetype * $providers = array_slice(self::$providers, 0, -1); - foreach($providers as $supportedMimetype => $provider) { - if(preg_match($supportedMimetype, $mimetype)) { + foreach ($providers as $supportedMimetype => $provider) { + if (preg_match($supportedMimetype, $mimetype)) { return true; } } diff --git a/lib/private/preview/movies.php b/lib/private/preview/movies.php index 71cd3bae05..7e0ff51ad2 100644 --- a/lib/private/preview/movies.php +++ b/lib/private/preview/movies.php @@ -9,7 +9,7 @@ namespace OC\Preview; function findBinaryPath($program) { - exec('which ' . escapeshellarg($program) . ' 2> /dev/null', $output, $returnCode); + exec('command -v ' . escapeshellarg($program) . ' 2> /dev/null', $output, $returnCode); if ($returnCode === 0 && count($output) > 0) { return escapeshellcmd($output[0]); } diff --git a/lib/private/preview/office-cl.php b/lib/private/preview/office-cl.php index b11fed13ba..6e4d4321eb 100644 --- a/lib/private/preview/office-cl.php +++ b/lib/private/preview/office-cl.php @@ -64,12 +64,12 @@ if (!\OC_Util::runningOnWindows()) { $cmd = \OC_Config::getValue('preview_libreoffice_path', null); } - $whichLibreOffice = shell_exec('which libreoffice'); + $whichLibreOffice = shell_exec('command -v libreoffice'); if($cmd === '' && !empty($whichLibreOffice)) { $cmd = 'libreoffice'; } - $whichOpenOffice = shell_exec('which openoffice'); + $whichOpenOffice = shell_exec('command -v openoffice'); if($cmd === '' && !empty($whichOpenOffice)) { $cmd = 'openoffice'; } diff --git a/lib/private/preview/office.php b/lib/private/preview/office.php index 02bb22e9b9..131bc9a0dc 100644 --- a/lib/private/preview/office.php +++ b/lib/private/preview/office.php @@ -11,9 +11,9 @@ if (extension_loaded('imagick') && count(@\Imagick::queryFormats("PDF")) === 1) // LibreOffice preview is currently not supported on Windows if (!\OC_Util::runningOnWindows()) { - $whichLibreOffice = ($isShellExecEnabled ? shell_exec('which libreoffice') : ''); + $whichLibreOffice = ($isShellExecEnabled ? shell_exec('command -v libreoffice') : ''); $isLibreOfficeAvailable = !empty($whichLibreOffice); - $whichOpenOffice = ($isShellExecEnabled ? shell_exec('which libreoffice') : ''); + $whichOpenOffice = ($isShellExecEnabled ? shell_exec('command -v libreoffice') : ''); $isOpenOfficeAvailable = !empty($whichOpenOffice); //let's see if there is libreoffice or openoffice on this machine if($isShellExecEnabled && ($isLibreOfficeAvailable || $isOpenOfficeAvailable || is_string(\OC_Config::getValue('preview_libreoffice_path', null)))) { diff --git a/lib/private/template/base.php b/lib/private/template/base.php index 232a29939c..7aa0cb4a95 100644 --- a/lib/private/template/base.php +++ b/lib/private/template/base.php @@ -61,7 +61,7 @@ class Base { /** * @brief Assign variables * @param string $key key - * @param string $value value + * @param array|bool|integer|string $value value * @return bool * * This function assigns a variable. It can be accessed via $_[$key] in diff --git a/settings/admin/controller.php b/settings/admin/controller.php index a075d77436..7019f9a4d2 100644 --- a/settings/admin/controller.php +++ b/settings/admin/controller.php @@ -73,6 +73,36 @@ class Controller { \OC_JSON::success(array("data" => array( "message" => $l->t("Saved") ))); } + /** + * Send a mail to test the settings + */ + public static function sendTestMail() { + \OC_Util::checkAdminUser(); + \OCP\JSON::callCheck(); + + $l = \OC_L10N::get('settings'); + $email = \OC_Preferences::getValue(\OC_User::getUser(), 'settings', 'email', ''); + if (!empty($email)) { + $defaults = new \OC_Defaults(); + + try { + \OC_Mail::send($email, $_POST['user'], + $l->t('test email settings'), + $l->t('If you received this email, the settings seem to be correct.'), + \OCP\Util::getDefaultEmailAddress('no-reply'), $defaults->getName()); + } catch (\Exception $e) { + $message = $l->t('A problem occurred while sending the e-mail. Please revisit your settings.'); + \OC_JSON::error( array( "data" => array( "message" => $message)) ); + exit; + } + + \OC_JSON::success(array("data" => array( "message" => $l->t("Email sent") ))); + } else { + $message = $l->t('You need to set your user email before being able to send test emails.'); + \OC_JSON::error( array( "data" => array( "message" => $message)) ); + } + } + /** * Get the field name to use it in error messages * diff --git a/settings/js/admin.js b/settings/js/admin.js index cfb1cb788d..c04c0505de 100644 --- a/settings/js/admin.js +++ b/settings/js/admin.js @@ -62,10 +62,18 @@ $(document).ready(function(){ }); $('#mail_settings').change(function(){ - OC.msg.startSaving('#mail_settings .msg'); + OC.msg.startSaving('#mail_settings_msg'); var post = $( "#mail_settings" ).serialize(); $.post(OC.generateUrl('/settings/admin/mailsettings'), post, function(data){ OC.msg.finishedSaving('#mail_settings .msg', data); }); }); + + $('#sendtestemail').click(function(){ + OC.msg.startAction('#sendtestmail_msg', t('settings', 'Sending...')); + var post = $( "#sendtestemail" ).serialize(); + $.post(OC.generateUrl('/settings/admin/mailtest'), post, function(data){ + OC.msg.finishedAction('#sendtestmail_msg', data); + }); + }); }); diff --git a/settings/routes.php b/settings/routes.php index 7d94f13008..6954bd3823 100644 --- a/settings/routes.php +++ b/settings/routes.php @@ -75,5 +75,8 @@ $this->create('settings_ajax_setloglevel', '/settings/ajax/setloglevel.php') $this->create('settings_mail_settings', '/settings/admin/mailsettings') ->post() ->action('OC\Settings\Admin\Controller', 'setMailSettings'); +$this->create('settings_admin_mail_test', '/settings/admin/mailtest') + ->post() + ->action('OC\Settings\Admin\Controller', 'sendTestMail'); $this->create('settings_ajax_setsecurity', '/settings/ajax/setsecurity.php') ->actionInclude('settings/ajax/setsecurity.php'); diff --git a/settings/templates/admin.php b/settings/templates/admin.php index 139a9dd076..487da036e7 100644 --- a/settings/templates/admin.php +++ b/settings/templates/admin.php @@ -272,7 +272,7 @@ if (!$_['internetconnectionworking']) {
-

t('Email Server'));?>

+

t('Email Server'));?>

t('This is used for sending out notifications.')); ?>

@@ -347,6 +347,10 @@ if (!$_['internetconnectionworking']) { placeholder="t('SMTP Password'))?>" value='' />

+
+ t( 'Test email settings' )); ?> + +
diff --git a/settings/templates/personal.php b/settings/templates/personal.php index 470b8180bc..9024f43565 100644 --- a/settings/templates/personal.php +++ b/settings/templates/personal.php @@ -83,7 +83,7 @@ if($_['passwordChangeSupported']) { placeholder="t('Your email address'));?>" autocomplete="on" autocapitalize="off" autocorrect="off" />
- t('Fill in an email address to enable password recovery'));?> + t('Fill in an email address to enable password recovery and receive notifications'));?>