diff options
Diffstat (limited to 'apps')
75 files changed, 872 insertions, 399 deletions
diff --git a/apps/files/ajax/delete.php b/apps/files/ajax/delete.php index c69f5a8860c..69f859daa97 100644 --- a/apps/files/ajax/delete.php +++ b/apps/files/ajax/delete.php @@ -9,8 +9,21 @@ OCP\JSON::callCheck(); // Get data $dir = stripslashes($_POST["dir"]); $files = isset($_POST["file"]) ? $_POST["file"] : $_POST["files"]; +$allFiles = isset($_POST["allfiles"]) ? $_POST["allfiles"] : $_POST["allfiles"]; +if ($allFiles === 'true') { + $allFiles = true; +} -$files = json_decode($files); +// delete all files in dir ? +if ($allFiles) { + $files = array(); + $fileList = \OC\Files\Filesystem::getDirectoryContent($dir); + foreach ($fileList as $fileInfo) { + $files[] = $fileInfo['name']; + } +} else { + $files = json_decode($files); +} $filesWithError = ''; $success = true; diff --git a/apps/files/ajax/list.php b/apps/files/ajax/list.php index 0be38c3b96f..c8286bc15ca 100644 --- a/apps/files/ajax/list.php +++ b/apps/files/ajax/list.php @@ -11,7 +11,8 @@ OCP\JSON::checkLoggedIn(); // Load the files $dir = isset( $_GET['dir'] ) ? $_GET['dir'] : ''; $dir = \OC\Files\Filesystem::normalizePath($dir); -if (!\OC\Files\Filesystem::is_dir($dir . '/')) { +$dirInfo = \OC\Files\Filesystem::getFileInfo($dir); +if (!$dirInfo->getType() === 'dir') { header("HTTP/1.0 404 Not Found"); exit(); } @@ -20,7 +21,7 @@ $doBreadcrumb = isset($_GET['breadcrumb']); $data = array(); $baseUrl = OCP\Util::linkTo('files', 'index.php') . '?dir='; -$permissions = \OCA\Files\Helper::getDirPermissions($dir); +$permissions = $dirInfo->getPermissions(); // Make breadcrumb if($doBreadcrumb) { diff --git a/apps/files/ajax/newfile.php b/apps/files/ajax/newfile.php index 1853098c507..0187b200759 100644 --- a/apps/files/ajax/newfile.php +++ b/apps/files/ajax/newfile.php @@ -50,16 +50,22 @@ $l10n = \OC_L10n::get('files'); $result = array( 'success' => false, 'data' => NULL - ); +); +$trimmedFileName = trim($filename); -if(trim($filename) === '') { +if($trimmedFileName === '') { $result['data'] = array('message' => (string)$l10n->t('File name cannot be empty.')); OCP\JSON::error($result); exit(); } +if($trimmedFileName === '.' || $trimmedFileName === '..') { + $result['data'] = array('message' => (string)$l10n->t('"%s" is an invalid file name.', $trimmedFileName)); + OCP\JSON::error($result); + exit(); +} -if(strpos($filename, '/') !== false) { - $result['data'] = array('message' => (string)$l10n->t('File name must not contain "/". Please choose a different name.')); +if(!OCP\Util::isValidFileName($filename)) { + $result['data'] = array('message' => (string)$l10n->t("Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed.")); OCP\JSON::error($result); exit(); } diff --git a/apps/files/ajax/newfolder.php b/apps/files/ajax/newfolder.php index 4cfcae3090d..b2b4fb27f74 100644 --- a/apps/files/ajax/newfolder.php +++ b/apps/files/ajax/newfolder.php @@ -23,8 +23,8 @@ if(trim($foldername) === '') { exit(); } -if(strpos($foldername, '/') !== false) { - $result['data'] = array('message' => $l10n->t('Folder name must not contain "/". Please choose a different name.')); +if(!OCP\Util::isValidFileName($foldername)) { + $result['data'] = array('message' => (string)$l10n->t("Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed.")); OCP\JSON::error($result); exit(); } diff --git a/apps/files/ajax/upload.php b/apps/files/ajax/upload.php index 754c34ef088..145f40c50da 100644 --- a/apps/files/ajax/upload.php +++ b/apps/files/ajax/upload.php @@ -22,6 +22,7 @@ if (empty($_POST['dirToken'])) { } else { // return only read permissions for public upload $allowedPermissions = OCP\PERMISSION_READ; + $public_directory = !empty($_POST['subdir']) ? $_POST['subdir'] : '/'; $linkItem = OCP\Share::getShareByToken($_POST['dirToken']); if ($linkItem === false) { @@ -45,7 +46,7 @@ if (empty($_POST['dirToken'])) { $dir = sprintf( "/%s/%s", $path, - isset($_POST['subdir']) ? $_POST['subdir'] : '' + $public_directory ); if (!$dir || empty($dir) || $dir === false) { @@ -112,7 +113,14 @@ if (strpos($dir, '..') === false) { } else { $target = \OC\Files\Filesystem::normalizePath(stripslashes($dir).'/'.$files['name'][$i]); } - + + $directory = \OC\Files\Filesystem::normalizePath(stripslashes($dir)); + if (isset($public_directory)) { + // If we are uploading from the public app, + // we want to send the relative path in the ajax request. + $directory = $public_directory; + } + if ( ! \OC\Files\Filesystem::file_exists($target) || (isset($_POST['resolution']) && $_POST['resolution']==='replace') ) { @@ -140,7 +148,7 @@ if (strpos($dir, '..') === false) { 'uploadMaxFilesize' => $maxUploadFileSize, 'maxHumanFilesize' => $maxHumanFileSize, 'permissions' => $meta['permissions'] & $allowedPermissions, - 'directory' => \OC\Files\Filesystem::normalizePath(stripslashes($dir)), + 'directory' => $directory, ); } @@ -168,7 +176,7 @@ if (strpos($dir, '..') === false) { 'uploadMaxFilesize' => $maxUploadFileSize, 'maxHumanFilesize' => $maxHumanFileSize, 'permissions' => $meta['permissions'] & $allowedPermissions, - 'directory' => \OC\Files\Filesystem::normalizePath(stripslashes($dir)), + 'directory' => $directory, ); } } diff --git a/apps/files/appinfo/update.php b/apps/files/appinfo/update.php index 3503678e7c7..f920f842166 100644 --- a/apps/files/appinfo/update.php +++ b/apps/files/appinfo/update.php @@ -3,17 +3,14 @@ // fix webdav properties,add namespace in front of the property, update for OC4.5 $installedVersion=OCP\Config::getAppValue('files', 'installed_version'); if (version_compare($installedVersion, '1.1.6', '<')) { - $query = OC_DB::prepare( 'SELECT `propertyname`, `propertypath`, `userid` FROM `*PREFIX*properties`' ); - $result = $query->execute(); - $updateQuery = OC_DB::prepare('UPDATE `*PREFIX*properties`' - .' SET `propertyname` = ?' - .' WHERE `userid` = ?' - .' AND `propertypath` = ?'); - while( $row = $result->fetchRow()) { - if ( $row['propertyname'][0] != '{' ) { - $updateQuery->execute(array('{DAV:}' + $row['propertyname'], $row['userid'], $row['propertypath'])); - } - } + $concat = OC_DB::getConnection()->getDatabasePlatform()-> + getConcatExpression( '\'{DAV:}\'', '`propertyname`' ); + $query = OC_DB::prepare(' + UPDATE `*PREFIX*properties` + SET `propertyname` = ' . $concat . ' + WHERE `propertyname` NOT LIKE \'{%\' + '); + $query->execute(); } //update from OC 3 diff --git a/apps/files/command/scan.php b/apps/files/command/scan.php index 25ab70af362..f334f29a939 100644 --- a/apps/files/command/scan.php +++ b/apps/files/command/scan.php @@ -58,6 +58,7 @@ class Scan extends Command { protected function execute(InputInterface $input, OutputInterface $output) { if ($input->getOption('all')) { + \OC_App::loadApps('authentication'); $users = $this->userManager->search(''); } else { $users = $input->getArgument('user_id'); diff --git a/apps/files/css/files.css b/apps/files/css/files.css index 5526abaf6e2..3ad167054c2 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -84,9 +84,26 @@ background-color: rgb(240,240,240); } tbody a { color:#000; } -span.extension, span.uploading, td.date { color:#999; } -span.extension { text-transform:lowercase; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)"; filter:alpha(opacity=70); opacity:.7; -webkit-transition:opacity 300ms; -moz-transition:opacity 300ms; -o-transition:opacity 300ms; transition:opacity 300ms; } -tr:hover span.extension { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; filter:alpha(opacity=100); opacity:1; color:#777; } + +span.extension, span.uploading, td.date { + color: #999; +} +span.extension { + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=70)"; + filter: alpha(opacity=70); + opacity: .7; + -webkit-transition: opacity 300ms; + -moz-transition: opacity 300ms; + -o-transition: opacity 300ms; + transition: opacity 300ms; +} +tr:hover span.extension { + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; + filter: alpha(opacity=100); + opacity: 1; + color: #777; +} + table tr.mouseOver td { background-color:#eee; } table th { height:24px; padding:0 8px; color:#999; } table th .name { @@ -302,7 +319,7 @@ a.action>img { max-height:16px; max-width:16px; vertical-align:text-bottom; } #fileList a.action { display: inline; margin: -8px 0; - padding: 18px 8px !important; + padding: 18px 8px; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; filter: alpha(opacity=0); opacity: 0; diff --git a/apps/files/index.php b/apps/files/index.php index dd63f29bc28..ad7a2e210ed 100644 --- a/apps/files/index.php +++ b/apps/files/index.php @@ -37,8 +37,9 @@ OCP\App::setActiveNavigationEntry('files_index'); // Load the files $dir = isset($_GET['dir']) ? stripslashes($_GET['dir']) : ''; $dir = \OC\Files\Filesystem::normalizePath($dir); +$dirInfo = \OC\Files\Filesystem::getFileInfo($dir); // Redirect if directory does not exist -if (!\OC\Files\Filesystem::is_dir($dir . '/')) { +if (!$dirInfo->getType() === 'dir') { header('Location: ' . OCP\Util::getScriptName() . ''); exit(); } @@ -79,6 +80,8 @@ if (\OC\Files\Cache\Upgrade::needUpgrade($user)) { //dont load anything if we ne $needUpgrade = false; } +$config = \OC::$server->getConfig(); + // Make breadcrumb $breadcrumb = \OCA\Files\Helper::makeBreadcrumb($dir); @@ -92,7 +95,7 @@ $breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', ''); $breadcrumbNav->assign('breadcrumb', $breadcrumb); $breadcrumbNav->assign('baseURL', OCP\Util::linkTo('files', 'index.php') . '?dir='); -$permissions = \OCA\Files\Helper::getDirPermissions($dir); +$permissions = $dirInfo->getPermissions(); if ($needUpgrade) { OCP\Util::addscript('files', 'upgrade'); @@ -104,7 +107,7 @@ if ($needUpgrade) { $freeSpace=$storageInfo['free']; $uploadLimit=OCP\Util::uploadLimit(); $maxUploadFilesize=OCP\Util::maxUploadFilesize($dir); - $publicUploadEnabled = \OC_Appconfig::getValue('core', 'shareapi_allow_public_upload', 'yes'); + $publicUploadEnabled = $config->getAppValue('core', 'shareapi_allow_public_upload', 'yes'); // if the encryption app is disabled, than everything is fine (INIT_SUCCESSFUL status code) $encryptionInitStatus = 2; if (OC_App::isEnabled('files_encryption')) { @@ -143,8 +146,8 @@ if ($needUpgrade) { $tmpl->assign('isPublic', false); $tmpl->assign('publicUploadEnabled', $publicUploadEnabled); $tmpl->assign("encryptedFiles", \OCP\Util::encryptedFiles()); - $tmpl->assign("mailNotificationEnabled", \OC_Appconfig::getValue('core', 'shareapi_allow_mail_notification', 'yes')); - $tmpl->assign("allowShareWithLink", \OC_Appconfig::getValue('core', 'shareapi_allow_links', 'yes')); + $tmpl->assign("mailNotificationEnabled", $config->getAppValue('core', 'shareapi_allow_mail_notification', 'yes')); + $tmpl->assign("allowShareWithLink", $config->getAppValue('core', 'shareapi_allow_links', 'yes')); $tmpl->assign("encryptionInitStatus", $encryptionInitStatus); $tmpl->assign('disableSharing', false); $tmpl->assign('ajaxLoad', $ajaxLoad); diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index a855d6cbe59..d6cffde05de 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -582,30 +582,49 @@ window.FileList={ }}); } }, - do_delete:function(files) { - if (files.substr) { + do_delete:function(files, dir) { + var params; + if (files && files.substr) { files=[files]; } - for (var i=0; i<files.length; i++) { - var deleteAction = FileList.findFileEl(files[i]).children("td.date").children(".action.delete"); - deleteAction.removeClass('delete-icon').addClass('progress-icon'); + if (files) { + for (var i=0; i<files.length; i++) { + var deleteAction = FileList.findFileEl(files[i]).children("td.date").children(".action.delete"); + deleteAction.removeClass('delete-icon').addClass('progress-icon'); + } } // Finish any existing actions if (FileList.lastAction) { FileList.lastAction(); } - var fileNames = JSON.stringify(files); + var params = { + dir: dir || FileList.getCurrentDirectory() + }; + if (files) { + params.files = JSON.stringify(files); + } + else { + // no files passed, delete all in current dir + params.allfiles = true; + } + $.post(OC.filePath('files', 'ajax', 'delete.php'), - {dir:$('#dir').val(),files:fileNames}, + params, function(result) { if (result.status === 'success') { - $.each(files,function(index,file) { - var files = FileList.findFileEl(file); - files.remove(); - files.find('input[type="checkbox"]').removeAttr('checked'); - files.removeClass('selected'); - }); + if (params.allfiles) { + // clear whole list + $('#fileList tr').remove(); + } + else { + $.each(files,function(index,file) { + var files = FileList.findFileEl(file); + files.remove(); + files.find('input[type="checkbox"]').removeAttr('checked'); + files.removeClass('selected'); + }); + } procesSelection(); checkTrashStatus(); FileList.updateFileSummary(); @@ -622,10 +641,17 @@ window.FileList={ setTimeout(function() { OC.Notification.hide(); }, 10000); - $.each(files,function(index,file) { - var deleteAction = FileList.findFileEl(file).find('.action.delete'); - deleteAction.removeClass('progress-icon').addClass('delete-icon'); - }); + if (params.allfiles) { + // reload the page as we don't know what files were deleted + // and which ones remain + FileList.reload(); + } + else { + $.each(files,function(index,file) { + var deleteAction = FileList.findFileEl(file).find('.action.delete'); + deleteAction.removeClass('progress-icon').addClass('delete-icon'); + }); + } } }); }, @@ -794,6 +820,13 @@ window.FileList={ $(e).removeClass("searchresult"); }); }, + /** + * Returns whether all files are selected + * @return true if all files are selected, false otherwise + */ + isAllSelected: function() { + return $('#select_all').prop('checked'); + }, /** * Returns the download URL of the given file @@ -801,10 +834,13 @@ window.FileList={ * @param dir optional directory in which the file name is, defaults to the current directory */ getDownloadUrl: function(filename, dir) { + var files = filename; + if ($.isArray(filename)) { + files = JSON.stringify(filename); + } var params = { - files: filename, dir: dir || FileList.getCurrentDirectory(), - download: null + files: files }; return OC.filePath('files', 'ajax', 'download.php') + '?' + OC.buildQueryString(params); } diff --git a/apps/files/js/files.js b/apps/files/js/files.js index 1ec4c4ec7ab..fbac601f67a 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -364,23 +364,26 @@ $(document).ready(function() { }); $('.download').click('click',function(event) { - var files=getSelectedFilesTrash('name'); - var fileslist = JSON.stringify(files); - var dir=$('#dir').val()||'/'; - OC.Notification.show(t('files','Your download is being prepared. This might take some time if the files are big.')); - // use special download URL if provided, e.g. for public shared files - var downloadURL = document.getElementById("downloadURL"); - if ( downloadURL ) { - window.location = downloadURL.value+"&download&files=" + encodeURIComponent(fileslist); - } else { - window.location = OC.filePath('files', 'ajax', 'download.php') + '?'+ $.param({ dir: dir, files: fileslist }); + var files; + var dir = FileList.getCurrentDirectory(); + if (FileList.isAllSelected()) { + files = OC.basename(dir); + dir = OC.dirname(dir) || '/'; } + else { + files = getSelectedFilesTrash('name'); + } + OC.Notification.show(t('files','Your download is being prepared. This might take some time if the files are big.')); + OC.redirect(FileList.getDownloadUrl(files, dir)); return false; }); $('.delete-selected').click(function(event) { var files=getSelectedFilesTrash('name'); event.preventDefault(); + if (FileList.isAllSelected()) { + files = null; + } FileList.do_delete(files); return false; }); diff --git a/apps/files/lib/helper.php b/apps/files/lib/helper.php index 21d1f50e587..ac8a2ad3200 100644 --- a/apps/files/lib/helper.php +++ b/apps/files/lib/helper.php @@ -5,14 +5,14 @@ namespace OCA\Files; class Helper { public static function buildFileStorageStatistics($dir) { + // information about storage capacities + $storageInfo = \OC_Helper::getStorageInfo($dir); + $l = new \OC_L10N('files'); - $maxUploadFilesize = \OCP\Util::maxUploadFilesize($dir); + $maxUploadFilesize = \OCP\Util::maxUploadFilesize($dir, $storageInfo['free']); $maxHumanFilesize = \OCP\Util::humanFileSize($maxUploadFilesize); $maxHumanFilesize = $l->t('Upload') . ' max. ' . $maxHumanFilesize; - // information about storage capacities - $storageInfo = \OC_Helper::getStorageInfo($dir); - return array('uploadMaxFilesize' => $maxUploadFilesize, 'maxHumanFilesize' => $maxHumanFilesize, 'freeSpace' => $storageInfo['free'], @@ -112,26 +112,4 @@ class Helper } return $breadcrumb; } - - /** - * Returns the numeric permissions for the given directory. - * @param string $dir directory without trailing slash - * @return numeric permissions - */ - public static function getDirPermissions($dir){ - $permissions = \OCP\PERMISSION_READ; - if (\OC\Files\Filesystem::isCreatable($dir . '/')) { - $permissions |= \OCP\PERMISSION_CREATE; - } - if (\OC\Files\Filesystem::isUpdatable($dir . '/')) { - $permissions |= \OCP\PERMISSION_UPDATE; - } - if (\OC\Files\Filesystem::isDeletable($dir . '/')) { - $permissions |= \OCP\PERMISSION_DELETE; - } - if (\OC\Files\Filesystem::isSharable($dir . '/')) { - $permissions |= \OCP\PERMISSION_SHARE; - } - return $permissions; - } } diff --git a/apps/files/tests/js/fileactionsSpec.js b/apps/files/tests/js/fileactionsSpec.js index 8bbc1d3d141..ef7ddcb874a 100644 --- a/apps/files/tests/js/fileactionsSpec.js +++ b/apps/files/tests/js/fileactionsSpec.js @@ -69,7 +69,7 @@ describe('FileActions tests', function() { $tr.find('.action[data-action=Download]').click(); expect(redirectStub.calledOnce).toEqual(true); - expect(redirectStub.getCall(0).args[0]).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?files=test%20download%20File.txt&dir=%2Fsubdir&download'); + expect(redirectStub.getCall(0).args[0]).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=test%20download%20File.txt'); redirectStub.restore(); }); }); diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js index c26e65fc4de..8f4cb86ab4a 100644 --- a/apps/files/tests/js/filelistSpec.js +++ b/apps/files/tests/js/filelistSpec.js @@ -58,8 +58,15 @@ describe('FileList tests', function() { expect($tr.attr('data-permissions')).toEqual('31'); //expect($tr.attr('data-mime')).toEqual('httpd/unix-directory'); }); - it('returns correct download URL', function() { - expect(FileList.getDownloadUrl('some file.txt')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?files=some%20file.txt&dir=%2Fsubdir&download'); - expect(FileList.getDownloadUrl('some file.txt', '/anotherpath/abc')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?files=some%20file.txt&dir=%2Fanotherpath%2Fabc&download'); + describe('Download Url', function() { + it('returns correct download URL for single files', function() { + expect(FileList.getDownloadUrl('some file.txt')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=some%20file.txt'); + expect(FileList.getDownloadUrl('some file.txt', '/anotherpath/abc')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fanotherpath%2Fabc&files=some%20file.txt'); + $('#dir').val('/'); + expect(FileList.getDownloadUrl('some file.txt')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2F&files=some%20file.txt'); + }); + it('returns correct download URL for multiple files', function() { + expect(FileList.getDownloadUrl(['a b c.txt', 'd e f.txt'])).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=%5B%22a%20b%20c.txt%22%2C%22d%20e%20f.txt%22%5D'); + }); }); }); diff --git a/apps/files_encryption/ajax/adminrecovery.php b/apps/files_encryption/ajax/adminrecovery.php index 6a0186d5a9b..61e43acc2c3 100644 --- a/apps/files_encryption/ajax/adminrecovery.php +++ b/apps/files_encryption/ajax/adminrecovery.php @@ -18,7 +18,7 @@ $l = OC_L10N::get('files_encryption'); $return = false; // Enable recoveryAdmin -$recoveryKeyId = OC_Appconfig::getValue('files_encryption', 'recoveryKeyId'); +$recoveryKeyId = \OC::$server->getAppConfig()->getValue('files_encryption', 'recoveryKeyId'); if (isset($_POST['adminEnableRecovery']) && $_POST['adminEnableRecovery'] === '1') { diff --git a/apps/files_encryption/ajax/getMigrationStatus.php b/apps/files_encryption/ajax/getMigrationStatus.php index 17469a1af0c..7c9e0dcc51c 100644 --- a/apps/files_encryption/ajax/getMigrationStatus.php +++ b/apps/files_encryption/ajax/getMigrationStatus.php @@ -13,16 +13,14 @@ use OCA\Encryption\Util; $loginname = isset($_POST['user']) ? $_POST['user'] : ''; $password = isset($_POST['password']) ? $_POST['password'] : ''; -$migrationCompleted = true; +$migrationStatus = Util::MIGRATION_COMPLETED; if ($loginname !== '' && $password !== '') { $username = \OCP\User::checkPassword($loginname, $password); if ($username) { $util = new Util(new \OC_FilesystemView('/'), $username); - if ($util->getMigrationStatus() !== Util::MIGRATION_COMPLETED) { - $migrationCompleted = false; - } + $migrationStatus = $util->getMigrationStatus(); } } -\OCP\JSON::success(array('data' => array('migrationCompleted' => $migrationCompleted))); +\OCP\JSON::success(array('data' => array('migrationStatus' => $migrationStatus))); diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php index fd9aa429b01..21de421c195 100644 --- a/apps/files_encryption/appinfo/app.php +++ b/apps/files_encryption/appinfo/app.php @@ -10,6 +10,7 @@ OC::$CLASSPATH['OCA\Encryption\Session'] = 'files_encryption/lib/session.php'; OC::$CLASSPATH['OCA\Encryption\Capabilities'] = 'files_encryption/lib/capabilities.php'; OC::$CLASSPATH['OCA\Encryption\Helper'] = 'files_encryption/lib/helper.php'; +\OCP\Util::addscript('files_encryption', 'encryption'); \OCP\Util::addscript('files_encryption', 'detect-migration'); if (!OC_Config::getValue('maintenance', false)) { diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 83abf3ba9de..3af43f10264 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -85,10 +85,9 @@ class Hooks { $ready = $util->beginMigration();
} elseif ($migrationStatus === Util::MIGRATION_IN_PROGRESS) {
// refuse login as long as the initial encryption is running
- while ($migrationStatus === Util::MIGRATION_IN_PROGRESS) {
- sleep(60);
- $migrationStatus = $util->getMigrationStatus();
- }
+ sleep(5);
+ \OCP\User::logout();
+ return false;
}
// If migration not yet done
@@ -109,21 +108,27 @@ class Hooks { }
- // Encrypt existing user files:
- if (
- $util->encryptAll('/' . $params['uid'] . '/' . 'files', $session->getLegacyKey(), $params['password'])
- ) {
+ // Encrypt existing user files
+ try {
+ $result = $util->encryptAll('/' . $params['uid'] . '/' . 'files', $session->getLegacyKey(), $params['password']);
+ } catch (\Exception $ex) {
+ \OCP\Util::writeLog('Encryption library', 'Initial encryption failed! Error: ' . $ex->getMessage(), \OCP\Util::FATAL);
+ $util->resetMigrationStatus();
+ \OCP\User::logout();
+ $result = false;
+ }
+
+ if ($result) {
\OC_Log::write(
'Encryption library', 'Encryption of existing files belonging to "' . $params['uid'] . '" completed'
, \OC_Log::INFO
);
- }
-
- // Register successful migration in DB
- $util->finishMigration();
+ // Register successful migration in DB
+ $util->finishMigration();
+ }
}
return true;
@@ -642,7 +647,7 @@ class Hooks { /**
* @brief if the file was really deleted we remove the encryption keys
* @param array $params
- * @return boolean
+ * @return boolean|null
*/
public static function postDelete($params) {
@@ -682,7 +687,7 @@ class Hooks { /**
* @brief remember the file which should be deleted and it's owner
* @param array $params
- * @return boolean
+ * @return boolean|null
*/
public static function preDelete($params) {
$path = $params[\OC\Files\Filesystem::signal_param_path];
diff --git a/apps/files_encryption/js/detect-migration.js b/apps/files_encryption/js/detect-migration.js index 301e77f24f7..f5627edf4e4 100644 --- a/apps/files_encryption/js/detect-migration.js +++ b/apps/files_encryption/js/detect-migration.js @@ -17,10 +17,14 @@ $(document).ready(function(){ data: {user: user, password: password}, async: false, success: function(response) { - if (response.data.migrationCompleted === false) { + if (response.data.migrationStatus === OC.Encryption.MIGRATION_OPEN) { var message = t('files_encryption', 'Initial encryption started... This can take some time. Please wait.'); $('#messageText').text(message); $('#message').removeClass('hidden').addClass('update'); + } else if (response.data.migrationStatus === OC.Encryption.MIGRATION_IN_PROGRESS) { + var message = t('files_encryption', 'Initial encryption running... Please try again later.'); + $('#messageText').text(message); + $('#message').removeClass('hidden').addClass('update'); } } }); diff --git a/apps/files_encryption/js/encryption.js b/apps/files_encryption/js/encryption.js new file mode 100644 index 00000000000..65ffabe55e6 --- /dev/null +++ b/apps/files_encryption/js/encryption.js @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2014 + * Bjoern Schiessle <schiessle@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or later. + * See the COPYING-README file. + */ + +OC.Encryption={ + MIGRATION_OPEN:0, + MIGRATION_COMPLETED:1, + MIGRATION_IN_PROGRESS:-1, +}; diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index 9155d238c77..caca13acece 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -182,6 +182,7 @@ class Crypt { * @param $data
* @param string $relPath The path of the file, relative to user/data;
* e.g. filename or /Docs/filename, NOT admin/files/filename
+ * @param boolean $isCatFileContent
* @return boolean
*/
public static function isLegacyEncryptedContent($isCatFileContent, $relPath) {
@@ -209,8 +210,8 @@ class Crypt { /**
* @brief Symmetrically encrypt a string
- * @param $plainContent
- * @param $iv
+ * @param string $plainContent
+ * @param string $iv
* @param string $passphrase
* @return string encrypted file content
*/
@@ -229,9 +230,9 @@ class Crypt { /**
* @brief Symmetrically decrypt a string
- * @param $encryptedContent
- * @param $iv
- * @param $passphrase
+ * @param string $encryptedContent
+ * @param string $iv
+ * @param string $passphrase
* @throws \Exception
* @return string decrypted file content
*/
@@ -292,8 +293,7 @@ class Crypt { * @brief Symmetrically encrypts a string and returns keyfile content
* @param string $plainContent content to be encrypted in keyfile
* @param string $passphrase
- * @return bool|string
- * @return string encrypted content combined with IV
+ * @return false|string encrypted content combined with IV
* @note IV need not be specified, as it will be stored in the returned keyfile
* and remain accessible therein.
*/
@@ -326,7 +326,7 @@ class Crypt { * @param $keyfileContent
* @param string $passphrase
* @throws \Exception
- * @return bool|string
+ * @return string|false
* @internal param string $source
* @internal param string $target
* @internal param string $key the decryption key
@@ -438,7 +438,7 @@ class Crypt { * @param $encryptedContent
* @param $shareKey
* @param $privateKey
- * @return bool
+ * @return false|string
* @internal param string $plainContent content to be encrypted
* @returns string $plainContent decrypted string
* @note symmetricDecryptFileContent() can be used to decrypt files created using this method
diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php index bb06a57c714..ef3775875f0 100755 --- a/apps/files_encryption/lib/helper.php +++ b/apps/files_encryption/lib/helper.php @@ -103,7 +103,7 @@ class Helper { * @brief enable recovery * * @param $recoveryKeyId - * @param $recoveryPassword + * @param string $recoveryPassword * @internal param \OCA\Encryption\Util $util * @internal param string $password * @return bool @@ -111,10 +111,11 @@ class Helper { public static function adminEnableRecovery($recoveryKeyId, $recoveryPassword) { $view = new \OC\Files\View('/'); + $appConfig = \OC::$server->getAppConfig(); if ($recoveryKeyId === null) { $recoveryKeyId = 'recovery_' . substr(md5(time()), 0, 8); - \OC_Appconfig::setValue('files_encryption', 'recoveryKeyId', $recoveryKeyId); + $appConfig->setValue('files_encryption', 'recoveryKeyId', $recoveryKeyId); } if (!$view->is_dir('/owncloud_private_key')) { @@ -147,7 +148,7 @@ class Helper { \OC_FileProxy::$enabled = true; // Set recoveryAdmin as enabled - \OC_Appconfig::setValue('files_encryption', 'recoveryAdminEnabled', 1); + $appConfig->setValue('files_encryption', 'recoveryAdminEnabled', 1); $return = true; @@ -155,7 +156,7 @@ class Helper { $util = new \OCA\Encryption\Util(new \OC_FilesystemView('/'), \OCP\User::getUser()); $return = $util->checkRecoveryPassword($recoveryPassword); if ($return) { - \OC_Appconfig::setValue('files_encryption', 'recoveryAdminEnabled', 1); + $appConfig->setValue('files_encryption', 'recoveryAdminEnabled', 1); } } @@ -209,7 +210,7 @@ class Helper { /** * @brief disable recovery * - * @param $recoveryPassword + * @param string $recoveryPassword * @return bool */ public static function adminDisableRecovery($recoveryPassword) { @@ -218,7 +219,7 @@ class Helper { if ($return) { // Set recoveryAdmin as disabled - \OC_Appconfig::setValue('files_encryption', 'recoveryAdminEnabled', 0); + \OC::$server->getAppConfig()->setValue('files_encryption', 'recoveryAdminEnabled', 0); } return $return; @@ -344,6 +345,7 @@ class Helper { /** * @brief redirect to a error page + * @param Session $session */ public static function redirectToErrorPage($session, $errorCode = null) { @@ -422,8 +424,8 @@ class Helper { /** * @brief glob uses different pattern than regular expressions, escape glob pattern only - * @param unescaped path - * @return escaped path + * @param string $path unescaped path + * @return string path */ public static function escapeGlobPattern($path) { return preg_replace('/(\*|\?|\[)/', '[$1]', $path); @@ -441,7 +443,7 @@ class Helper { /** * @brief get the path of the original file * @param string $tmpFile path of the tmp file - * @return mixed path of the original file or false + * @return string|false path of the original file or false */ public static function getPathFromTmpFile($tmpFile) { if (isset(self::$tmpFileMapping[$tmpFile])) { diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 7abc565f609..cb9f5e64af3 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -170,7 +170,7 @@ class Keymanager { * @brief retrieve keyfile for an encrypted file * @param \OC_FilesystemView $view * @param \OCA\Encryption\Util $util - * @param $filePath + * @param string|false $filePath * @internal param \OCA\Encryption\file $string name * @return string file key or false * @note The keyfile returned is asymmetrically encrypted. Decryption @@ -513,6 +513,8 @@ class Keymanager { /** * @brief Make preparations to vars and filesystem for saving a keyfile + * @param string|boolean $path + * @param string $basePath */ public static function keySetPreparation(\OC_FilesystemView $view, $path, $basePath, $userId) { @@ -542,7 +544,7 @@ class Keymanager { /** * @brief extract filename from share key name * @param string $shareKey (filename.userid.sharekey) - * @return mixed filename or false + * @return string|false filename or false */ protected static function getFilenameFromShareKey($shareKey) { $parts = explode('.', $shareKey); diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 11048005969..9d456f6c517 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -262,7 +262,7 @@ class Proxy extends \OC_FileProxy { } elseif ( self::shouldEncrypt($path) - and $meta ['mode'] !== 'r' + and $meta['mode'] !== 'r' and $meta['mode'] !== 'rb' ) { $result = fopen('crypt://' . $path, $meta['mode']); @@ -283,7 +283,7 @@ class Proxy extends \OC_FileProxy { public function postGetFileInfo($path, $data) { // if path is a folder do nothing - if (\OCP\App::isEnabled('files_encryption') && is_array($data) && array_key_exists('size', $data)) { + if (\OCP\App::isEnabled('files_encryption') && $data !== false && array_key_exists('size', $data)) { // Disable encryption proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; @@ -341,7 +341,7 @@ class Proxy extends \OC_FileProxy { } // if file is encrypted return real file size - if (is_array($fileInfo) && $fileInfo['encrypted'] === true) { + if ($fileInfo && $fileInfo['encrypted'] === true) { // try to fix unencrypted file size if it doesn't look plausible if ((int)$fileInfo['size'] > 0 && (int)$fileInfo['unencrypted_size'] === 0 ) { $fixSize = $util->getFileSize($path); @@ -354,7 +354,7 @@ class Proxy extends \OC_FileProxy { $size = $fileInfo['unencrypted_size']; } else { // self healing if file was removed from file cache - if (!is_array($fileInfo)) { + if (!$fileInfo) { $fileInfo = array(); } diff --git a/apps/files_encryption/lib/session.php b/apps/files_encryption/lib/session.php index 25f2198181f..aa58e33e9d2 100644 --- a/apps/files_encryption/lib/session.php +++ b/apps/files_encryption/lib/session.php @@ -51,11 +51,13 @@ class Session { } - $publicShareKeyId = \OC_Appconfig::getValue('files_encryption', 'publicShareKeyId'); + $appConfig = \OC::$server->getAppConfig(); + + $publicShareKeyId = $appConfig->getValue('files_encryption', 'publicShareKeyId'); if ($publicShareKeyId === null) { $publicShareKeyId = 'pubShare_' . substr(md5(time()), 0, 8); - \OC_Appconfig::setValue('files_encryption', 'publicShareKeyId', $publicShareKeyId); + $appConfig->setValue('files_encryption', 'publicShareKeyId', $publicShareKeyId); } if ( @@ -195,7 +197,7 @@ class Session { /** * @brief Sets user legacy key to session - * @param $legacyKey + * @param string $legacyKey * @return bool */ public function setLegacyKey($legacyKey) { diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index b3bf34ddb82..88eacc6f136 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -567,7 +567,7 @@ class Stream { // get file info $fileInfo = $this->rootView->getFileInfo($path); - if (is_array($fileInfo)) { + if ($fileInfo) { // set encryption data $fileInfo['encrypted'] = true; $fileInfo['size'] = $this->size; diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index ae3e2a2e15a..ec06bd52f5e 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -63,8 +63,10 @@ class Util { $this->client = $client; $this->userId = $userId; - $this->publicShareKeyId = \OC_Appconfig::getValue('files_encryption', 'publicShareKeyId'); - $this->recoveryKeyId = \OC_Appconfig::getValue('files_encryption', 'recoveryKeyId'); + $appConfig = \OC::$server->getAppConfig(); + + $this->publicShareKeyId = $appConfig->getValue('files_encryption', 'publicShareKeyId'); + $this->recoveryKeyId = $appConfig->getValue('files_encryption', 'recoveryKeyId'); $this->userDir = '/' . $this->userId; $this->fileFolderName = 'files'; @@ -316,7 +318,8 @@ class Util { $found = array( 'plain' => array(), 'encrypted' => array(), - 'legacy' => array() + 'legacy' => array(), + 'broken' => array(), ); } @@ -327,10 +330,7 @@ class Util { if(is_resource($handle)) { while (false !== ($file = readdir($handle))) { - if ( - $file !== "." - && $file !== ".." - ) { + if ($file !== "." && $file !== "..") { $filePath = $directory . '/' . $this->view->getRelativePath('/' . $file); $relPath = \OCA\Encryption\Helper::stripUserFilesPath($filePath); @@ -357,15 +357,23 @@ class Util { // NOTE: This is inefficient; // scanning every file like this // will eat server resources :( - if ( - Keymanager::getFileKey($this->view, $this, $relPath) - && $isEncryptedPath - ) { - - $found['encrypted'][] = array( - 'name' => $file, - 'path' => $filePath - ); + if ($isEncryptedPath) { + + $fileKey = Keymanager::getFileKey($this->view, $this, $relPath); + $shareKey = Keymanager::getShareKey($this->view, $this->userId, $this, $relPath); + // if file is encrypted but now file key is available, throw exception + if ($fileKey === false || $shareKey === false) { + \OCP\Util::writeLog('encryption library', 'No keys available to decrypt the file: ' . $filePath, \OCP\Util::ERROR); + $found['broken'][] = array( + 'name' => $file, + 'path' => $filePath, + ); + } else { + $found['encrypted'][] = array( + 'name' => $file, + 'path' => $filePath, + ); + } // If the file uses old // encryption system @@ -563,7 +571,7 @@ class Util { /** - * @param $path + * @param string $path * @return bool */ public function isSharedPath($path) { @@ -771,6 +779,12 @@ class Util { $successful = false; } + // if there are broken encrypted files than the complete decryption + // was not successful + if (!empty($found['broken'])) { + $successful = false; + } + if ($successful) { $this->view->deleteAll($this->keyfilesPath); $this->view->deleteAll($this->shareKeysPath); @@ -1031,7 +1045,7 @@ class Util { * @brief Decrypt a keyfile * @param string $filePath * @param string $privateKey - * @return bool|string + * @return false|string */ private function decryptKeyfile($filePath, $privateKey) { @@ -1110,12 +1124,15 @@ class Util { /** * @brief Find, sanitise and format users sharing a file * @note This wraps other methods into a portable bundle + * @param boolean $sharingEnabled */ public function getSharingUsersArray($sharingEnabled, $filePath, $currentUserId = false) { + $appConfig = \OC::$server->getAppConfig(); + // Check if key recovery is enabled if ( - \OC_Appconfig::getValue('files_encryption', 'recoveryAdminEnabled') + $appConfig->getValue('files_encryption', 'recoveryAdminEnabled') && $this->recoveryEnabledForUser() ) { $recoveryEnabled = true; @@ -1144,7 +1161,7 @@ class Util { // Admin UID to list of users to share to if ($recoveryEnabled) { // Find recoveryAdmin user ID - $recoveryKeyId = \OC_Appconfig::getValue('files_encryption', 'recoveryKeyId'); + $recoveryKeyId = $appConfig->getValue('files_encryption', 'recoveryKeyId'); // Add recoveryAdmin to list of users sharing $userIds[] = $recoveryKeyId; } @@ -1186,26 +1203,48 @@ class Util { } /** - * @brief start migration mode to initially encrypt users data + * @brief set migration status + * @param int $status * @return boolean */ - public function beginMigration() { - - $return = false; + private function setMigrationStatus($status) { - $sql = 'UPDATE `*PREFIX*encryption` SET `migration_status` = ? WHERE `uid` = ? and `migration_status` = ?'; - $args = array(self::MIGRATION_IN_PROGRESS, $this->userId, self::MIGRATION_OPEN); + $sql = 'UPDATE `*PREFIX*encryption` SET `migration_status` = ? WHERE `uid` = ?'; + $args = array($status, $this->userId); $query = \OCP\DB::prepare($sql); $manipulatedRows = $query->execute($args); if ($manipulatedRows === 1) { - $return = true; + $result = true; + \OCP\Util::writeLog('Encryption library', "Migration status set to " . self::MIGRATION_OPEN, \OCP\Util::INFO); + } else { + $result = false; + \OCP\Util::writeLog('Encryption library', "Could not set migration status to " . self::MIGRATION_OPEN, \OCP\Util::WARN); + } + + return $result; + } + + /** + * @brief start migration mode to initially encrypt users data + * @return boolean + */ + public function beginMigration() { + + $result = $this->setMigrationStatus(self::MIGRATION_IN_PROGRESS); + + if ($result) { \OCP\Util::writeLog('Encryption library', "Start migration to encryption mode for " . $this->userId, \OCP\Util::INFO); } else { \OCP\Util::writeLog('Encryption library', "Could not activate migration mode for " . $this->userId . ". Probably another process already started the initial encryption", \OCP\Util::WARN); } - return $return; + return $result; + } + + public function resetMigrationStatus() { + return $this->setMigrationStatus(self::MIGRATION_OPEN); + } /** @@ -1213,22 +1252,15 @@ class Util { * @return boolean */ public function finishMigration() { + $result = $this->setMigrationStatus(self::MIGRATION_COMPLETED); - $return = false; - - $sql = 'UPDATE `*PREFIX*encryption` SET `migration_status` = ? WHERE `uid` = ? and `migration_status` = ?'; - $args = array(self::MIGRATION_COMPLETED, $this->userId, self::MIGRATION_IN_PROGRESS); - $query = \OCP\DB::prepare($sql); - $manipulatedRows = $query->execute($args); - - if ($manipulatedRows === 1) { - $return = true; + if ($result) { \OCP\Util::writeLog('Encryption library', "Finish migration successfully for " . $this->userId, \OCP\Util::INFO); } else { \OCP\Util::writeLog('Encryption library', "Could not deactivate migration mode for " . $this->userId, \OCP\Util::WARN); } - return $return; + return $result; } /** diff --git a/apps/files_encryption/settings-admin.php b/apps/files_encryption/settings-admin.php index 9ad9bfb8877..88e06613997 100644 --- a/apps/files_encryption/settings-admin.php +++ b/apps/files_encryption/settings-admin.php @@ -11,7 +11,7 @@ $tmpl = new OCP\Template('files_encryption', 'settings-admin'); // Check if an adminRecovery account is enabled for recovering files after lost pwd -$recoveryAdminEnabled = OC_Appconfig::getValue('files_encryption', 'recoveryAdminEnabled', '0'); +$recoveryAdminEnabled = \OC::$server->getAppConfig()->getValue('files_encryption', 'recoveryAdminEnabled', '0'); $tmpl->assign('recoveryEnabled', $recoveryAdminEnabled); diff --git a/apps/files_encryption/settings-personal.php b/apps/files_encryption/settings-personal.php index ffcb99602e2..09e9df05352 100644 --- a/apps/files_encryption/settings-personal.php +++ b/apps/files_encryption/settings-personal.php @@ -20,7 +20,7 @@ $privateKeySet = $session->getPrivateKey() !== false; // did we tried to initialize the keys for this session?
$initialized = $session->getInitialized();
-$recoveryAdminEnabled = OC_Appconfig::getValue('files_encryption', 'recoveryAdminEnabled');
+$recoveryAdminEnabled = \OC::$server->getAppConfig()->getValue('files_encryption', 'recoveryAdminEnabled');
$recoveryEnabledForUser = $util->recoveryEnabledForUser();
$result = false;
diff --git a/apps/files_encryption/tests/crypt.php b/apps/files_encryption/tests/crypt.php index 388980ad4fd..123943ea26a 100755 --- a/apps/files_encryption/tests/crypt.php +++ b/apps/files_encryption/tests/crypt.php @@ -661,7 +661,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { /** * @brief encryption using legacy blowfish method - * @param $data string data to encrypt + * @param string $data data to encrypt * @param $passwd string password * @return string */ diff --git a/apps/files_encryption/tests/hooks.php b/apps/files_encryption/tests/hooks.php index 44525791743..7d926caea1b 100644 --- a/apps/files_encryption/tests/hooks.php +++ b/apps/files_encryption/tests/hooks.php @@ -203,7 +203,7 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase { $fileInfo = $this->user1View->getFileInfo($this->filename); // check if we have a valid file info - $this->assertTrue(is_array($fileInfo)); + $this->assertTrue($fileInfo instanceof \OC\Files\FileInfo); // share the file with user2 \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, self::TEST_ENCRYPTION_HOOKS_USER2, OCP\PERMISSION_ALL); diff --git a/apps/files_encryption/tests/keymanager.php b/apps/files_encryption/tests/keymanager.php index 6f32c50743c..0caf12e91a3 100644 --- a/apps/files_encryption/tests/keymanager.php +++ b/apps/files_encryption/tests/keymanager.php @@ -250,6 +250,10 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase { * dummy class to access protected methods of \OCA\Encryption\Keymanager for testing */ class TestProtectedKeymanagerMethods extends \OCA\Encryption\Keymanager { + + /** + * @param string $sharekey + */ public static function testGetFilenameFromShareKey($sharekey) { return self::getFilenameFromShareKey($sharekey); } diff --git a/apps/files_encryption/tests/share.php b/apps/files_encryption/tests/share.php index acf408a07f0..46a21dd55cd 100755 --- a/apps/files_encryption/tests/share.php +++ b/apps/files_encryption/tests/share.php @@ -61,7 +61,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { \OC_User::useBackend('database'); // enable resharing - \OC_Appconfig::setValue('core', 'shareapi_allow_resharing', 'yes'); + \OC::$server->getAppConfig()->setValue('core', 'shareapi_allow_resharing', 'yes'); // clear share hooks \OC_Hook::clear('OCP\\Share'); @@ -150,7 +150,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename); // check if we have a valid file info - $this->assertTrue(is_array($fileInfo)); + $this->assertTrue($fileInfo instanceof \OC\Files\FileInfo); // check if the unencrypted file size is stored $this->assertGreaterThan(0, $fileInfo['unencrypted_size']); @@ -310,7 +310,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files' . $this->folder1); // check if we have a valid file info - $this->assertTrue(is_array($fileInfo)); + $this->assertTrue($fileInfo instanceof \OC\Files\FileInfo); // re-enable the file proxy \OC_FileProxy::$enabled = $proxyStatus; @@ -388,7 +388,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { . $this->subfolder); // check if we have a valid file info - $this->assertTrue(is_array($fileInfoSubFolder)); + $this->assertTrue($fileInfoSubFolder instanceof \OC\Files\FileInfo); // re-enable the file proxy \OC_FileProxy::$enabled = $proxyStatus; @@ -422,7 +422,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { . $this->subsubfolder . '/' . $this->filename); // check if we have fileInfos - $this->assertTrue(is_array($fileInfo)); + $this->assertTrue($fileInfo instanceof \OC\Files\FileInfo); // share the file with user3 \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4, OCP\PERMISSION_ALL); @@ -517,7 +517,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename); // check if we have a valid file info - $this->assertTrue(is_array($fileInfo)); + $this->assertTrue($fileInfo instanceof \OC\Files\FileInfo); // check if the unencrypted file size is stored $this->assertGreaterThan(0, $fileInfo['unencrypted_size']); @@ -531,7 +531,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { // login as admin \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1); - $publicShareKeyId = \OC_Appconfig::getValue('files_encryption', 'publicShareKeyId'); + $publicShareKeyId = \OC::$server->getAppConfig()->getValue('files_encryption', 'publicShareKeyId'); // check if share key for public exists $this->assertTrue($this->view->file_exists( @@ -595,7 +595,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename); // check if we have a valid file info - $this->assertTrue(is_array($fileInfo)); + $this->assertTrue($fileInfo instanceof \OC\Files\FileInfo); // check if the unencrypted file size is stored $this->assertGreaterThan(0, $fileInfo['unencrypted_size']); @@ -662,7 +662,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1); \OCA\Encryption\Helper::adminEnableRecovery(null, 'test123'); - $recoveryKeyId = OC_Appconfig::getValue('files_encryption', 'recoveryKeyId'); + $recoveryKeyId = \OC::$server->getAppConfig()->getValue('files_encryption', 'recoveryKeyId'); // login as admin \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1); @@ -755,7 +755,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { $this->assertTrue(\OCA\Encryption\Helper::adminEnableRecovery(null, 'test123')); $this->assertTrue(\OCA\Encryption\Helper::adminDisableRecovery('test123')); - $this->assertEquals(0, \OC_Appconfig::getValue('files_encryption', 'recoveryAdminEnabled')); + $this->assertEquals(0, \OC::$server->getAppConfig()->getValue('files_encryption', 'recoveryAdminEnabled')); } /** @@ -769,7 +769,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { $result = \OCA\Encryption\Helper::adminEnableRecovery(null, 'test123'); $this->assertTrue($result); - $recoveryKeyId = OC_Appconfig::getValue('files_encryption', 'recoveryKeyId'); + $recoveryKeyId = \OC::$server->getAppConfig()->getValue('files_encryption', 'recoveryKeyId'); // login as user2 \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2); @@ -863,7 +863,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { $this->assertTrue($util->setRecoveryForUser(0)); \OCA\Encryption\Helper::adminDisableRecovery('test123'); - $this->assertEquals(0, \OC_Appconfig::getValue('files_encryption', 'recoveryAdminEnabled')); + $this->assertEquals(0, \OC::$server->getAppConfig()->getValue('files_encryption', 'recoveryAdminEnabled')); } /** @@ -888,7 +888,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename); // check if we have a valid file info - $this->assertTrue(is_array($fileInfo)); + $this->assertTrue($fileInfo instanceof \OC\Files\FileInfo); // check if the unencrypted file size is stored $this->assertGreaterThan(0, $fileInfo['unencrypted_size']); diff --git a/apps/files_encryption/tests/util.php b/apps/files_encryption/tests/util.php index 97e3c518dac..f70e30c4d73 100755 --- a/apps/files_encryption/tests/util.php +++ b/apps/files_encryption/tests/util.php @@ -64,6 +64,8 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { function setUp() { + // login user + \Test_Encryption_Util::loginHelper(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1); \OC_User::setUserId(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1); $this->userId = \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1; $this->pass = \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1; @@ -328,7 +330,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { $fileInfoUnencrypted = $this->view->getFileInfo($this->userId . '/files/' . $filename); - $this->assertTrue(is_array($fileInfoUnencrypted)); + $this->assertTrue($fileInfoUnencrypted instanceof \OC\Files\FileInfo); // enable file encryption again \OC_App::enable('files_encryption'); @@ -338,7 +340,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { $fileInfoEncrypted = $this->view->getFileInfo($this->userId . '/files/' . $filename); - $this->assertTrue(is_array($fileInfoEncrypted)); + $this->assertTrue($fileInfoEncrypted instanceof \OC\Files\FileInfo); // check if mtime and etags unchanged $this->assertEquals($fileInfoEncrypted['mtime'], $fileInfoUnencrypted['mtime']); @@ -357,23 +359,98 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { $fileInfoEncrypted = $this->view->getFileInfo($this->userId . '/files/' . $filename); - $this->assertTrue(is_array($fileInfoEncrypted)); + $this->assertTrue($fileInfoEncrypted instanceof \OC\Files\FileInfo); + $this->assertEquals($fileInfoEncrypted['encrypted'], 1); - // encrypt all unencrypted files - $util->decryptAll('/' . $this->userId . '/' . 'files'); + // decrypt all encrypted files + $result = $util->decryptAll('/' . $this->userId . '/' . 'files'); + + $this->assertTrue($result); $fileInfoUnencrypted = $this->view->getFileInfo($this->userId . '/files/' . $filename); - $this->assertTrue(is_array($fileInfoUnencrypted)); + $this->assertTrue($fileInfoUnencrypted instanceof \OC\Files\FileInfo); // check if mtime and etags unchanged $this->assertEquals($fileInfoEncrypted['mtime'], $fileInfoUnencrypted['mtime']); $this->assertEquals($fileInfoEncrypted['etag'], $fileInfoUnencrypted['etag']); + // file should no longer be encrypted + $this->assertEquals(0, $fileInfoUnencrypted['encrypted']); $this->view->unlink($this->userId . '/files/' . $filename); } + function testDescryptAllWithBrokenFiles() { + + $file1 = "/decryptAll1" . uniqid() . ".txt"; + $file2 = "/decryptAll2" . uniqid() . ".txt"; + + $util = new Encryption\Util($this->view, $this->userId); + + $this->view->file_put_contents($this->userId . '/files/' . $file1, $this->dataShort); + $this->view->file_put_contents($this->userId . '/files/' . $file2, $this->dataShort); + + $fileInfoEncrypted1 = $this->view->getFileInfo($this->userId . '/files/' . $file1); + $fileInfoEncrypted2 = $this->view->getFileInfo($this->userId . '/files/' . $file2); + + $this->assertTrue($fileInfoEncrypted1 instanceof \OC\Files\FileInfo); + $this->assertTrue($fileInfoEncrypted2 instanceof \OC\Files\FileInfo); + $this->assertEquals($fileInfoEncrypted1['encrypted'], 1); + $this->assertEquals($fileInfoEncrypted2['encrypted'], 1); + + // rename keyfile for file1 so that the decryption for file1 fails + // Expected behaviour: decryptAll() returns false, file2 gets decrypted anyway + $this->view->rename($this->userId . '/files_encryption/keyfiles/' . $file1 . '.key', + $this->userId . '/files_encryption/keyfiles/' . $file1 . '.key.moved'); + + // decrypt all encrypted files + $result = $util->decryptAll('/' . $this->userId . '/' . 'files'); + + $this->assertFalse($result); + + $fileInfoUnencrypted1 = $this->view->getFileInfo($this->userId . '/files/' . $file1); + $fileInfoUnencrypted2 = $this->view->getFileInfo($this->userId . '/files/' . $file2); + + $this->assertTrue($fileInfoUnencrypted1 instanceof \OC\Files\FileInfo); + $this->assertTrue($fileInfoUnencrypted2 instanceof \OC\Files\FileInfo); + + // file1 should be still encrypted; file2 should be decrypted + $this->assertEquals(1, $fileInfoUnencrypted1['encrypted']); + $this->assertEquals(0, $fileInfoUnencrypted2['encrypted']); + + // keyfiles and share keys should still exist + $this->assertTrue($this->view->is_dir($this->userId . '/files_encryption/keyfiles/')); + $this->assertTrue($this->view->is_dir($this->userId . '/files_encryption/share-keys/')); + + // rename the keyfile for file1 back + $this->view->rename($this->userId . '/files_encryption/keyfiles/' . $file1 . '.key.moved', + $this->userId . '/files_encryption/keyfiles/' . $file1 . '.key'); + + // try again to decrypt all encrypted files + $result = $util->decryptAll('/' . $this->userId . '/' . 'files'); + + $this->assertTrue($result); + + $fileInfoUnencrypted1 = $this->view->getFileInfo($this->userId . '/files/' . $file1); + $fileInfoUnencrypted2 = $this->view->getFileInfo($this->userId . '/files/' . $file2); + + $this->assertTrue($fileInfoUnencrypted1 instanceof \OC\Files\FileInfo); + $this->assertTrue($fileInfoUnencrypted2 instanceof \OC\Files\FileInfo); + + // now both files should be decrypted + $this->assertEquals(0, $fileInfoUnencrypted1['encrypted']); + $this->assertEquals(0, $fileInfoUnencrypted2['encrypted']); + + // keyfiles and share keys should be deleted + $this->assertFalse($this->view->is_dir($this->userId . '/files_encryption/keyfiles/')); + $this->assertFalse($this->view->is_dir($this->userId . '/files_encryption/share-keys/')); + + $this->view->unlink($this->userId . '/files/' . $file1); + $this->view->unlink($this->userId . '/files/' . $file2); + + } + /** * @large */ @@ -461,7 +538,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { * helper function to set migration status to the right value * to be able to test the migration path * - * @param $status needed migration status for test + * @param integer $status needed migration status for test * @param $user for which user the status should be set * @return boolean */ diff --git a/apps/files_external/ajax/addRootCertificate.php b/apps/files_external/ajax/addRootCertificate.php index ae349bfcd3a..fcd3a617ada 100644 --- a/apps/files_external/ajax/addRootCertificate.php +++ b/apps/files_external/ajax/addRootCertificate.php @@ -4,7 +4,7 @@ OCP\JSON::checkAppEnabled('files_external'); OCP\JSON::callCheck(); if ( ! ($filename = $_FILES['rootcert_import']['name']) ) { - header("Location: settings/personal.php"); + header('Location:' . OCP\Util::linkToRoute( "settings_personal" )); exit; } diff --git a/apps/files_external/lib/amazons3.php b/apps/files_external/lib/amazons3.php index 00baacd488c..06ccd5d16fa 100644 --- a/apps/files_external/lib/amazons3.php +++ b/apps/files_external/lib/amazons3.php @@ -54,6 +54,9 @@ class AmazonS3 extends \OC\Files\Storage\Common { */ private $timeout = 15; + /** + * @param string $path + */ private function normalizePath($path) { $path = trim($path, '/'); diff --git a/apps/files_external/lib/config.php b/apps/files_external/lib/config.php index 01d588b3721..b2109e5eacd 100755 --- a/apps/files_external/lib/config.php +++ b/apps/files_external/lib/config.php @@ -35,7 +35,7 @@ class OC_Mount_Config { * 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 + * @return string */ public static function getBackends() { @@ -61,7 +61,7 @@ class OC_Mount_Config { 'configuration' => array( 'configured' => '#configured', 'app_key' => 'App key', - 'app_secret' => 'App secret', + 'app_secret' => '*App secret', 'token' => '#token', 'token_secret' => '#token_secret'), 'custom' => 'dropbox'); @@ -69,7 +69,7 @@ class OC_Mount_Config { if(OC_Mount_Config::checkphpftp()) $backends['\OC\Files\Storage\FTP']=array( 'backend' => 'FTP', 'configuration' => array( - 'host' => 'URL', + 'host' => 'Hostname', 'user' => 'Username', 'password' => '*Password', 'root' => '&Root', @@ -80,7 +80,7 @@ class OC_Mount_Config { 'configuration' => array( 'configured' => '#configured', 'client_id' => 'Client ID', - 'client_secret' => 'Client secret', + 'client_secret' => '*Client secret', 'token' => '#token'), 'custom' => 'google'); @@ -263,13 +263,13 @@ class OC_Mount_Config { /** * Add a mount point to the filesystem - * @param string Mount point - * @param string Backend class + * @param string $mountPoint Mount point + * @param string $class Backend class * @param array Backend parameters for the class - * @param string MOUNT_TYPE_GROUP | MOUNT_TYPE_USER - * @param string User or group to apply mount to + * @param string $mountType MOUNT_TYPE_GROUP | MOUNT_TYPE_USER + * @param string $applicable User or group to apply mount to * @param bool Personal or system mount point i.e. is this being called from the personal or admin page - * @return bool + * @return boolean */ public static function addMountPoint($mountPoint, $class, @@ -343,7 +343,7 @@ class OC_Mount_Config { /** * Read the mount points in the config file into an array - * @param bool Personal or system config file + * @param boolean $isPersonal Personal or system config file * @return array */ private static function readData($isPersonal) { @@ -352,9 +352,8 @@ class OC_Mount_Config { $phpFile = OC_User::getHome(OCP\User::getUser()).'/mount.php'; $jsonFile = OC_User::getHome(OCP\User::getUser()).'/mount.json'; } else { - $datadir = \OC_Config::getValue("datadirectory", \OC::$SERVERROOT . "/data"); $phpFile = OC::$SERVERROOT.'/config/mount.php'; - $jsonFile = $datadir . '/mount.json'; + $jsonFile = \OC_Config::getValue("mount_file", \OC::$SERVERROOT . "/data/mount.json"); } if (is_file($jsonFile)) { $mountPoints = json_decode(file_get_contents($jsonFile), true); @@ -374,13 +373,13 @@ class OC_Mount_Config { * Write the mount points to the config file * @param bool Personal or system config file * @param array Mount points + * @param boolean $isPersonal */ private static function writeData($isPersonal, $data) { if ($isPersonal) { $file = OC_User::getHome(OCP\User::getUser()).'/mount.json'; } else { - $datadir = \OC_Config::getValue("datadirectory", \OC::$SERVERROOT . "/data"); - $file = $datadir . '/mount.json'; + $file = \OC_Config::getValue("mount_file", \OC::$SERVERROOT . "/data/mount.json"); } $content = json_encode($data); @file_put_contents($file, $content); diff --git a/apps/files_external/lib/dropbox.php b/apps/files_external/lib/dropbox.php index f7d8d98cf03..0214e18020c 100755 --- a/apps/files_external/lib/dropbox.php +++ b/apps/files_external/lib/dropbox.php @@ -50,6 +50,9 @@ class Dropbox extends \OC\Files\Storage\Common { } } + /** + * @param string $path + */ private function deleteMetaData($path) { $path = $this->root.$path; if (isset($this->metaData[$path])) { @@ -61,7 +64,7 @@ class Dropbox extends \OC\Files\Storage\Common { /** * @brief Returns the path's metadata - * @param $path path for which to return the metadata + * @param string $path path for which to return the metadata * @param $list if true, also return the directory's contents * @return directory contents if $list is true, file metadata if $list is * false, null if the file doesn't exist or "false" if the operation failed diff --git a/apps/files_external/lib/google.php b/apps/files_external/lib/google.php index 426caf008ec..35457f68528 100644 --- a/apps/files_external/lib/google.php +++ b/apps/files_external/lib/google.php @@ -67,7 +67,7 @@ class Google extends \OC\Files\Storage\Common { /** * Get the Google_DriveFile object for the specified path * @param string $path - * @return Google_DriveFile + * @return string */ private function getDriveFile($path) { // Remove leading and trailing slashes @@ -524,6 +524,7 @@ class Google extends \OC\Files\Storage\Common { } public function hasUpdated($path, $time) { + $appConfig = \OC::$server->getAppConfig(); if ($this->is_file($path)) { return parent::hasUpdated($path, $time); } else { @@ -533,7 +534,7 @@ class Google extends \OC\Files\Storage\Common { if ($folder) { $result = false; $folderId = $folder->getId(); - $startChangeId = \OC_Appconfig::getValue('files_external', $this->getId().'cId'); + $startChangeId = $appConfig->getValue('files_external', $this->getId().'cId'); $params = array( 'includeDeleted' => true, 'includeSubscribed' => true, @@ -578,7 +579,7 @@ class Google extends \OC\Files\Storage\Common { break; } } - \OC_Appconfig::setValue('files_external', $this->getId().'cId', $largestChangeId); + $appConfig->setValue('files_external', $this->getId().'cId', $largestChangeId); return $result; } } diff --git a/apps/files_external/lib/irods.php b/apps/files_external/lib/irods.php index 6d4f66e856e..7a7e900fbf0 100644 --- a/apps/files_external/lib/irods.php +++ b/apps/files_external/lib/irods.php @@ -134,6 +134,7 @@ class iRODS extends \OC\Files\Storage\StreamWrapper{ /** * get the best guess for the modification time of an iRODS collection + * @param string $path */ private function collectionMTime($path) { $dh = $this->opendir($path); diff --git a/apps/files_external/lib/sftp.php b/apps/files_external/lib/sftp.php index cd8a0e78864..a0816e2870d 100644 --- a/apps/files_external/lib/sftp.php +++ b/apps/files_external/lib/sftp.php @@ -75,6 +75,9 @@ class SFTP extends \OC\Files\Storage\Common { return 'sftp::' . $this->user . '@' . $this->host . '/' . $this->root; } + /** + * @param string $path + */ private function absPath($path) { return $this->root . $this->cleanPath($path); } @@ -277,6 +280,9 @@ class SFTP extends \OC\Files\Storage\Common { } } + /** + * @param string $path + */ public function constructUrl($path) { $url = 'sftp://'.$this->user.':'.$this->password.'@'.$this->host.$this->root.$path; return $url; diff --git a/apps/files_external/lib/streamwrapper.php b/apps/files_external/lib/streamwrapper.php index e484325e2fb..44bd9a0161a 100644 --- a/apps/files_external/lib/streamwrapper.php +++ b/apps/files_external/lib/streamwrapper.php @@ -9,6 +9,11 @@ namespace OC\Files\Storage; abstract class StreamWrapper extends Common { + + /** + * @param string $path + * @return string|null + */ abstract public function constructUrl($path); public function mkdir($path) { @@ -76,10 +81,17 @@ abstract class StreamWrapper extends Common { } } + /** + * @param string $path + * @param string $target + */ public function getFile($path, $target) { return copy($this->constructUrl($path), $target); } + /** + * @param string $target + */ public function uploadFile($path, $target) { return copy($path, $this->constructUrl($target)); } diff --git a/apps/files_external/lib/swift.php b/apps/files_external/lib/swift.php index b615d24ce76..7a56fcfc8b7 100644 --- a/apps/files_external/lib/swift.php +++ b/apps/files_external/lib/swift.php @@ -52,6 +52,9 @@ class Swift extends \OC\Files\Storage\Common { */ private static $tmpFiles = array(); + /** + * @param string $path + */ private function normalizePath($path) { $path = trim($path, '/'); @@ -62,6 +65,9 @@ class Swift extends \OC\Files\Storage\Common { return $path; } + /** + * @param string $path + */ private function doesObjectExist($path) { try { $object = $this->container->DataObject($path); diff --git a/apps/files_external/lib/webdav.php b/apps/files_external/lib/webdav.php index f6f4cb16e87..9afe73aebd7 100644 --- a/apps/files_external/lib/webdav.php +++ b/apps/files_external/lib/webdav.php @@ -99,7 +99,9 @@ class DAV extends \OC\Files\Storage\Common{ public function rmdir($path) { $this->init(); - $path=$this->cleanPath($path); + $path=$this->cleanPath($path) . '/'; + // FIXME: some WebDAV impl return 403 when trying to DELETE + // a non-empty folder return $this->simpleResponse('DELETE', $path, null, 204); } @@ -107,7 +109,7 @@ class DAV extends \OC\Files\Storage\Common{ $this->init(); $path=$this->cleanPath($path); try { - $response=$this->client->propfind($path, array(), 1); + $response=$this->client->propfind($this->encodePath($path), array(), 1); $id=md5('webdav'.$this->root.$path); $content = array(); $files=array_keys($response); @@ -127,8 +129,11 @@ class DAV extends \OC\Files\Storage\Common{ $this->init(); $path=$this->cleanPath($path); try { - $response=$this->client->propfind($path, array('{DAV:}resourcetype')); - $responseType=$response["{DAV:}resourcetype"]->resourceType; + $response=$this->client->propfind($this->encodePath($path), array('{DAV:}resourcetype')); + $responseType = array(); + if (isset($response["{DAV:}resourcetype"])) { + $responseType=$response["{DAV:}resourcetype"]->resourceType; + } return (count($responseType)>0 and $responseType[0]=="{DAV:}collection")?'dir':'file'; } catch(\Exception $e) { error_log($e->getMessage()); @@ -141,7 +146,7 @@ class DAV extends \OC\Files\Storage\Common{ $this->init(); $path=$this->cleanPath($path); try { - $this->client->propfind($path, array('{DAV:}resourcetype')); + $this->client->propfind($this->encodePath($path), array('{DAV:}resourcetype')); return true;//no 404 exception } catch(\Exception $e) { return false; @@ -166,7 +171,7 @@ class DAV extends \OC\Files\Storage\Common{ $curl = curl_init(); $fp = fopen('php://temp', 'r+'); curl_setopt($curl, CURLOPT_USERPWD, $this->user.':'.$this->password); - curl_setopt($curl, CURLOPT_URL, $this->createBaseUri().str_replace(' ', '%20', $path)); + curl_setopt($curl, CURLOPT_URL, $this->createBaseUri().$this->encodePath($path)); curl_setopt($curl, CURLOPT_FILE, $fp); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); if ($this->secure === true) { @@ -178,6 +183,10 @@ class DAV extends \OC\Files\Storage\Common{ } curl_exec ($curl); + $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); + if ($statusCode !== 200) { + \OCP\Util::writeLog("webdav client", 'curl GET ' . curl_getinfo($curl, CURLINFO_EFFECTIVE_URL) . ' returned status code ' . $statusCode, \OCP\Util::ERROR); + } curl_close ($curl); rewind($fp); return $fp; @@ -220,7 +229,7 @@ class DAV extends \OC\Files\Storage\Common{ $this->init(); $path=$this->cleanPath($path); try { - $response=$this->client->propfind($path, array('{DAV:}quota-available-bytes')); + $response=$this->client->propfind($this->encodePath($path), array('{DAV:}quota-available-bytes')); if (isset($response['{DAV:}quota-available-bytes'])) { return (int)$response['{DAV:}quota-available-bytes']; } else { @@ -240,13 +249,22 @@ class DAV extends \OC\Files\Storage\Common{ // if file exists, update the mtime, else create a new empty file if ($this->file_exists($path)) { - $this->client->proppatch($path, array('{DAV:}lastmodified' => $mtime)); + try { + $this->client->proppatch($this->encodePath($path), array('{DAV:}lastmodified' => $mtime)); + } + catch (\Sabre_DAV_Exception_NotImplemented $e) { + return false; + } } else { $this->file_put_contents($path, ''); } return true; } + /** + * @param string $path + * @param string $target + */ public function getFile($path, $target) { $this->init(); $source=$this->fopen($path, 'r'); @@ -272,13 +290,17 @@ class DAV extends \OC\Files\Storage\Common{ } } curl_exec ($curl); + $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); + if ($statusCode !== 200) { + \OCP\Util::writeLog("webdav client", 'curl GET ' . curl_getinfo($curl, CURLINFO_EFFECTIVE_URL) . ' returned status code ' . $statusCode, \OCP\Util::ERROR); + } curl_close ($curl); } public function rename($path1, $path2) { $this->init(); - $path1=$this->cleanPath($path1); - $path2=$this->createBaseUri().$this->cleanPath($path2); + $path1 = $this->encodePath($this->cleanPath($path1)); + $path2 = $this->createBaseUri().$this->encodePath($this->cleanPath($path2)); try { $this->client->request('MOVE', $path1, null, array('Destination'=>$path2)); return true; @@ -289,8 +311,8 @@ class DAV extends \OC\Files\Storage\Common{ public function copy($path1, $path2) { $this->init(); - $path1=$this->cleanPath($path1); - $path2=$this->createBaseUri().$this->cleanPath($path2); + $path1 = $this->encodePath($this->cleanPath($path1)); + $path2 = $this->createBaseUri().$this->encodePath($this->cleanPath($path2)); try { $this->client->request('COPY', $path1, null, array('Destination'=>$path2)); return true; @@ -303,7 +325,7 @@ class DAV extends \OC\Files\Storage\Common{ $this->init(); $path=$this->cleanPath($path); try { - $response=$this->client->propfind($path, array('{DAV:}getlastmodified', '{DAV:}getcontentlength')); + $response = $this->client->propfind($this->encodePath($path), array('{DAV:}getlastmodified', '{DAV:}getcontentlength')); return array( 'mtime'=>strtotime($response['{DAV:}getlastmodified']), 'size'=>(int)isset($response['{DAV:}getcontentlength']) ? $response['{DAV:}getcontentlength'] : 0, @@ -317,8 +339,11 @@ class DAV extends \OC\Files\Storage\Common{ $this->init(); $path=$this->cleanPath($path); try { - $response=$this->client->propfind($path, array('{DAV:}getcontenttype', '{DAV:}resourcetype')); - $responseType=$response["{DAV:}resourcetype"]->resourceType; + $response=$this->client->propfind($this->encodePath($path), array('{DAV:}getcontenttype', '{DAV:}resourcetype')); + $responseType = array(); + if (isset($response["{DAV:}resourcetype"])) { + $responseType=$response["{DAV:}resourcetype"]->resourceType; + } $type=(count($responseType)>0 and $responseType[0]=="{DAV:}collection")?'dir':'file'; if ($type=='dir') { return 'httpd/unix-directory'; @@ -332,16 +357,34 @@ class DAV extends \OC\Files\Storage\Common{ } } + /** + * @param string $path + */ public function cleanPath($path) { $path = \OC\Files\Filesystem::normalizePath($path); // remove leading slash return substr($path, 1); } + /** + * URL encodes the given path but keeps the slashes + * @param string $path to encode + * @return string encoded path + */ + private function encodePath($path) { + // slashes need to stay + return str_replace('%2F', '/', rawurlencode($path)); + } + + /** + * @param string $method + * @param string $path + * @param integer $expected + */ private function simpleResponse($method, $path, $body, $expected) { $path=$this->cleanPath($path); try { - $response=$this->client->request($method, $path, $body); + $response=$this->client->request($method, $this->encodePath($path), $body); return $response['statusCode']==$expected; } catch(\Exception $e) { return false; diff --git a/apps/files_external/tests/config.php b/apps/files_external/tests/config.php index e296bfcb5b2..767c0adf58e 100644 --- a/apps/files_external/tests/config.php +++ b/apps/files_external/tests/config.php @@ -21,7 +21,11 @@ return array( 'host'=>'localhost', 'user'=>'test', 'password'=>'test', - 'root'=>'/owncloud/files/webdav.php', + 'root'=>'', + // wait delay in seconds after write operations + // (only in tests) + // set to higher value for lighttpd webdav + 'wait'=> 0 ), 'owncloud'=>array( 'run'=>true, diff --git a/apps/files_external/tests/webdav.php b/apps/files_external/tests/webdav.php index 1f9b767eca6..74e905ccc89 100644 --- a/apps/files_external/tests/webdav.php +++ b/apps/files_external/tests/webdav.php @@ -18,6 +18,9 @@ class DAV extends Storage { if ( ! is_array($this->config) or ! isset($this->config['webdav']) or ! $this->config['webdav']['run']) { $this->markTestSkipped('WebDAV backend not configured'); } + if (isset($this->config['webdav']['wait'])) { + $this->waitDelay = $this->config['webdav']['wait']; + } $this->config['webdav']['root'] .= '/' . $id; //make sure we have an new empty folder to work in $this->instance = new \OC\Files\Storage\DAV($this->config['webdav']); $this->instance->mkdir('/'); diff --git a/apps/files_sharing/ajax/publicpreview.php b/apps/files_sharing/ajax/publicpreview.php index a52f522afac..d12d212a2e6 100644 --- a/apps/files_sharing/ajax/publicpreview.php +++ b/apps/files_sharing/ajax/publicpreview.php @@ -11,7 +11,7 @@ if(!\OC_App::isEnabled('files_sharing')){ \OC_User::setIncognitoMode(true); -$file = array_key_exists('file', $_GET) ? (string) urldecode($_GET['file']) : ''; +$file = array_key_exists('file', $_GET) ? (string) $_GET['file'] : ''; $maxX = array_key_exists('x', $_GET) ? (int) $_GET['x'] : '36'; $maxY = array_key_exists('y', $_GET) ? (int) $_GET['y'] : '36'; $scalingUp = array_key_exists('scalingup', $_GET) ? (bool) $_GET['scalingup'] : true; diff --git a/apps/files_sharing/css/public.css b/apps/files_sharing/css/public.css index 21f0c82b829..5246a4b2fec 100644 --- a/apps/files_sharing/css/public.css +++ b/apps/files_sharing/css/public.css @@ -66,7 +66,8 @@ p.info a { margin:0 auto; } -#imgframe img { +#imgframe img, +#imgframe video { max-height:100%; max-width:100%; } @@ -76,6 +77,8 @@ p.info a { margin-top: 10%; } + + thead { padding-left: 0 !important; /* fixes multiselect bar offset on shared page */ } diff --git a/apps/files_sharing/js/public.js b/apps/files_sharing/js/public.js index c1b7eee3fb7..06c168969de 100644 --- a/apps/files_sharing/js/public.js +++ b/apps/files_sharing/js/public.js @@ -1,3 +1,15 @@ +/* + * Copyright (c) 2014 + * + * This file is licensed under the Affero General Public License version 3 + * or later. + * + * See the COPYING-README file. + * + */ + +/* global OC, FileList, FileActions */ + // Override download path to files_sharing/public.php function fileDownloadPath(dir, file) { var url = $('#downloadURL').val(); @@ -28,12 +40,20 @@ $(document).ready(function() { // override since the format is different FileList.getDownloadUrl = function(filename, dir) { - // we use this because we need the service and token attributes - var tr = FileList.findFileEl(filename); - if (tr.length > 0) { - return $(tr).find('a.name').attr('href') + '&download'; + if ($.isArray(filename)) { + filename = JSON.stringify(filename); + } + var path = dir || FileList.getCurrentDirectory(); + var params = { + service: 'files', + t: $('#sharingToken').val(), + path: path, + download: null + }; + if (filename) { + params.files = filename; } - return null; + return OC.filePath('', '', 'public.php') + '?' + OC.buildQueryString(params); }; } diff --git a/apps/files_sharing/lib/api.php b/apps/files_sharing/lib/api.php index 061e60ad8ed..19a2d22b068 100644 --- a/apps/files_sharing/lib/api.php +++ b/apps/files_sharing/lib/api.php @@ -218,7 +218,7 @@ class Api { //allow password protection $shareWith = isset($_POST['password']) ? $_POST['password'] : null; //check public link share - $publicUploadEnabled = \OC_Appconfig::getValue('core', 'shareapi_allow_public_upload', 'yes'); + $publicUploadEnabled = \OC::$server->getAppConfig()->getValue('core', 'shareapi_allow_public_upload', 'yes'); if(isset($_POST['publicUpload']) && $publicUploadEnabled !== 'yes') { return new \OC_OCS_Result(null, 403, "public upload disabled by the administrator"); } @@ -317,7 +317,7 @@ class Api { $shareType = $share['share_type']; $permissions = isset($params['_put']['permissions']) ? (int)$params['_put']['permissions'] : null; - $publicUploadStatus = \OC_Appconfig::getValue('core', 'shareapi_allow_public_upload', 'yes'); + $publicUploadStatus = \OC::$server->getAppConfig()->getValue('core', 'shareapi_allow_public_upload', 'yes'); $publicUploadEnabled = ($publicUploadStatus === 'yes') ? true : false; @@ -356,7 +356,7 @@ class Api { */ private static function updatePublicUpload($share, $params) { - $publicUploadEnabled = \OC_Appconfig::getValue('core', 'shareapi_allow_public_upload', 'yes'); + $publicUploadEnabled = \OC::$server->getAppConfig()->getValue('core', 'shareapi_allow_public_upload', 'yes'); if($publicUploadEnabled !== 'yes') { return new \OC_OCS_Result(null, 403, "public upload disabled by the administrator"); } diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php index 1b102f9e5f8..aadc54e4a7f 100644 --- a/apps/files_sharing/lib/cache.php +++ b/apps/files_sharing/lib/cache.php @@ -32,6 +32,9 @@ class Shared_Cache extends Cache { private $storage; private $files = array(); + /** + * @param \OC\Files\Storage\Shared $storage + */ public function __construct($storage) { $this->storage = $storage; } @@ -393,7 +396,7 @@ class Shared_Cache extends Cache { * use the one with the highest id gives the best result with the background scanner, since that is most * likely the folder where we stopped scanning previously * - * @return string|bool the path of the folder or false when no folder matched + * @return boolean the path of the folder or false when no folder matched */ public function getIncomplete() { return false; diff --git a/apps/files_sharing/lib/permissions.php b/apps/files_sharing/lib/permissions.php index 1dc53428a7f..31b7ac361ae 100644 --- a/apps/files_sharing/lib/permissions.php +++ b/apps/files_sharing/lib/permissions.php @@ -42,6 +42,10 @@ class Shared_Permissions extends Permissions { } } + /** + * @param integer $fileId + * @param string $user + */ private function getFile($fileId, $user) { if ($fileId == -1) { return \OCP\PERMISSION_READ; diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index afe5dffdebd..b922654e5ec 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -41,6 +41,7 @@ class Shared extends \OC\Files\Storage\Common { /** * @brief Get the source file path, permissions, and owner for a shared file * @param string Shared target file path + * @param string $target * @return Returns array with the keys path, permissions, and owner or false if not found */ public function getFile($target) { @@ -64,6 +65,7 @@ class Shared extends \OC\Files\Storage\Common { /** * @brief Get the source file path for a shared file * @param string Shared target file path + * @param string $target * @return string source file path or false if not found */ public function getSourcePath($target) { diff --git a/apps/files_sharing/public.php b/apps/files_sharing/public.php index f03ac7205a3..e7a5f5024b8 100644 --- a/apps/files_sharing/public.php +++ b/apps/files_sharing/public.php @@ -2,7 +2,9 @@ // Load other apps for file previews OC_App::loadApps(); -if (\OC_Appconfig::getValue('core', 'shareapi_allow_links', 'yes') !== 'yes') { +$appConfig = \OC::$server->getAppConfig(); + +if ($appConfig->getValue('core', 'shareapi_allow_links', 'yes') !== 'yes') { header('HTTP/1.0 404 Not Found'); $tmpl = new OCP\Template('', '404', 'guest'); $tmpl->printPage(); @@ -151,7 +153,7 @@ if (isset($path)) { $tmpl->assign('dirToken', $linkItem['token']); $tmpl->assign('sharingToken', $token); $allowPublicUploadEnabled = (bool) ($linkItem['permissions'] & OCP\PERMISSION_CREATE); - if (OC_Appconfig::getValue('core', 'shareapi_allow_public_upload', 'yes') === 'no') { + if ($appConfig->getValue('core', 'shareapi_allow_public_upload', 'yes') === 'no') { $allowPublicUploadEnabled = false; } if ($linkItem['item_type'] !== 'folder') { diff --git a/apps/files_sharing/templates/public.php b/apps/files_sharing/templates/public.php index 3ddaf4446df..3eb84ce1672 100644 --- a/apps/files_sharing/templates/public.php +++ b/apps/files_sharing/templates/public.php @@ -35,7 +35,7 @@ <?php else: ?> <div id="imgframe"> <?php $size = \OC\Preview::isMimeSupported($_['mimetype']) ? 500 : 128 ?> - <img src="<?php p(OCP\Util::linkToRoute( 'core_ajax_public_preview', array('x' => $size, 'y' => $size, 'file' => urlencode($_['directory_path']), 't' => $_['dirToken']))); ?>" class="publicpreview"/> + <img src="<?php p(OCP\Util::linkToRoute( 'core_ajax_public_preview', array('x' => $size, 'y' => $size, 'file' => $_['directory_path'], 't' => $_['dirToken']))); ?>" class="publicpreview"/> </div> <?php endif; ?> <div class="directDownload"> diff --git a/apps/files_sharing/tests/watcher.php b/apps/files_sharing/tests/watcher.php index 1a9a54cbcf8..5ab716e829f 100644 --- a/apps/files_sharing/tests/watcher.php +++ b/apps/files_sharing/tests/watcher.php @@ -145,6 +145,7 @@ class Test_Files_Sharing_Watcher extends Test_Files_Sharing_Base { /** * Returns the sizes of the path and its parent dirs in a hash * where the key is the path and the value is the size. + * @param string $path */ function getOwnerDirSizes($path) { $result = array(); diff --git a/apps/files_trashbin/ajax/delete.php b/apps/files_trashbin/ajax/delete.php index 75d481768ad..ebabc5bc7a2 100644 --- a/apps/files_trashbin/ajax/delete.php +++ b/apps/files_trashbin/ajax/delete.php @@ -2,42 +2,38 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::callCheck(); +$folder = isset($_POST['dir']) ? $_POST['dir'] : '/'; // "empty trash" command if (isset($_POST['allfiles']) and $_POST['allfiles'] === 'true'){ $deleteAll = true; - $folder = isset($_POST['dir']) ? $_POST['dir'] : '/'; if ($folder === '/' || $folder === '') { OCA\Files_Trashbin\Trashbin::deleteAll(); $list = array(); } else { - $dirname = dirname($folder); - if ( $dirname !== '/' && $dirname !== '.' ) { - $dirlisting = '1'; - } else { - $dirlisting = '0'; - } $list[] = $folder; + $folder = dirname($folder); } } else { $deleteAll = false; $files = $_POST['files']; - $dirlisting = $_POST['dirlisting']; $list = json_decode($files); } + +$folder = rtrim($folder, '/') . '/'; $error = array(); $success = array(); $i = 0; foreach ($list as $file) { - if ( $dirlisting === '0') { + if ($folder === '/') { $file = ltrim($file, '/'); $delimiter = strrpos($file, '.d'); $filename = substr($file, 0, $delimiter); $timestamp = substr($file, $delimiter+2); } else { - $filename = $file; + $filename = $folder . '/' . $file; $timestamp = null; } diff --git a/apps/files_trashbin/ajax/preview.php b/apps/files_trashbin/ajax/preview.php index 44738734b19..ce64d9ecc9f 100644 --- a/apps/files_trashbin/ajax/preview.php +++ b/apps/files_trashbin/ajax/preview.php @@ -11,7 +11,7 @@ if(!\OC_App::isEnabled('files_trashbin')){ exit; } -$file = array_key_exists('file', $_GET) ? (string) urldecode($_GET['file']) : ''; +$file = array_key_exists('file', $_GET) ? (string) $_GET['file'] : ''; $maxX = array_key_exists('x', $_GET) ? (int) $_GET['x'] : '44'; $maxY = array_key_exists('y', $_GET) ? (int) $_GET['y'] : '44'; $scalingUp = array_key_exists('scalingup', $_GET) ? (bool) $_GET['scalingup'] : true; diff --git a/apps/files_trashbin/ajax/undelete.php b/apps/files_trashbin/ajax/undelete.php index 876ad269a70..9c3ccba7ed8 100644 --- a/apps/files_trashbin/ajax/undelete.php +++ b/apps/files_trashbin/ajax/undelete.php @@ -4,15 +4,36 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::callCheck(); $files = $_POST['files']; -$dirlisting = $_POST['dirlisting']; -$list = json_decode($files); +$dir = '/'; +if (isset($_POST['dir'])) { + $dir = rtrim($_POST['dir'], '/'). '/'; +} +$allFiles = false; +if (isset($_POST['allfiles']) and $_POST['allfiles'] === 'true') { + $allFiles = true; + $list = array(); + $dirListing = true; + if ($dir === '' || $dir === '/') { + $dirListing = false; + } + foreach (OCA\Files_Trashbin\Helper::getTrashFiles($dir) as $file) { + $fileName = $file['name']; + if (!$dirListing) { + $fileName .= '.d' . $file['timestamp']; + } + $list[] = $fileName; + } +} else { + $list = json_decode($files); +} $error = array(); $success = array(); $i = 0; foreach ($list as $file) { - if ( $dirlisting === '0') { + $path = $dir . '/' . $file; + if ($dir === '/') { $file = ltrim($file, '/'); $delimiter = strrpos($file, '.d'); $filename = substr($file, 0, $delimiter); @@ -23,9 +44,9 @@ foreach ($list as $file) { $timestamp = null; } - if ( !OCA\Files_Trashbin\Trashbin::restore($file, $filename, $timestamp) ) { + if ( !OCA\Files_Trashbin\Trashbin::restore($path, $filename, $timestamp) ) { $error[] = $filename; - OC_Log::write('trashbin','can\'t restore ' . $filename, OC_Log::ERROR); + OC_Log::write('trashbin', 'can\'t restore ' . $filename, OC_Log::ERROR); } else { $success[$i]['filename'] = $file; $success[$i]['timestamp'] = $timestamp; diff --git a/apps/files_trashbin/js/trash.js b/apps/files_trashbin/js/trash.js index 46d8b56308c..6aade210505 100644 --- a/apps/files_trashbin/js/trash.js +++ b/apps/files_trashbin/js/trash.js @@ -1,5 +1,29 @@ +/* + * Copyright (c) 2014 + * + * This file is licensed under the Affero General Public License version 3 + * or later. + * + * See the COPYING-README file. + * + */ + +/* global OC, t, FileList, FileActions */ $(document).ready(function() { + function removeCallback(result) { + if (result.status !== 'success') { + OC.dialogs.alert(result.data.message, t('core', 'Error')); + } + + var files = result.data.success; + for (var i = 0; i < files.length; i++) { + FileList.findFileEl(OC.basename(files[i].filename)).remove(); + } + FileList.updateFileSummary(); + FileList.updateEmptyContent(); + enableActions(); + } if (typeof FileActions !== 'undefined') { FileActions.register('all', 'Restore', OC.PERMISSION_READ, OC.imagePath('core', 'actions/history'), function(filename) { @@ -7,22 +31,12 @@ $(document).ready(function() { var deleteAction = tr.children("td.date").children(".action.delete"); deleteAction.removeClass('delete-icon').addClass('progress-icon'); disableActions(); - $.post(OC.filePath('files_trashbin', 'ajax', 'undelete.php'), - {files: JSON.stringify([$('#dir').val() + '/' + filename]), dirlisting: tr.attr('data-dirlisting')}, - function(result) { - for (var i = 0; i < result.data.success.length; i++) { - var row = document.getElementById(result.data.success[i].filename); - row.parentNode.removeChild(row); - } - if (result.status !== 'success') { - OC.dialogs.alert(result.data.message, t('core', 'Error')); - } - enableActions(); - FileList.updateFileSummary(); - FileList.updateEmptyContent(); - } + $.post(OC.filePath('files_trashbin', 'ajax', 'undelete.php'), { + files: JSON.stringify([filename]), + dir: FileList.getCurrentDirectory() + }, + removeCallback ); - }); }; @@ -34,22 +48,12 @@ $(document).ready(function() { var deleteAction = tr.children("td.date").children(".action.delete"); deleteAction.removeClass('delete-icon').addClass('progress-icon'); disableActions(); - $.post(OC.filePath('files_trashbin', 'ajax', 'delete.php'), - {files: JSON.stringify([$('#dir').val() + '/' +filename]), dirlisting: tr.attr('data-dirlisting')}, - function(result) { - for (var i = 0; i < result.data.success.length; i++) { - var row = document.getElementById(result.data.success[i].filename); - row.parentNode.removeChild(row); - } - if (result.status !== 'success') { - OC.dialogs.alert(result.data.message, t('core', 'Error')); - } - enableActions(); - FileList.updateFileSummary(); - FileList.updateEmptyContent(); - } + $.post(OC.filePath('files_trashbin', 'ajax', 'delete.php'), { + files: JSON.stringify([filename]), + dir: FileList.getCurrentDirectory() + }, + removeCallback ); - }); // Sets the select_all checkbox behaviour : @@ -68,29 +72,45 @@ $(document).ready(function() { $('.undelete').click('click', function(event) { event.preventDefault(); - var files = getSelectedFiles('file'); - var fileslist = JSON.stringify(files); - var dirlisting = getSelectedFiles('dirlisting')[0]; + var allFiles = $('#select_all').is(':checked'); + var files = []; + var params = {}; disableActions(); - for (var i = 0; i < files.length; i++) { - var deleteAction = FileList.findFileEl(files[i]).children("td.date").children(".action.delete"); - deleteAction.removeClass('delete-icon').addClass('progress-icon'); + if (allFiles) { + FileList.showMask(); + params = { + allfiles: true, + dir: FileList.getCurrentDirectory() + }; + } + else { + files = getSelectedFiles('name'); + for (var i = 0; i < files.length; i++) { + var deleteAction = FileList.findFileEl(files[i]).children("td.date").children(".action.delete"); + deleteAction.removeClass('delete-icon').addClass('progress-icon'); + } + params = { + files: JSON.stringify(files), + dir: FileList.getCurrentDirectory() + }; } $.post(OC.filePath('files_trashbin', 'ajax', 'undelete.php'), - {files: fileslist, dirlisting: dirlisting}, - function(result) { - for (var i = 0; i < result.data.success.length; i++) { - var row = document.getElementById(result.data.success[i].filename); - row.parentNode.removeChild(row); - } + params, + function(result) { + if (allFiles) { if (result.status !== 'success') { OC.dialogs.alert(result.data.message, t('core', 'Error')); } + FileList.hideMask(); + // simply remove all files + FileList.update(''); enableActions(); - FileList.updateFileSummary(); - FileList.updateEmptyContent(); } + else { + removeCallback(result); + } + } ); }); @@ -101,17 +121,17 @@ $(document).ready(function() { var params = {}; if (allFiles) { params = { - allfiles: true, - dir: $('#dir').val() + allfiles: true, + dir: FileList.getCurrentDirectory() }; } else { - files = getSelectedFiles('file'); + files = getSelectedFiles('name'); params = { files: JSON.stringify(files), - dirlisting: getSelectedFiles('dirlisting')[0] + dir: FileList.getCurrentDirectory() }; - }; + } disableActions(); if (allFiles) { @@ -128,22 +148,17 @@ $(document).ready(function() { params, function(result) { if (allFiles) { + if (result.status !== 'success') { + OC.dialogs.alert(result.data.message, t('core', 'Error')); + } FileList.hideMask(); // simply remove all files - $('#fileList').empty(); + FileList.update(''); + enableActions(); } else { - for (var i = 0; i < result.data.success.length; i++) { - var row = document.getElementById(result.data.success[i].filename); - row.parentNode.removeChild(row); - } + removeCallback(result); } - if (result.status !== 'success') { - OC.dialogs.alert(result.data.message, t('core', 'Error')); - } - enableActions(); - FileList.updateFileSummary(); - FileList.updateEmptyContent(); } ); @@ -208,11 +223,9 @@ function getSelectedFiles(property){ var files=[]; elements.each(function(i,element){ var file={ - name:$(element).attr('data-filename'), - file:$('#dir').val() + "/" + $(element).attr('data-file'), + name:$(element).attr('data-file'), timestamp:$(element).attr('data-timestamp'), - type:$(element).attr('data-type'), - dirlisting:$(element).attr('data-dirlisting') + type:$(element).attr('data-type') }; if(property){ files.push(file[property]); diff --git a/apps/files_trashbin/lib/trashbin.php b/apps/files_trashbin/lib/trashbin.php index 7544980e071..bc77e9c1543 100644 --- a/apps/files_trashbin/lib/trashbin.php +++ b/apps/files_trashbin/lib/trashbin.php @@ -61,6 +61,11 @@ class Trashbin { } + /** + * @param string $owner + * @param integer $timestamp + * @param string $type + */ private static function copyFilesToOwner($sourcePath, $owner, $ownerPath, $timestamp, $type, $mime) { self::setUpTrash($owner); @@ -169,7 +174,7 @@ class Trashbin { * * @param $file_path path to original file * @param $filename of deleted file - * @param $timestamp when the file was deleted + * @param integer $timestamp when the file was deleted * * @return size of stored versions */ @@ -214,7 +219,7 @@ class Trashbin { * * @param $file_path path to original file * @param $filename of deleted file - * @param $timestamp when the file was deleted + * @param integer $timestamp when the file was deleted * * @return size of encryption keys */ @@ -406,7 +411,7 @@ class Trashbin { * @param \OC\Files\View $view file view * @param $file complete path to file * @param $filename name of file once it was deleted - * @param $uniqueFilename new file name to restore the file without overwriting existing files + * @param string $uniqueFilename new file name to restore the file without overwriting existing files * @param $location location if file * @param $timestamp deleteion time * @@ -460,7 +465,7 @@ class Trashbin { * @param \OC\Files\View $view * @param $file complete path to file * @param $filename name of file - * @param $uniqueFilename new file name to restore the file without overwriting existing files + * @param string $uniqueFilename new file name to restore the file without overwriting existing files * @param $location location of file * @param $timestamp deleteion time * @@ -621,6 +626,9 @@ class Trashbin { return $size; } + /** + * @param \OC\Files\View $view + */ private static function deleteVersions($view, $file, $filename, $timestamp) { $size = 0; if (\OCP\App::isEnabled('files_versions')) { @@ -643,6 +651,9 @@ class Trashbin { return $size; } + /** + * @param \OC\Files\View $view + */ private static function deleteEncryptionKeys($view, $file, $filename, $timestamp) { $size = 0; if (\OCP\App::isEnabled('files_encryption')) { @@ -713,7 +724,7 @@ class Trashbin { /** * calculate remaining free space for trash bin * - * @param $trashbinSize current size of the trash bin + * @param integer $trashbinSize current size of the trash bin * @return available free space for trash bin */ private static function calculateFreeSpace($trashbinSize) { @@ -722,7 +733,7 @@ class Trashbin { $quota = \OC_Preferences::getValue($user, 'files', 'quota'); $view = new \OC\Files\View('/' . $user); if ($quota === null || $quota === 'default') { - $quota = \OC_Appconfig::getValue('files', 'default_quota'); + $quota = \OC::$server->getAppConfig()->getValue('files', 'default_quota'); } if ($quota === null || $quota === 'none') { $quota = \OC\Files\Filesystem::free_space('/'); @@ -826,9 +837,9 @@ class Trashbin { /** * recursive copy to copy a whole directory * - * @param $source source path, relative to the users files directory - * @param $destination destination path relative to the users root directoy - * @param $view file view for the users root directory + * @param string $source source path, relative to the users files directory + * @param string $destination destination path relative to the users root directoy + * @param \OC\Files\View $view file view for the users root directory */ private static function copy_recursive($source, $destination, $view) { $size = 0; @@ -887,7 +898,7 @@ class Trashbin { * find unique extension for restored file if a file with the same name already exists * @param $location where the file should be restored * @param $filename name of the file - * @param $view filesystem view relative to users root directory + * @param \OC\Files\View $view filesystem view relative to users root directory * @return string with unique extension */ private static function getUniqueFilename($location, $filename, $view) { @@ -916,8 +927,8 @@ class Trashbin { /** * @brief get the size from a given root folder - * @param $view file view on the root folder - * @return size of the folder + * @param \OC\Files\View $view file view on the root folder + * @return integer size of the folder */ private static function calculateSize($view) { $root = \OCP\Config::getSystemValue('datadirectory') . $view->getAbsolutePath(''); @@ -996,6 +1007,6 @@ class Trashbin { } public static function preview_icon($path) { - return \OC_Helper::linkToRoute( 'core_ajax_trashbin_preview', array('x' => 36, 'y' => 36, 'file' => urlencode($path) )); + return \OC_Helper::linkToRoute( 'core_ajax_trashbin_preview', array('x' => 36, 'y' => 36, 'file' => $path )); } } diff --git a/apps/files_versions/lib/versions.php b/apps/files_versions/lib/versions.php index 328ed4305f4..2bd9c15bae4 100644 --- a/apps/files_versions/lib/versions.php +++ b/apps/files_versions/lib/versions.php @@ -336,7 +336,7 @@ class Storage { * @brief deletes used space for files versions in db if user was deleted * * @param type $uid id of deleted user - * @return result of db delete operation + * @return \OC_DB_StatementWrapper of db delete operation */ public static function deleteUser($uid) { $query = \OC_DB::prepare('DELETE FROM `*PREFIX*files_versions` WHERE `user`=?'); @@ -372,7 +372,7 @@ class Storage { /** * @brief returns all stored file versions from a given user - * @param $uid id to the user + * @param string $uid id of the user * @return array with contains two arrays 'all' which contains all versions sorted by age and 'by_file' which contains all versions sorted by filename */ private static function getAllVersions($uid) { @@ -420,8 +420,8 @@ class Storage { /** * @brief get list of files we want to expire - * @param int $currentTime timestamp of current time * @param array $versions list of versions + * @param integer $time * @return array containing the list of to deleted versions and the size of them */ protected static function getExpireList($time, $versions) { @@ -487,7 +487,7 @@ class Storage { $softQuota = true; $quota = \OC_Preferences::getValue($uid, 'files', 'quota'); if ( $quota === null || $quota === 'default') { - $quota = \OC_Appconfig::getValue('files', 'default_quota'); + $quota = \OC::$server->getAppConfig()->getValue('files', 'default_quota'); } if ( $quota === null || $quota === 'none' ) { $quota = \OC\Files\Filesystem::free_space('/'); diff --git a/apps/files_versions/tests/versions.php b/apps/files_versions/tests/versions.php index 25490aa1a04..9f15b86d981 100644 --- a/apps/files_versions/tests/versions.php +++ b/apps/files_versions/tests/versions.php @@ -181,6 +181,9 @@ class Test_Files_Versioning extends \PHPUnit_Framework_TestCase { // extend the original class to make it possible to test protected methods class VersionStorageToTest extends \OCA\Files_Versions\Storage { + /** + * @param integer $time + */ public function callProtectedGetExpireList($time, $versions) { return self::getExpireList($time, $versions); diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php index b619f62f296..b7e4023dd73 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -107,8 +107,8 @@ class Access extends LDAPUtility { /** * @brief checks wether the given attribute`s valua is probably a DN - * @param $attr the attribute in question - * @return if so true, otherwise false + * @param string $attr the attribute in question + * @return boolean if so true, otherwise false */ private function resemblesDN($attr) { $resemblingAttributes = array( @@ -164,6 +164,7 @@ class Access extends LDAPUtility { /** * gives back the database table for the query + * @param boolean $isUser */ private function getMapTable($isUser) { if($isUser) { @@ -175,7 +176,7 @@ class Access extends LDAPUtility { /** * @brief returns the LDAP DN for the given internal ownCloud name of the group - * @param $name the ownCloud name in question + * @param string $name the ownCloud name in question * @returns string with the LDAP DN on success, otherwise false * * returns the LDAP DN for the given internal ownCloud name of the group @@ -211,7 +212,7 @@ class Access extends LDAPUtility { /** * @brief returns the LDAP DN for the given internal ownCloud name * @param $name the ownCloud name in question - * @param $isUser is it a user? otherwise group + * @param boolean $isUser is it a user? otherwise group * @returns string with the LDAP DN on success, otherwise false * * returns the LDAP DN for the given internal ownCloud name @@ -417,6 +418,9 @@ class Access extends LDAPUtility { } + /** + * @param boolean $isUsers + */ private function ldap2ownCloudNames($ldapObjects, $isUsers) { if($isUsers) { $nameAttribute = $this->connection->ldapUserDisplayName; @@ -509,7 +513,7 @@ class Access extends LDAPUtility { /** * @brief creates a unique name for internal ownCloud use. * @param $name the display name of the object - * @param $isUser boolean, whether name should be created for a user (true) or a group (false) + * @param boolean $isUser whether name should be created for a user (true) or a group (false) * @returns string with with the name to use in ownCloud or false if unsuccessful */ private function createAltInternalOwnCloudName($name, $isUser) { @@ -545,6 +549,9 @@ class Access extends LDAPUtility { return $this->mappedComponents(true); } + /** + * @param boolean $isUsers + */ private function mappedComponents($isUsers) { $table = $this->getMapTable($isUsers); @@ -601,14 +608,26 @@ class Access extends LDAPUtility { return true; } + /** + * @param integer $limit + * @param integer $offset + */ public function fetchListOfUsers($filter, $attr, $limit = null, $offset = null) { return $this->fetchList($this->searchUsers($filter, $attr, $limit, $offset), (count($attr) > 1)); } + /** + * @param string $filter + * @param integer $limit + * @param integer $offset + */ public function fetchListOfGroups($filter, $attr, $limit = null, $offset = null) { return $this->fetchList($this->searchGroups($filter, $attr, $limit, $offset), (count($attr) > 1)); } + /** + * @param boolean $manyAttributes + */ private function fetchList($list, $manyAttributes) { if(is_array($list)) { if($manyAttributes) { @@ -626,6 +645,8 @@ class Access extends LDAPUtility { * @brief executes an LDAP search, optimized for Users * @param $filter the LDAP filter for the search * @param $attr optional, when a certain attribute shall be filtered out + * @param integer $limit + * @param integer $offset * @returns array with the search result * * Executes an LDAP search @@ -634,14 +655,19 @@ class Access extends LDAPUtility { return $this->search($filter, $this->connection->ldapBaseUsers, $attr, $limit, $offset); } + /** + * @param string $filter + */ public function countUsers($filter, $attr = array('dn'), $limit = null, $offset = null) { return $this->count($filter, $this->connection->ldapBaseGroups, $attr, $limit, $offset); } /** * @brief executes an LDAP search, optimized for Groups - * @param $filter the LDAP filter for the search + * @param string $filter the LDAP filter for the search * @param $attr optional, when a certain attribute shall be filtered out + * @param integer $limit + * @param integer $offset * @returns array with the search result * * Executes an LDAP search @@ -702,7 +728,7 @@ class Access extends LDAPUtility { * @param $limit maximum results to be counted * @param $offset a starting point * @param $pagedSearchOK whether a paged search has been executed - * @param $skipHandling required for paged search when cookies to + * @param boolean $skipHandling required for paged search when cookies to * prior results need to be gained * @returns array with the search result as first value and pagedSearchOK as * second | false if not successful @@ -736,7 +762,7 @@ class Access extends LDAPUtility { /** * @brief executes an LDAP search, but counts the results only - * @param $filter the LDAP filter for the search + * @param string $filter the LDAP filter for the search * @param $base an array containing the LDAP subtree(s) that shall be searched * @param $attr optional, array, one or more attributes that shall be * retrieved. Results will according to the order in the array. @@ -896,6 +922,17 @@ class Access extends LDAPUtility { } /** + * @brief escapes (user provided) parts for LDAP filter + * @param String $input, the provided value + * @returns the escaped string + */ + public function escapeFilterPart($input) { + $search = array('*', '\\', '(', ')'); + $replace = array('\\*', '\\\\', '\\(', '\\)'); + return str_replace($search, $replace, $input); + } + + /** * @brief combines the input filters with AND * @param $filters array, the filters to connect * @returns the combined filter @@ -920,7 +957,7 @@ class Access extends LDAPUtility { /** * @brief combines the input filters with given operator * @param $filters array, the filters to connect - * @param $operator either & or | + * @param string $operator either & or | * @returns the combined filter * * Combines Filter arguments with AND @@ -985,6 +1022,9 @@ class Access extends LDAPUtility { return $this->combineFilterWithOr($filter); } + /** + * @param string $password + */ public function areCredentialsValid($name, $password) { $name = $this->DNasBaseParameter($name); $testConnection = clone $this->connection; @@ -1173,7 +1213,7 @@ class Access extends LDAPUtility { /** * @brief check wether the most recent paged search was successful. It flushed the state var. Use it always after a possible paged search. - * @return true on success, null or false otherwise + * @return boolean|null true on success, null or false otherwise */ public function getPagedSearchResultState() { $result = $this->pagedSearchedSuccessful; diff --git a/apps/user_ldap/lib/configuration.php b/apps/user_ldap/lib/configuration.php index 93f044e3152..954d0501fad 100644 --- a/apps/user_ldap/lib/configuration.php +++ b/apps/user_ldap/lib/configuration.php @@ -78,6 +78,9 @@ class Configuration { 'lastJpegPhotoLookup' => null, ); + /** + * @param string $configPrefix + */ public function __construct($configPrefix, $autoread = true) { $this->configPrefix = $configPrefix; if($autoread) { @@ -106,7 +109,7 @@ class Configuration { * @param $config array that holds the config parameters in an associated * array * @param &$applied optional; array where the set fields will be given to - * @return null + * @return false|null */ public function setConfiguration($config, &$applied = null) { if(!is_array($config)) { diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index 7fbabda7106..b2075748a3b 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -140,6 +140,9 @@ class Connection extends LDAPUtility { return $prefix.md5($key); } + /** + * @param string $key + */ public function getFromCache($key) { if(!$this->configured) { $this->readConfiguration(); @@ -156,6 +159,9 @@ class Connection extends LDAPUtility { return unserialize(base64_decode($this->cache->get($key))); } + /** + * @param string $key + */ public function isCached($key) { if(!$this->configured) { $this->readConfiguration(); @@ -167,6 +173,9 @@ class Connection extends LDAPUtility { return $this->cache->hasKey($key); } + /** + * @param string $key + */ public function writeToCache($key, $value) { if(!$this->configured) { $this->readConfiguration(); @@ -201,7 +210,7 @@ class Connection extends LDAPUtility { * @brief set LDAP configuration with values delivered by an array, not read from configuration * @param $config array that holds the config parameters in an associated array * @param &$setParameters optional; array where the set fields will be given to - * @return true if config validates, false otherwise. Check with $setParameters for detailed success on single parameters + * @return boolean true if config validates, false otherwise. Check with $setParameters for detailed success on single parameters */ public function setConfiguration($config, &$setParameters = null) { if(is_null($setParameters)) { diff --git a/apps/user_ldap/lib/helper.php b/apps/user_ldap/lib/helper.php index 9727d847d27..7de7fe8667f 100644 --- a/apps/user_ldap/lib/helper.php +++ b/apps/user_ldap/lib/helper.php @@ -118,10 +118,16 @@ class Helper { return false; } + $saveOtherConfigurations = ''; + if(empty($prefix)) { + $saveOtherConfigurations = 'AND `Configkey` NOT LIKE \'s%\''; + } + $query = \OCP\DB::prepare(' DELETE FROM `*PREFIX*appconfig` WHERE `configkey` LIKE ? + '.$saveOtherConfigurations.' AND `appid` = \'user_ldap\' AND `configkey` NOT IN (\'enabled\', \'installed_version\', \'types\', \'bgjUpdateGroupsLastRun\') '); diff --git a/apps/user_ldap/lib/ildapwrapper.php b/apps/user_ldap/lib/ildapwrapper.php index e60cf5ec63f..017d5549690 100644 --- a/apps/user_ldap/lib/ildapwrapper.php +++ b/apps/user_ldap/lib/ildapwrapper.php @@ -29,7 +29,7 @@ interface ILDAPWrapper { /** * @brief Bind to LDAP directory - * @param $link LDAP link resource + * @param resource $link LDAP link resource * @param $dn an RDN to log in with * @param $password the password * @return true on success, false otherwise @@ -50,7 +50,7 @@ interface ILDAPWrapper { * @brief Send LDAP pagination control * @param $link LDAP link resource * @param $pagesize number of results per page - * @param $isCritical Indicates whether the pagination is critical of not. + * @param boolean $isCritical Indicates whether the pagination is critical of not. * @param $cookie structure sent by LDAP server * @return true on success, false otherwise */ @@ -61,7 +61,7 @@ interface ILDAPWrapper { * @param $link LDAP link resource * @param $result LDAP result resource * @param $cookie structure sent by LDAP server - * @return true on success, false otherwise + * @return boolean on success, false otherwise * * Corresponds to ldap_control_paged_result_response */ @@ -124,7 +124,7 @@ interface ILDAPWrapper { /** * @brief Return next result id * @param $link LDAP link resource - * @param $result LDAP entry result resource + * @param resource $result LDAP entry result resource * @return an LDAP search result resource * */ public function nextEntry($link, $result); @@ -155,7 +155,7 @@ interface ILDAPWrapper { * @brief Sets the value of the specified option to be $value * @param $link LDAP link resource * @param $option a defined LDAP Server option - * @param $value the new value for the option + * @param integer $value the new value for the option * @return true on success, false otherwise */ public function setOption($link, $option, $value); @@ -177,7 +177,7 @@ interface ILDAPWrapper { /** * @brief Unbind from LDAP directory - * @param $link LDAP link resource + * @param resource $link LDAP link resource * @return true on success, false otherwise */ public function unbind($link); @@ -186,20 +186,20 @@ interface ILDAPWrapper { /** * @brief Checks whether the server supports LDAP - * @return true if it the case, false otherwise + * @return boolean if it the case, false otherwise * */ public function areLDAPFunctionsAvailable(); /** * @brief Checks whether PHP supports LDAP Paged Results - * @return true if it the case, false otherwise + * @return boolean if it the case, false otherwise * */ public function hasPagedResultSupport(); /** * @brief Checks whether the submitted parameter is a resource * @param $resource the resource variable to check - * @return true if it is a resource, false otherwise + * @return boolean if it is a resource, false otherwise */ public function isResource($resource); diff --git a/apps/user_ldap/lib/ldap.php b/apps/user_ldap/lib/ldap.php index a99c6480121..de9b7481c19 100644 --- a/apps/user_ldap/lib/ldap.php +++ b/apps/user_ldap/lib/ldap.php @@ -108,7 +108,7 @@ class LDAP implements ILDAPWrapper { /** * @brief Checks whether the server supports LDAP - * @return true if it the case, false otherwise + * @return boolean if it the case, false otherwise * */ public function areLDAPFunctionsAvailable() { return function_exists('ldap_connect'); @@ -116,7 +116,7 @@ class LDAP implements ILDAPWrapper { /** * @brief Checks whether PHP supports LDAP Paged Results - * @return true if it the case, false otherwise + * @return boolean if it the case, false otherwise * */ public function hasPagedResultSupport() { $hasSupport = function_exists('ldap_control_paged_result') @@ -127,7 +127,7 @@ class LDAP implements ILDAPWrapper { /** * @brief Checks whether the submitted parameter is a resource * @param $resource the resource variable to check - * @return true if it is a resource, false otherwise + * @return boolean if it is a resource, false otherwise */ public function isResource($resource) { return is_resource($resource); @@ -144,6 +144,9 @@ class LDAP implements ILDAPWrapper { } } + /** + * @param string $functionName + */ private function preFunctionCall($functionName, $args) { $this->curFunc = $functionName; $this->curArgs = $args; diff --git a/apps/user_ldap/lib/proxy.php b/apps/user_ldap/lib/proxy.php index 30e1875901c..b27233bcd19 100644 --- a/apps/user_ldap/lib/proxy.php +++ b/apps/user_ldap/lib/proxy.php @@ -54,13 +54,21 @@ abstract class Proxy { return 'group-'.$gid.'-lastSeenOn'; } + /** + * @param boolean $passOnWhen + * @param string $method + */ abstract protected function callOnLastSeenOn($id, $method, $parameters, $passOnWhen); + + /** + * @param string $method + */ abstract protected function walkBackends($id, $method, $parameters); /** * @brief Takes care of the request to the User backend * @param $uid string, the uid connected to the request - * @param $method string, the method of the user backend that shall be called + * @param string $method string, the method of the user backend that shall be called * @param $parameters an array of parameters to be passed * @return mixed, the result of the specified method */ @@ -80,6 +88,9 @@ abstract class Proxy { return $prefix.md5($key); } + /** + * @param string $key + */ public function getFromCache($key) { if(!$this->isCached($key)) { return null; @@ -89,11 +100,17 @@ abstract class Proxy { return unserialize(base64_decode($this->cache->get($key))); } + /** + * @param string $key + */ public function isCached($key) { $key = $this->getCacheKey($key); return $this->cache->hasKey($key); } + /** + * @param string $key + */ public function writeToCache($key, $value) { $key = $this->getCacheKey($key); $value = base64_encode(serialize($value)); diff --git a/apps/user_ldap/lib/wizard.php b/apps/user_ldap/lib/wizard.php index 00623b74fb1..e79090febc1 100644 --- a/apps/user_ldap/lib/wizard.php +++ b/apps/user_ldap/lib/wizard.php @@ -176,7 +176,7 @@ class Wizard extends LDAPUtility { /** * @brief return the state of the mode of the specified filter - * @param $confkey string, contains the access key of the Configuration + * @param string $confkey string, contains the access key of the Configuration */ private function getFilterMode($confkey) { $mode = $this->configuration->$confkey; @@ -240,6 +240,8 @@ class Wizard extends LDAPUtility { /** * @brief detects the available LDAP groups + * @param string $dbkey + * @param string $confkey * @returns the instance's WizardResult instance */ private function determineGroups($dbkey, $confkey, $testMemberOf = true) { @@ -554,7 +556,7 @@ class Wizard extends LDAPUtility { /** * @brief Checks whether for a given BaseDN results will be returned - * @param $base the BaseDN to test + * @param string $base the BaseDN to test * @return bool true on success, false otherwise */ private function testBaseDN($base) { @@ -619,7 +621,7 @@ class Wizard extends LDAPUtility { /** * @brief creates an LDAP Filter from given configuration - * @param $filterType int, for which use case the filter shall be created + * @param integer $filterType int, for which use case the filter shall be created * can be any of self::LFILTER_USER_LIST, self::LFILTER_LOGIN or * self::LFILTER_GROUP_LIST * @return mixed, string with the filter on success, false otherwise @@ -846,6 +848,9 @@ class Wizard extends LDAPUtility { || (empty($agent) && empty($pwd))); } + /** + * @param string[] $reqs + */ private function checkRequirements($reqs) { $this->checkAgentRequirements(); foreach($reqs as $option) { @@ -860,11 +865,11 @@ class Wizard extends LDAPUtility { /** * @brief does a cumulativeSearch on LDAP to get different values of a * specified attribute - * @param $filters array, the filters that shall be used in the search - * @param $attr the attribute of which a list of values shall be returned + * @param string[] $filters array, the filters that shall be used in the search + * @param string $attr the attribute of which a list of values shall be returned * @param $lfw bool, whether the last filter is a wildcard which shall not * be processed if there were already findings, defaults to true - * @param $maxF string. if not null, this variable will have the filter that + * @param string $maxF string. if not null, this variable will have the filter that * yields most result entries * @return mixed, an array with the values on success, false otherwise * @@ -926,10 +931,10 @@ class Wizard extends LDAPUtility { /** * @brief determines if and which $attr are available on the LDAP server - * @param $objectclasses the objectclasses to use as search filter - * @param $attr the attribute to look for - * @param $dbkey the dbkey of the setting the feature is connected to - * @param $confkey the confkey counterpart for the $dbkey as used in the + * @param string[] $objectclasses the objectclasses to use as search filter + * @param string $attr the attribute to look for + * @param string $dbkey the dbkey of the setting the feature is connected to + * @param string $confkey the confkey counterpart for the $dbkey as used in the * Configuration class * @param $po boolean, whether the objectClass with most result entries * shall be pre-selected via the result diff --git a/apps/user_ldap/templates/part.wizard-groupfilter.php b/apps/user_ldap/templates/part.wizard-groupfilter.php index 0cc4dfa572a..e460997b1bf 100644 --- a/apps/user_ldap/templates/part.wizard-groupfilter.php +++ b/apps/user_ldap/templates/part.wizard-groupfilter.php @@ -1,7 +1,7 @@ <fieldset id="ldapWizard4"> <div> <p> - <?php p($l->t('Limit the access to %s to groups meeting this criteria:', $theme->getName()));?> + <?php p($l->t('Groups meeting these criteria are available in %s:', $theme->getName()));?> </p> <p> <label for="ldap_groupfilter_objectclass"> diff --git a/apps/user_ldap/templates/part.wizard-loginfilter.php b/apps/user_ldap/templates/part.wizard-loginfilter.php index dc5d61e9f77..3dde46fa979 100644 --- a/apps/user_ldap/templates/part.wizard-loginfilter.php +++ b/apps/user_ldap/templates/part.wizard-loginfilter.php @@ -1,7 +1,7 @@ <fieldset id="ldapWizard3"> <div> <p> - <?php p($l->t('What attribute shall be used as login name:'));?> + <?php p($l->t('Users login with this attribute:'));?> </p> <p> <label for="ldap_loginfilter_username"> diff --git a/apps/user_ldap/templates/part.wizard-userfilter.php b/apps/user_ldap/templates/part.wizard-userfilter.php index c1d522ce2a6..eff9f89ce2c 100644 --- a/apps/user_ldap/templates/part.wizard-userfilter.php +++ b/apps/user_ldap/templates/part.wizard-userfilter.php @@ -1,7 +1,7 @@ <fieldset id="ldapWizard2"> <div> <p> - <?php p($l->t('Limit the access to %s to users meeting this criteria:', $theme->getName()));?> + <?php p($l->t('Limit %s access to users meeting these criteria:', $theme->getName()));?> </p> <p> <label for="ldap_userfilter_objectclass"> diff --git a/apps/user_ldap/user_ldap.php b/apps/user_ldap/user_ldap.php index a19af86086c..757de6b60f4 100644 --- a/apps/user_ldap/user_ldap.php +++ b/apps/user_ldap/user_ldap.php @@ -25,7 +25,6 @@ namespace OCA\user_ldap; -use OCA\user_ldap\lib\ILDAPWrapper; use OCA\user_ldap\lib\BackendUtility; class USER_LDAP extends BackendUtility implements \OCP\UserInterface { @@ -85,15 +84,14 @@ class USER_LDAP extends BackendUtility implements \OCP\UserInterface { return; } - $jpegPhoto = $this->access->readAttribute($dn, 'jpegPhoto'); - \OCP\Config::setUserValue($uid, 'user_ldap', 'lastJpegPhotoLookup', time()); - if(!$jpegPhoto || !is_array($jpegPhoto) || !isset($jpegPhoto[0])) { + $avatarImage = $this->getAvatarImage($uid, $dn); + if($avatarImage === false) { //not set, nothing left to do; return; } $image = new \OCP\Image(); - $image->loadFromBase64(base64_encode($jpegPhoto[0])); + $image->loadFromBase64(base64_encode($avatarImage)); if(!$image->valid()) { \OCP\Util::writeLog('user_ldap', 'jpegPhoto data invalid for '.$dn, @@ -128,8 +126,7 @@ class USER_LDAP extends BackendUtility implements \OCP\UserInterface { if(!$dn) { return false; } - $jpegPhoto = $this->access->readAttribute($dn, 'jpegPhoto'); - if(!$jpegPhoto || !is_array($jpegPhoto) || !isset($jpegPhoto[0])) { + if($this->getAvatarImage($uid, $dn) === false) { //The user is allowed to change his avatar in ownCloud only if no //avatar is provided by LDAP return true; @@ -138,14 +135,36 @@ class USER_LDAP extends BackendUtility implements \OCP\UserInterface { } /** + * @brief reads the image from LDAP that shall be used as Avatar + * @param $uid string, the ownCloud user name + * @param $dn string, the user DN + * @return string data (provided by LDAP) | false + */ + private function getAvatarImage($uid, $dn) { + $attributes = array('jpegPhoto', 'thumbnailPhoto'); + foreach($attributes as $attribute) { + $result = $this->access->readAttribute($dn, $attribute); + \OCP\Config::setUserValue($uid, 'user_ldap', 'lastJpegPhotoLookup', + time()); + if($result !== false && is_array($result) && isset($result[0])) { + return $result[0]; + } + } + + return false; + } + + /** * @brief Check if the password is correct - * @param $uid The username - * @param $password The password - * @returns true/false + * @param string $uid The username + * @param string $password The password + * @return boolean * * Check if the password is correct without logging in the user */ public function checkPassword($uid, $password) { + $uid = $this->access->escapeFilterPart($uid); + //find out dn of the user name $filter = \OCP\Util::mb_str_replace( '%uid', $uid, $this->access->connection->ldapLoginFilter, 'UTF-8'); @@ -186,6 +205,7 @@ class USER_LDAP extends BackendUtility implements \OCP\UserInterface { * Get a list of all users. */ public function getUsers($search = '', $limit = 10, $offset = 0) { + $search = $this->access->escapeFilterPart($search); $cachekey = 'getUsers-'.$search.'-'.$limit.'-'.$offset; //check if users are cached, if so return @@ -238,7 +258,8 @@ class USER_LDAP extends BackendUtility implements \OCP\UserInterface { } //check if user really still exists by reading its entry if(!is_array($this->access->readAttribute($dn, ''))) { - \OCP\Util::writeLog('user_ldap', 'LDAP says no user '.$dn, \OCP\Util::DEBUG); + \OCP\Util::writeLog('user_ldap', 'LDAP says no user '.$dn.' on '. + $this->access->connection->ldapHost, \OCP\Util::DEBUG); $this->access->connection->writeToCache('userExists'.$uid, false); return false; } |