diff options
author | Thomas Müller <thomas.mueller@tmit.eu> | 2014-02-14 23:03:27 +0100 |
---|---|---|
committer | Thomas Müller <thomas.mueller@tmit.eu> | 2014-02-14 23:03:27 +0100 |
commit | 9fac95c2ab46a734607657bbad6f164aaa61286f (patch) | |
tree | fc035f83bc812fd4b2f36427bb130ddabf71433e | |
parent | b330d07b51a983dc563a91244a3c83e691c9e97d (diff) | |
parent | df282d9ef8e040833574fac5c5fd3cbbae1b3209 (diff) | |
download | nextcloud-server-9fac95c2ab46a734607657bbad6f164aaa61286f.tar.gz nextcloud-server-9fac95c2ab46a734607657bbad6f164aaa61286f.zip |
Merge branch 'master' into scrutinizer_documentation_patches
Conflicts:
lib/private/appconfig.php
69 files changed, 1130 insertions, 226 deletions
diff --git a/README.md b/README.md index ca7b04a925a..3f76c1a4773 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,9 @@ A personal cloud which runs on your own server. ### Build Status on [Jenkins CI](https://ci.owncloud.org/) -Git master: [![Build Status](https://ci.owncloud.org/buildStatus/icon?job=ownCloud-Server%28master%29)](https://ci.owncloud.org/job/ownCloud-Server%28master%29/) +Git master: [![Build Status](https://ci.owncloud.org/job/server-master-linux/badge/icon)](https://ci.owncloud.org/job/server-master-linux/) + +Quality: [![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/owncloud/core/badges/quality-score.png?s=ce2f5ded03d4ac628e9ee5c767243fa7412e644f)](https://scrutinizer-ci.com/g/owncloud/core/) ### Installation instructions http://doc.owncloud.org/server/5.0/developer_manual/app/gettingstarted.html diff --git a/apps/files/ajax/upload.php b/apps/files/ajax/upload.php index 8f6c42d6620..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') ) { @@ -139,7 +147,8 @@ if (strpos($dir, '..') === false) { 'originalname' => $files['tmp_name'][$i], 'uploadMaxFilesize' => $maxUploadFileSize, 'maxHumanFilesize' => $maxHumanFileSize, - 'permissions' => $meta['permissions'] & $allowedPermissions + 'permissions' => $meta['permissions'] & $allowedPermissions, + 'directory' => $directory, ); } @@ -166,7 +175,8 @@ if (strpos($dir, '..') === false) { 'originalname' => $files['tmp_name'][$i], 'uploadMaxFilesize' => $maxUploadFileSize, 'maxHumanFilesize' => $maxHumanFileSize, - 'permissions' => $meta['permissions'] & $allowedPermissions + 'permissions' => $meta['permissions'] & $allowedPermissions, + 'directory' => $directory, ); } } 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..27fa75ebc59 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 { diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index f538af10362..a855d6cbe59 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -435,10 +435,9 @@ window.FileList={ tr.attr('data-file', newname); var path = td.children('a.name').attr('href'); td.children('a.name').attr('href', path.replace(encodeURIComponent(oldname), encodeURIComponent(newname))); + var basename = newname; if (newname.indexOf('.') > 0 && tr.data('type') !== 'dir') { - var basename=newname.substr(0,newname.lastIndexOf('.')); - } else { - var basename=newname; + basename = newname.substr(0,newname.lastIndexOf('.')); } td.find('a.name span.nametext').text(basename); if (newname.indexOf('.') > 0 && tr.data('type') !== 'dir') { @@ -544,10 +543,9 @@ window.FileList={ td.children('a.name .span').text(newName); var path = td.children('a.name').attr('href'); td.children('a.name').attr('href', path.replace(encodeURIComponent(oldName), encodeURIComponent(newName))); + var basename = newName; if (newName.indexOf('.') > 0) { - var basename = newName.substr(0, newName.lastIndexOf('.')); - } else { - var basename = newName; + basename = newName.substr(0, newName.lastIndexOf('.')); } td.children('a.name').empty(); var span = $('<span class="nametext"></span>'); @@ -924,8 +922,8 @@ $(document).ready(function() { data.context.find('td.filesize').text(humanFileSize(size)); } else { - // only append new file if dragged onto current dir's crumb (last) - if (data.context && data.context.hasClass('crumb') && !data.context.hasClass('last')) { + // only append new file if uploaded into the current folder + if (file.directory !== FileList.getCurrentDirectory()) { return; } diff --git a/apps/files/js/files.js b/apps/files/js/files.js index a535700c1b3..1ec4c4ec7ab 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -405,7 +405,7 @@ $(document).ready(function() { Files.resizeBreadcrumbs(width, true); // display storage warnings - setTimeout ( "Files.displayStorageWarnings()", 100 ); + setTimeout(Files.displayStorageWarnings, 100); OC.Notification.setDefault(Files.displayStorageWarnings); // only possible at the moment if user is logged in diff --git a/apps/files/lib/helper.php b/apps/files/lib/helper.php index 21d1f50e587..01fc65d76b7 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'], diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index d599665644b..d2a8290156f 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -80,8 +80,15 @@ class Hooks { // Check if first-run file migration has already been performed
$ready = false;
- if ($util->getMigrationStatus() === Util::MIGRATION_OPEN) {
+ $migrationStatus = $util->getMigrationStatus();
+ if ($migrationStatus === Util::MIGRATION_OPEN) {
$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();
+ }
}
// If migration not yet done
diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 11048005969..2ea477a6e4d 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -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/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/tests/hooks.php b/apps/files_encryption/tests/hooks.php index c26cba6406d..7d926caea1b 100644 --- a/apps/files_encryption/tests/hooks.php +++ b/apps/files_encryption/tests/hooks.php @@ -36,8 +36,8 @@ use OCA\Encryption; */ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase { - const TEST_ENCRYPTION_HOOKS_USER1 = "test-proxy-user1"; - const TEST_ENCRYPTION_HOOKS_USER2 = "test-proxy-user2"; + const TEST_ENCRYPTION_HOOKS_USER1 = "test-encryption-hooks-user1"; + const TEST_ENCRYPTION_HOOKS_USER2 = "test-encryption-hooks-user2"; /** * @var \OC_FilesystemView @@ -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/share.php b/apps/files_encryption/tests/share.php index acf408a07f0..5c6569f20e7 100755 --- a/apps/files_encryption/tests/share.php +++ b/apps/files_encryption/tests/share.php @@ -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']); @@ -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']); @@ -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 9eaff79d850..f87502e6cab 100755 --- a/apps/files_encryption/tests/util.php +++ b/apps/files_encryption/tests/util.php @@ -328,7 +328,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 +338,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,14 +357,14 @@ 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); // encrypt all unencrypted files $util->decryptAll('/' . $this->userId . '/' . 'files'); $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']); diff --git a/apps/files_external/lib/config.php b/apps/files_external/lib/config.php index ae0f4e41a5a..94dc5fb7ad8 100755 --- a/apps/files_external/lib/config.php +++ b/apps/files_external/lib/config.php @@ -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'); 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/lib/cache.php b/apps/files_sharing/lib/cache.php index cf89f3ea629..7d63e7a4fe3 100644 --- a/apps/files_sharing/lib/cache.php +++ b/apps/files_sharing/lib/cache.php @@ -95,12 +95,11 @@ class Shared_Cache extends Cache { } else { $query = \OC_DB::prepare( 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`,' - .' `size`, `mtime`, `encrypted`' + .' `size`, `mtime`, `encrypted`, `unencrypted_size`' .' FROM `*PREFIX*filecache` WHERE `fileid` = ?'); $result = $query->execute(array($file)); $data = $result->fetchRow(); $data['fileid'] = (int)$data['fileid']; - $data['size'] = (int)$data['size']; $data['mtime'] = (int)$data['mtime']; $data['storage_mtime'] = (int)$data['storage_mtime']; $data['encrypted'] = (bool)$data['encrypted']; @@ -109,6 +108,12 @@ class Shared_Cache extends Cache { if ($data['storage_mtime'] === 0) { $data['storage_mtime'] = $data['mtime']; } + if ($data['encrypted'] or ($data['unencrypted_size'] > 0 and $data['mimetype'] === 'httpd/unix-directory')) { + $data['encrypted_size'] = (int)$data['size']; + $data['size'] = (int)$data['unencrypted_size']; + } else { + $data['size'] = (int)$data['size']; + } return $data; } return false; @@ -337,6 +342,12 @@ class Shared_Cache extends Cache { } $row['mimetype'] = $this->getMimetype($row['mimetype']); $row['mimepart'] = $this->getMimetype($row['mimepart']); + if ($row['encrypted'] or ($row['unencrypted_size'] > 0 and $row['mimetype'] === 'httpd/unix-directory')) { + $row['encrypted_size'] = $row['size']; + $row['size'] = $row['unencrypted_size']; + } else { + $row['size'] = $row['size']; + } $files[] = $row; } } diff --git a/apps/files_sharing/lib/share/file.php b/apps/files_sharing/lib/share/file.php index c956c55a1df..ec0f368386f 100644 --- a/apps/files_sharing/lib/share/file.php +++ b/apps/files_sharing/lib/share/file.php @@ -91,10 +91,17 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent { $file['name'] = basename($item['file_target']); $file['mimetype'] = $item['mimetype']; $file['mimepart'] = $item['mimepart']; - $file['size'] = $item['size']; $file['mtime'] = $item['mtime']; $file['encrypted'] = $item['encrypted']; $file['etag'] = $item['etag']; + $storage = \OC\Files\Filesystem::getStorage('/'); + $cache = $storage->getCache(); + if ($item['encrypted'] or ($item['unencrypted_size'] > 0 and $cache->getMimetype($item['mimetype']) === 'httpd/unix-directory')) { + $file['size'] = $item['unencrypted_size']; + $file['encrypted_size'] = $item['size']; + } else { + $file['size'] = $item['size']; + } $files[] = $file; } return $files; 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_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/lib/trashbin.php b/apps/files_trashbin/lib/trashbin.php index 6d2d3f08112..56ab2e72c7b 100644 --- a/apps/files_trashbin/lib/trashbin.php +++ b/apps/files_trashbin/lib/trashbin.php @@ -1007,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/user_ldap/appinfo/info.xml b/apps/user_ldap/appinfo/info.xml index 148a72cecbb..9cc908e8522 100644 --- a/apps/user_ldap/appinfo/info.xml +++ b/apps/user_ldap/appinfo/info.xml @@ -14,4 +14,7 @@ <types> <authentication/> </types> + <documentation> + <admin>http://doc.owncloud.org/server/6.0/go.php?to=admin-ldap</admin> + </documentation> </info> diff --git a/apps/user_ldap/js/settings.js b/apps/user_ldap/js/settings.js index acf88ef58a4..792638f2b58 100644 --- a/apps/user_ldap/js/settings.js +++ b/apps/user_ldap/js/settings.js @@ -240,6 +240,7 @@ var LdapWizard = { LdapWizard.hideSpinner('#ldap_base'); LdapWizard.showInfoBox('Please specify a Base DN'); LdapWizard.showInfoBox('Could not determine Base DN'); + $('#ldap_base').prop('disabled', false); } ); } diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php index 579aedeefc3..8a8d8aa5e3a 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -750,7 +750,7 @@ class Access extends LDAPUtility { } } else { if(!is_null($limit)) { - \OCP\Util::writeLog('user_ldap', 'Paged search failed :(', \OCP\Util::INFO); + \OCP\Util::writeLog('user_ldap', 'Paged search was not available', \OCP\Util::INFO); } } } diff --git a/apps/user_ldap/lib/ildapwrapper.php b/apps/user_ldap/lib/ildapwrapper.php index 3cda2aac7a5..017d5549690 100644 --- a/apps/user_ldap/lib/ildapwrapper.php +++ b/apps/user_ldap/lib/ildapwrapper.php @@ -145,9 +145,11 @@ interface ILDAPWrapper { * @param $baseDN The DN of the entry to read from * @param $filter An LDAP filter * @param $attr array of the attributes to read + * @param $attrsonly optional, 1 if only attribute types shall be returned + * @param $limit optional, limits the result entries * @return an LDAP search result resource, false on error */ - public function search($link, $baseDN, $filter, $attr); + public function search($link, $baseDN, $filter, $attr, $attrsonly = 0, $limit = 0); /** * @brief Sets the value of the specified option to be $value diff --git a/apps/user_ldap/lib/ldap.php b/apps/user_ldap/lib/ldap.php index ffd97ab83f9..de9b7481c19 100644 --- a/apps/user_ldap/lib/ldap.php +++ b/apps/user_ldap/lib/ldap.php @@ -85,9 +85,9 @@ class LDAP implements ILDAPWrapper { return $this->invokeLDAPMethod('read', $link, $baseDN, $filter, $attr); } - public function search($link, $baseDN, $filter, $attr) { - return $this->invokeLDAPMethod('search', $link, $baseDN, - $filter, $attr); + public function search($link, $baseDN, $filter, $attr, $attrsonly = 0, $limit = 0) { + return $this->invokeLDAPMethod('search', $link, $baseDN, $filter, + $attr, $attrsonly, $limit); } public function setOption($link, $option, $value) { diff --git a/apps/user_ldap/lib/wizard.php b/apps/user_ldap/lib/wizard.php index 27edeb2a449..5079642d954 100644 --- a/apps/user_ldap/lib/wizard.php +++ b/apps/user_ldap/lib/wizard.php @@ -569,6 +569,10 @@ class Wizard extends LDAPUtility { //get a result set > 0 on a proper base $rr = $this->ldap->search($cr, $base, 'objectClass=*', array('dn'), 0, 1); if(!$this->ldap->isResource($rr)) { + $errorNo = $this->ldap->errno($cr); + $errorMsg = $this->ldap->error($cr); + \OCP\Util::writeLog('user_ldap', 'Wiz: Could not search base '.$base. + ' Error '.$errorNo.': '.$errorMsg, \OCP\Util::INFO); return false; } $entries = $this->ldap->countEntries($cr, $rr); @@ -1015,6 +1019,7 @@ class Wizard extends LDAPUtility { $this->configuration->ldapPort); $this->ldap->setOption($cr, LDAP_OPT_PROTOCOL_VERSION, 3); + $this->ldap->setOption($cr, LDAP_OPT_REFERRALS, 0); $this->ldap->setOption($cr, LDAP_OPT_NETWORK_TIMEOUT, self::LDAP_NW_TIMEOUT); if($this->configuration->ldapTLS === 1) { $this->ldap->startTls($cr); diff --git a/apps/user_ldap/user_ldap.php b/apps/user_ldap/user_ldap.php index f983c7835af..1088dafab71 100644 --- a/apps/user_ldap/user_ldap.php +++ b/apps/user_ldap/user_ldap.php @@ -85,15 +85,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 +127,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,6 +136,26 @@ 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 image 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 string $uid The username * @param string $password The password @@ -238,7 +256,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; } diff --git a/config/config.sample.php b/config/config.sample.php index ef5fb7ea5a5..0cd321d095d 100755 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -120,8 +120,14 @@ $CONFIG = array( /* Password to use for sendmail mail, depends on mail_smtpauth if this is used */ "mail_smtppassword" => "", -/* memcached hostname and port (Only used when xCache, APC and APCu are absent.) */ -"memcached_server" => array('localhost', 11211), +/* memcached servers (Only used when xCache, APC and APCu are absent.) */ +"memcached_servers" => array( + // hostname, port and optional weight. Also see: + // http://www.php.net/manual/en/memcached.addservers.php + // http://www.php.net/manual/en/memcached.addserver.php + array('localhost', 11211), + //array('other.host.local', 11211), +), /* How long should ownCloud keep deleted files in the trash bin, default value: 30 days */ 'trashbin_retention_obligation' => 30, diff --git a/core/ajax/preview.php b/core/ajax/preview.php index af0f0493f4c..a1267d6f5cf 100644 --- a/core/ajax/preview.php +++ b/core/ajax/preview.php @@ -7,7 +7,7 @@ */ \OC_Util::checkLoggedIn(); -$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/core/ajax/share.php b/core/ajax/share.php index 8b48effb458..c251f8e7bae 100644 --- a/core/ajax/share.php +++ b/core/ajax/share.php @@ -354,6 +354,10 @@ if (isset($_POST['action']) && isset($_POST['itemType']) && isset($_POST['itemSo break; } } + $sorter = new \OC\Share\SearchResultSorter($_GET['search'], + 'label', + new \OC\Log()); + usort($shareWith, array($sorter, 'sort')); OC_JSON::success(array('data' => $shareWith)); } break; diff --git a/core/setup/controller.php b/core/setup/controller.php index 58ed4d28dc0..697408cfb57 100644 --- a/core/setup/controller.php +++ b/core/setup/controller.php @@ -91,7 +91,7 @@ class Controller { $databases['sqlite'] = 'SQLite'; } if ($hasMySQL) { - $databases['mysql'] = 'MySQL'; + $databases['mysql'] = 'MySQL/MariaDB'; } if ($hasPostgreSQL) { $databases['pgsql'] = 'PostgreSQL'; diff --git a/lib/private/appconfig.php b/lib/private/appconfig.php index 5da0a7e906b..a32c1126c7b 100644 --- a/lib/private/appconfig.php +++ b/lib/private/appconfig.php @@ -33,15 +33,56 @@ * */ +namespace OC; + +use \OC\DB\Connection; + /** * This class provides an easy way for apps to store config values in the * database. */ -class OC_Appconfig { +class AppConfig implements \OCP\IAppConfig { + /** + * @var \OC\DB\Connection $conn + */ + protected $conn; + + private $cache = array(); - private static $cache = array(); + private $appsLoaded = array(); - private static $appsLoaded = array(); + /** + * @param \OC\DB\Connection $conn + */ + public function __construct(Connection $conn) { + $this->conn = $conn; + } + + /** + * @param string $app + * @return string[] + */ + private function getAppCache($app) { + if (!isset($this->cache[$app])) { + $this->cache[$app] = array(); + } + return $this->cache[$app]; + } + + private function getAppValues($app) { + $appCache = $this->getAppCache($app); + if (array_search($app, $this->appsLoaded) === false) { + $query = 'SELECT `configvalue`, `configkey` FROM `*PREFIX*appconfig`' + . ' WHERE `appid` = ?'; + $result = $this->conn->executeQuery($query, array($app)); + while ($row = $result->fetch()) { + $appCache[$row['configkey']] = $row['configvalue']; + } + $this->appsLoaded[] = $app; + } + $this->cache[$app] = $appCache; + return $appCache; + } /** * @brief Get all apps using the config @@ -50,16 +91,14 @@ class OC_Appconfig { * This function returns a list of all apps that have at least one * entry in the appconfig table. */ - public static function getApps() { - // No magic in here! - $query = OC_DB::prepare('SELECT DISTINCT `appid` FROM `*PREFIX*appconfig` ORDER BY `appid`'); - $result = $query->execute(); + public function getApps() { + $query = 'SELECT DISTINCT `appid` FROM `*PREFIX*appconfig` ORDER BY `appid`'; + $result = $this->conn->executeQuery($query); $apps = array(); - while ($row = $result->fetchRow()) { - $apps[] = $row["appid"]; + while ($appid = $result->fetchColumn()) { + $apps[] = $appid; } - return $apps; } @@ -71,39 +110,14 @@ class OC_Appconfig { * This function gets all keys of an app. Please note that the values are * not returned. */ - public static function getKeys($app) { - // No magic in here as well - $query = OC_DB::prepare('SELECT `configkey` FROM `*PREFIX*appconfig` WHERE `appid` = ?'); - $result = $query->execute(array($app)); - - $keys = array(); - while ($row = $result->fetchRow()) { - $keys[] = $row["configkey"]; - } - + public function getKeys($app) { + $values = $this->getAppValues($app); + $keys = array_keys($values); + sort($keys); return $keys; } /** - * @param string $app - */ - private static function getAppValues($app) { - if (!isset(self::$cache[$app])) { - self::$cache[$app] = array(); - } - if (array_search($app, self::$appsLoaded) === false) { - $query = OC_DB::prepare('SELECT `configvalue`, `configkey` FROM `*PREFIX*appconfig`' - . ' WHERE `appid` = ?'); - $result = $query->execute(array($app)); - while ($row = $result->fetchRow()) { - self::$cache[$app][$row['configkey']] = $row['configvalue']; - } - self::$appsLoaded[] = $app; - } - return self::$cache[$app]; - } - - /** * @brief Gets the config value * @param string $app app * @param string $key key @@ -113,18 +127,11 @@ class OC_Appconfig { * This function gets a value from the appconfig table. If the key does * not exist the default value will be returned */ - public static function getValue($app, $key, $default = null) { - if (!isset(self::$cache[$app])) { - self::$cache[$app] = array(); - } - if (isset(self::$cache[$app][$key])) { - return self::$cache[$app][$key]; - } - $values = self::getAppValues($app); + public function getValue($app, $key, $default = null) { + $values = $this->getAppValues($app); if (isset($values[$key])) { return $values[$key]; } else { - self::$cache[$app][$key] = $default; return $default; } } @@ -135,12 +142,9 @@ class OC_Appconfig { * @param string $key * @return bool */ - public static function hasKey($app, $key) { - if (isset(self::$cache[$app]) and isset(self::$cache[$app][$key])) { - return true; - } - $exists = self::getKeys($app); - return in_array($key, $exists); + public function hasKey($app, $key) { + $values = $this->getAppValues($app); + return isset($values[$key]); } /** @@ -148,31 +152,32 @@ class OC_Appconfig { * @param string $app app * @param string $key key * @param string $value value - * @return boolean|null * * Sets a value. If the key did not exist before it will be created. */ - public static function setValue($app, $key, $value) { - // Does the key exist? yes: update. No: insert - if (!self::hasKey($app, $key)) { - $query = OC_DB::prepare('INSERT INTO `*PREFIX*appconfig` ( `appid`, `configkey`, `configvalue` )' - . ' VALUES( ?, ?, ? )'); - $query->execute(array($app, $key, $value)); + public function setValue($app, $key, $value) { + // Does the key exist? no: insert, yes: update. + if (!$this->hasKey($app, $key)) { + $data = array( + 'appid' => $app, + 'configkey' => $key, + 'configvalue' => $value, + ); + $this->conn->insert('*PREFIX*appconfig', $data); } else { - $query = OC_DB::prepare('UPDATE `*PREFIX*appconfig` SET `configvalue` = ?' - . ' WHERE `appid` = ? AND `configkey` = ?'); - $query->execute(array($value, $app, $key)); + $data = array( + 'configvalue' => $value, + ); + $where = array( + 'appid' => $app, + 'configkey' => $key, + ); + $this->conn->update('*PREFIX*appconfig', $data, $where); } - // TODO where should this be documented? - \OC_Hook::emit('OC_Appconfig', 'post_set_value', array( - 'app' => $app, - 'key' => $key, - 'value' => $value - )); - if (!isset(self::$cache[$app])) { - self::$cache[$app] = array(); + if (!isset($this->cache[$app])) { + $this->cache[$app] = array(); } - self::$cache[$app][$key] = $value; + $this->cache[$app][$key] = $value; } /** @@ -181,15 +186,15 @@ class OC_Appconfig { * @param string $key key * @return bool */ - public static function deleteKey($app, $key) { - // Boring! - $query = OC_DB::prepare('DELETE FROM `*PREFIX*appconfig` WHERE `appid` = ? AND `configkey` = ?'); - $query->execute(array($app, $key)); - if (isset(self::$cache[$app]) and isset(self::$cache[$app][$key])) { - unset(self::$cache[$app][$key]); + public function deleteKey($app, $key) { + $where = array( + 'appid' => $app, + 'configkey' => $key, + ); + $this->conn->delete('*PREFIX*appconfig', $where); + if (isset($this->cache[$app]) and isset($this->cache[$app][$key])) { + unset($this->cache[$app][$key]); } - - return true; } /** @@ -199,13 +204,12 @@ class OC_Appconfig { * * Removes all keys in appconfig belonging to the app. */ - public static function deleteApp($app) { - // Nothing special - $query = OC_DB::prepare('DELETE FROM `*PREFIX*appconfig` WHERE `appid` = ?'); - $query->execute(array($app)); - self::$cache[$app] = array(); - - return true; + public function deleteApp($app) { + $where = array( + 'appid' => $app, + ); + $this->conn->delete('*PREFIX*appconfig', $where); + unset($this->cache[$app]); } /** @@ -215,10 +219,11 @@ class OC_Appconfig { * @param string $key * @return array */ - public static function getValues($app, $key) { - if ($app !== false and $key !== false) { + public function getValues($app, $key) { + if (($app !== false) == ($key !== false)) { return false; } + $fields = '`configvalue`'; $where = 'WHERE'; $params = array(); @@ -233,13 +238,14 @@ class OC_Appconfig { $params[] = $key; $key = 'appid'; } - $queryString = 'SELECT ' . $fields . ' FROM `*PREFIX*appconfig` ' . $where; - $query = OC_DB::prepare($queryString); - $result = $query->execute($params); + $query = 'SELECT ' . $fields . ' FROM `*PREFIX*appconfig` ' . $where; + $result = $this->conn->executeQuery($query, $params); + $values = array(); - while ($row = $result->fetchRow()) { + while ($row = $result->fetch((\PDO::FETCH_ASSOC))) { $values[$row[$key]] = $row['configvalue']; } + return $values; } } diff --git a/lib/private/db/statementwrapper.php b/lib/private/db/statementwrapper.php index 2da10741ce6..90dbef1c730 100644 --- a/lib/private/db/statementwrapper.php +++ b/lib/private/db/statementwrapper.php @@ -34,6 +34,9 @@ class OC_DB_StatementWrapper { /** * make execute return the result instead of a bool + * + * @param array $input + * @return \OC_DB_StatementWrapper | int */ public function execute($input=array()) { if(OC_Config::getValue( "log_query", false)) { diff --git a/lib/private/files.php b/lib/private/files.php index 6fb7d9ff41d..4a6b9d8ca0e 100644 --- a/lib/private/files.php +++ b/lib/private/files.php @@ -131,7 +131,7 @@ class OC_Files { } if ($xsendfile) { list($storage) = \OC\Files\Filesystem::resolvePath(\OC\Files\Filesystem::getView()->getAbsolutePath($filename)); - if ($storage instanceof \OC\Files\Storage\Local) { + if ($storage->isLocal()) { self::addSendfileHeader(\OC\Files\Filesystem::getLocalFile($filename)); } } diff --git a/lib/private/files/cache/storage.php b/lib/private/files/cache/storage.php index 59972667287..6b6b0bce9d7 100644 --- a/lib/private/files/cache/storage.php +++ b/lib/private/files/cache/storage.php @@ -76,4 +76,23 @@ class Storage { return false; } } + + /** + * remove the entry for the storage + * + * @param string $storageId + */ + public static function remove($storageId) { + $storageCache = new Storage($storageId); + $numericId = $storageCache->getNumericId(); + + if (strlen($storageId) > 64) { + $storageId = md5($storageId); + } + $sql = 'DELETE FROM `*PREFIX*storages` WHERE `id` = ?'; + \OC_DB::executeAudited($sql, array($storageId)); + + $sql = 'DELETE FROM `*PREFIX*filecache` WHERE `storage` = ?'; + \OC_DB::executeAudited($sql, array($numericId)); + } } diff --git a/lib/private/files/fileinfo.php b/lib/private/files/fileinfo.php new file mode 100644 index 00000000000..c77571cd2a7 --- /dev/null +++ b/lib/private/files/fileinfo.php @@ -0,0 +1,185 @@ +<?php +/** + * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Files; + +class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess { + /** + * @var array $data + */ + private $data; + + /** + * @var string $path + */ + private $path; + + /** + * @var \OC\Files\Storage\Storage $storage + */ + private $storage; + + /** + * @var string $internalPath + */ + private $internalPath; + + public function __construct($path, $storage, $internalPath, $data) { + $this->path = $path; + $this->storage = $storage; + $this->internalPath = $internalPath; + $this->data = $data; + } + + public function offsetSet($offset, $value) { + $this->data[$offset] = $value; + } + + public function offsetExists($offset) { + return isset($this->data[$offset]); + } + + public function offsetUnset($offset) { + unset($this->data[$offset]); + } + + public function offsetGet($offset) { + return $this->data[$offset]; + } + + /** + * @return string + */ + public function getPath() { + return $this->path; + } + + /** + * @return \OCP\Files\Storage + */ + public function getStorage() { + return $this->storage; + } + + /** + * @return string + */ + public function getInternalPath() { + return $this->internalPath; + } + + /** + * @return int + */ + public function getId() { + return $this->data['fileid']; + } + + /** + * @return string + */ + public function getMimetype() { + return $this->data['mimetype']; + } + + /** + * @return string + */ + public function getMimePart() { + return $this->data['mimepart']; + } + + /** + * @return string + */ + public function getName() { + return $this->data['name']; + } + + /** + * @return string + */ + public function getEtag() { + return $this->data['etag']; + } + + /** + * @return int + */ + public function getSize() { + return $this->data['size']; + } + + /** + * @return int + */ + public function getMTime() { + return $this->data['mtime']; + } + + /** + * @return bool + */ + public function isEncrypted() { + return $this->data['encrypted']; + } + + /** + * @return int + */ + public function getPermissions() { + return $this->data['permissions']; + } + + /** + * @return \OCP\Files\FileInfo::TYPE_FILE | \OCP\Files\FileInfo::TYPE_FOLDER + */ + public function getType() { + return $this->data['type']; + } + + public function getData(){ + return $this->data; + } + + /** + * @param int $permissions + * @return bool + */ + protected function checkPermissions($permissions) { + return ($this->getPermissions() & $permissions) === $permissions; + } + + /** + * @return bool + */ + public function isReadable() { + return $this->checkPermissions(\OCP\PERMISSION_READ); + } + + /** + * @return bool + */ + public function isUpdateable() { + return $this->checkPermissions(\OCP\PERMISSION_UPDATE); + } + + /** + * @return bool + */ + public function isDeletable() { + return $this->checkPermissions(\OCP\PERMISSION_DELETE); + } + + /** + * @return bool + */ + public function isShareable() { + return $this->checkPermissions(\OCP\PERMISSION_SHARE); + } +} diff --git a/lib/private/files/storage/common.php b/lib/private/files/storage/common.php index 35464035209..d4dca780ff3 100644 --- a/lib/private/files/storage/common.php +++ b/lib/private/files/storage/common.php @@ -380,4 +380,13 @@ abstract class Common implements \OC\Files\Storage\Storage { public function free_space($path) { return \OC\Files\SPACE_UNKNOWN; } + + /** + * {@inheritdoc} + */ + public function isLocal() { + // the common implementation returns a temporary file by + // default, which is not local + return false; + } } diff --git a/lib/private/files/storage/local.php b/lib/private/files/storage/local.php index ba5e036cd8e..a62230bdba5 100644 --- a/lib/private/files/storage/local.php +++ b/lib/private/files/storage/local.php @@ -307,5 +307,12 @@ if (\OC_Util::runningOnWindows()) { public function hasUpdated($path, $time) { return $this->filemtime($path) > $time; } + + /** + * {@inheritdoc} + */ + public function isLocal() { + return true; + } } } diff --git a/lib/private/files/storage/wrapper/wrapper.php b/lib/private/files/storage/wrapper/wrapper.php index f9adda80314..11ea9f71da7 100644 --- a/lib/private/files/storage/wrapper/wrapper.php +++ b/lib/private/files/storage/wrapper/wrapper.php @@ -432,4 +432,12 @@ class Wrapper implements \OC\Files\Storage\Storage { public function test() { return $this->storage->test(); } + + /** + * Returns the wrapped storage's value for isLocal() + * @return bool wrapped storage's isLocal() value + */ + public function isLocal() { + return $this->storage->isLocal(); + } } diff --git a/lib/private/files/type/detection.php b/lib/private/files/type/detection.php index d7cc9ebbf4e..11e439032ce 100644 --- a/lib/private/files/type/detection.php +++ b/lib/private/files/type/detection.php @@ -72,11 +72,12 @@ class Detection { and function_exists('finfo_file') and $finfo = finfo_open(FILEINFO_MIME) ) { $info = @strtolower(finfo_file($finfo, $path)); + finfo_close($finfo); if ($info) { $mimeType = substr($info, 0, strpos($info, ';')); return empty($mimeType) ? 'application/octet-stream' : $mimeType; } - finfo_close($finfo); + } $isWrapped = (strpos($path, '://') !== false) and (substr($path, 0, 7) === 'file://'); if (!$isWrapped and $mimeType === 'application/octet-stream' && function_exists("mime_content_type")) { diff --git a/lib/private/files/view.php b/lib/private/files/view.php index 147bbed1ef3..530aa8f7514 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -787,14 +787,7 @@ class View { * @param string $path * @param boolean $includeMountPoints whether to add mountpoint sizes, * defaults to true - * @return array - * - * returns an associative array with the following keys: - * - size - * - mtime - * - mimetype - * - encrypted - * - versioned + * @return \OC\Files\FileInfo | false */ public function getFileInfo($path, $includeMountPoints = true) { $data = array(); @@ -847,10 +840,13 @@ class View { $data['permissions'] = $permissions; } } + if (!$data) { + return false; + } $data = \OC_FileProxy::runPostProxies('getFileInfo', $path, $data); - return $data; + return new FileInfo($path, $storage, $internalPath, $data); } /** @@ -858,7 +854,7 @@ class View { * * @param string $directory path under datadirectory * @param string $mimetype_filter limit returned content to this mimetype or mimepart - * @return array + * @return FileInfo[] */ public function getDirectoryContent($directory, $mimetype_filter = '') { $result = array(); @@ -884,7 +880,11 @@ class View { $watcher->checkUpdate($internalPath); } - $files = $cache->getFolderContents($internalPath); //TODO: mimetype_filter + $files = array(); + $contents = $cache->getFolderContents($internalPath); //TODO: mimetype_filter + foreach ($contents as $content) { + $files[] = new FileInfo($path . '/' . $content['name'], $storage, $content['path'], $content); + } $permissions = $permissionsCache->getDirectoryPermissions($cache->getId($internalPath), $user); $ids = array(); @@ -942,7 +942,7 @@ class View { break; } } - $files[] = $rootEntry; + $files[] = new FileInfo($path . '/' . $rootEntry['name'], $subStorage, '', $rootEntry); } } } @@ -964,6 +964,7 @@ class View { $result = $files; } } + return $result; } @@ -971,12 +972,15 @@ class View { * change file metadata * * @param string $path - * @param array $data + * @param array | \OCP\Files\FileInfo $data * @return int * * returns the fileid of the updated file */ public function putFileInfo($path, $data) { + if ($data instanceof FileInfo) { + $data = $data->getData(); + } $path = Filesystem::normalizePath($this->fakeRoot . '/' . $path); /** * @var \OC\Files\Storage\Storage $storage @@ -1001,7 +1005,7 @@ class View { * search for files with the name matching $query * * @param string $query - * @return array + * @return FileInfo[] */ public function search($query) { return $this->searchCommon('%' . $query . '%', 'search'); @@ -1011,7 +1015,7 @@ class View { * search for files by mimetype * * @param string $mimetype - * @return array + * @return FileInfo[] */ public function searchByMime($mimetype) { return $this->searchCommon($mimetype, 'searchByMime'); @@ -1020,7 +1024,7 @@ class View { /** * @param string $query * @param string $method - * @return array + * @return FileInfo[] */ private function searchCommon($query, $method) { $files = array(); @@ -1034,8 +1038,9 @@ class View { $results = $cache->$method($query); foreach ($results as $result) { if (substr($mountPoint . $result['path'], 0, $rootLength + 1) === $this->fakeRoot . '/') { + $internalPath = $result['path']; $result['path'] = substr($mountPoint . $result['path'], $rootLength); - $files[] = $result; + $files[] = new FileInfo($mountPoint . $result['path'], $storage, $internalPath, $result); } } @@ -1049,8 +1054,9 @@ class View { $results = $cache->$method($query); if ($results) { foreach ($results as $result) { + $internalPath = $result['path']; $result['path'] = $relativeMountPoint . $result['path']; - $files[] = $result; + $files[] = new FileInfo($mountPoint . $result['path'], $storage, $internalPath, $result); } } } diff --git a/lib/private/group/manager.php b/lib/private/group/manager.php index bf469d51d12..9b433b64fd4 100644 --- a/lib/private/group/manager.php +++ b/lib/private/group/manager.php @@ -76,12 +76,7 @@ class Manager extends PublicEmitter { if (isset($this->cachedGroups[$gid])) { return $this->cachedGroups[$gid]; } - foreach ($this->backends as $backend) { - if ($backend->groupExists($gid)) { - return $this->getGroupObject($gid); - } - } - return null; + return $this->getGroupObject($gid); } protected function getGroupObject($gid) { @@ -91,6 +86,9 @@ class Manager extends PublicEmitter { $backends[] = $backend; } } + if (count($backends) === 0) { + return null; + } $this->cachedGroups[$gid] = new Group($gid, $backends, $this->userManager, $this); return $this->cachedGroups[$gid]; } @@ -110,8 +108,8 @@ class Manager extends PublicEmitter { public function createGroup($gid) { if (!$gid) { return false; - } else if ($this->groupExists($gid)) { - return $this->get($gid); + } else if ($group = $this->get($gid)) { + return $group; } else { $this->emit('\OC\Group', 'preCreate', array($gid)); foreach ($this->backends as $backend) { diff --git a/lib/private/helper.php b/lib/private/helper.php index 580f81acc62..58cb1b88d66 100644 --- a/lib/private/helper.php +++ b/lib/private/helper.php @@ -804,18 +804,22 @@ class OC_Helper { /** * @brief calculates the maximum upload size respecting system settings, free space and user quota * - * @param $dir the current folder where the user currently operates - * @return number of bytes representing + * @param string $dir the current folder where the user currently operates + * @param int $freeSpace the number of bytes free on the storage holding $dir, if not set this will be received from the storage directly + * @return int number of bytes representing */ - public static function maxUploadFilesize($dir) { - return min(self::freeSpace($dir), self::uploadLimit()); + public static function maxUploadFilesize($dir, $freeSpace = null) { + if (is_null($freeSpace)){ + $freeSpace = self::freeSpace($dir); + } + return min($freeSpace, self::uploadLimit()); } /** * Calculate free space left within user quota * - * @param $dir the current folder where the user currently operates - * @return number of bytes representing + * @param string $dir the current folder where the user currently operates + * @return int number of bytes representing */ public static function freeSpace($dir) { $freeSpace = \OC\Files\Filesystem::free_space($dir); diff --git a/lib/private/image.php b/lib/private/image.php index 54232234fe7..42afa35ea56 100644 --- a/lib/private/image.php +++ b/lib/private/image.php @@ -409,14 +409,14 @@ class OC_Image { /** * @brief Loads an image from a local file. - * @param $imageref The path to a local file. + * @param $imagePath The path to a local file. * @returns An image resource or false on error */ public function loadFromFile($imagePath=false) { // exif_imagetype throws "read error!" if file is less than 12 byte if(!@is_file($imagePath) || !file_exists($imagePath) || filesize($imagePath) < 12 || !is_readable($imagePath)) { // Debug output disabled because this method is tried before loadFromBase64? - OC_Log::write('core', 'OC_Image->loadFromFile, couldn\'t load: '.$imagePath, OC_Log::DEBUG); + OC_Log::write('core', 'OC_Image->loadFromFile, couldn\'t load: ' . (string) urlencode($imagePath), OC_Log::DEBUG); return false; } $iType = exif_imagetype($imagePath); diff --git a/lib/private/l10n.php b/lib/private/l10n.php index 0aa949ba9be..1d8152c5844 100644 --- a/lib/private/l10n.php +++ b/lib/private/l10n.php @@ -132,10 +132,10 @@ class OC_L10N implements \OCP\IL10N { $i18ndir = self::findI18nDir($app); // Localization is in /l10n, Texts are in $i18ndir // (Just no need to define date/time format etc. twice) - if((OC_Helper::issubdirectory($i18ndir.$lang.'.php', OC_App::getAppPath($app).'/l10n/') - || OC_Helper::issubdirectory($i18ndir.$lang.'.php', OC::$SERVERROOT.'/core/l10n/') + if((OC_Helper::issubdirectory($i18ndir.$lang.'.php', OC::$SERVERROOT.'/core/l10n/') || OC_Helper::issubdirectory($i18ndir.$lang.'.php', OC::$SERVERROOT.'/lib/l10n/') || OC_Helper::issubdirectory($i18ndir.$lang.'.php', OC::$SERVERROOT.'/settings') + || OC_Helper::issubdirectory($i18ndir.$lang.'.php', OC_App::getAppPath($app).'/l10n/') ) && file_exists($i18ndir.$lang.'.php')) { // Include the file, save the data from $CONFIG diff --git a/lib/private/legacy/appconfig.php b/lib/private/legacy/appconfig.php new file mode 100644 index 00000000000..46a8068c3b4 --- /dev/null +++ b/lib/private/legacy/appconfig.php @@ -0,0 +1,126 @@ +<?php +/** + * ownCloud + * + * @author Frank Karlitschek + * @author Jakob Sack + * @copyright 2012 Frank Karlitschek frank@owncloud.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + +/** + * This class provides an easy way for apps to store config values in the + * database. + */ +class OC_Appconfig { + /** + * @return \OCP\IAppConfig + */ + private static function getAppConfig() { + return \OC::$server->getAppConfig(); + } + + /** + * @brief Get all apps using the config + * @return array with app ids + * + * This function returns a list of all apps that have at least one + * entry in the appconfig table. + */ + public static function getApps() { + return self::getAppConfig()->getApps(); + } + + /** + * @brief Get the available keys for an app + * @param string $app the app we are looking for + * @return array with key names + * + * This function gets all keys of an app. Please note that the values are + * not returned. + */ + public static function getKeys($app) { + return self::getAppConfig()->getKeys($app); + } + + /** + * @brief Gets the config value + * @param string $app app + * @param string $key key + * @param string $default = null, default value if the key does not exist + * @return string the value or $default + * + * This function gets a value from the appconfig table. If the key does + * not exist the default value will be returned + */ + public static function getValue($app, $key, $default = null) { + return self::getAppConfig()->getValue($app, $key, $default); + } + + /** + * @brief check if a key is set in the appconfig + * @param string $app + * @param string $key + * @return bool + */ + public static function hasKey($app, $key) { + return self::getAppConfig()->hasKey($app, $key); + } + + /** + * @brief sets a value in the appconfig + * @param string $app app + * @param string $key key + * @param string $value value + * + * Sets a value. If the key did not exist before it will be created. + */ + public static function setValue($app, $key, $value) { + self::getAppConfig()->setValue($app, $key, $value); + } + + /** + * @brief Deletes a key + * @param string $app app + * @param string $key key + * + * Deletes a key. + */ + public static function deleteKey($app, $key) { + self::getAppConfig()->deleteKey($app, $key); + } + + /** + * @brief Remove app from appconfig + * @param string $app app + * + * Removes all keys in appconfig belonging to the app. + */ + public static function deleteApp($app) { + self::getAppConfig()->deleteApp($app); + } + + /** + * get multiply values, either the app or key can be used as wildcard by setting it to false + * + * @param app + * @param key + * @return array + */ + public static function getValues($app, $key) { + return self::getAppConfig()->getValues($app, $key); + } +} diff --git a/lib/private/memcache/memcached.php b/lib/private/memcache/memcached.php index 978e6c2eff1..075828eebad 100644 --- a/lib/private/memcache/memcached.php +++ b/lib/private/memcache/memcached.php @@ -18,8 +18,16 @@ class Memcached extends Cache { parent::__construct($prefix); if (is_null(self::$cache)) { self::$cache = new \Memcached(); - list($host, $port) = \OC_Config::getValue('memcached_server', array('localhost', 11211)); - self::$cache->addServer($host, $port); + $servers = \OC_Config::getValue('memcached_servers'); + if (!$servers) { + $server = \OC_Config::getValue('memcached_server'); + if ($server) { + $servers = array($server); + } else { + $servers = array(array('localhost', 11211)); + } + } + self::$cache->addServers($servers); } } diff --git a/lib/private/ocs/result.php b/lib/private/ocs/result.php index 84f06fa01c7..9f14e8da7e8 100644 --- a/lib/private/ocs/result.php +++ b/lib/private/ocs/result.php @@ -29,7 +29,13 @@ class OC_OCS_Result{ * @param $data mixed the data to return */ public function __construct($data=null, $code=100, $message=null) { - $this->data = $data; + if ($data === null) { + $this->data = array(); + } elseif (!is_array($data)) { + $this->data = array($this->data); + } else { + $this->data = $data; + } $this->statusCode = $code; $this->message = $message; } @@ -49,7 +55,7 @@ class OC_OCS_Result{ public function setItemsPerPage(int $items) { $this->perPage = $items; } - + /** * get the status code * @return int @@ -57,7 +63,7 @@ class OC_OCS_Result{ public function getStatusCode() { return $this->statusCode; } - + /** * get the meta data for the result * @return array @@ -76,15 +82,15 @@ class OC_OCS_Result{ return $meta; } - + /** * get the result data - * @return array|string|int + * @return array */ public function getData() { return $this->data; } - + /** * return bool if the method succedded * @return bool diff --git a/lib/private/preview/office.php b/lib/private/preview/office.php index 7a4826c76ec..02bb22e9b94 100644 --- a/lib/private/preview/office.php +++ b/lib/private/preview/office.php @@ -6,7 +6,7 @@ * See the COPYING-README file. */ //both, libreoffice backend and php fallback, need imagick -if (extension_loaded('imagick')) { +if (extension_loaded('imagick') && count(@\Imagick::queryFormats("PDF")) === 1) { $isShellExecEnabled = \OC_Helper::is_function_enabled('shell_exec'); // LibreOffice preview is currently not supported on Windows diff --git a/lib/private/preview/pdf.php b/lib/private/preview/pdf.php index cc974b68818..d390b4fc677 100644 --- a/lib/private/preview/pdf.php +++ b/lib/private/preview/pdf.php @@ -7,7 +7,7 @@ */ namespace OC\Preview; -if (extension_loaded('imagick')) { +if (extension_loaded('imagick') && count(@\Imagick::queryFormats("PDF")) === 1) { class PDF extends Provider { diff --git a/lib/private/preview/svg.php b/lib/private/preview/svg.php index b49e51720fa..9a73fff9467 100644 --- a/lib/private/preview/svg.php +++ b/lib/private/preview/svg.php @@ -7,7 +7,7 @@ */ namespace OC\Preview; -if (extension_loaded('imagick')) { +if (extension_loaded('imagick') && count(@\Imagick::queryFormats("SVG")) === 1) { class SVG extends Provider { diff --git a/lib/private/preview/unknown.php b/lib/private/preview/unknown.php index 4747f9e25ed..2d3b5c5655e 100644 --- a/lib/private/preview/unknown.php +++ b/lib/private/preview/unknown.php @@ -22,7 +22,7 @@ class Unknown extends Provider { $svgPath = substr_replace($path, 'svg', -3); - if (extension_loaded('imagick') && file_exists($svgPath)) { + if (extension_loaded('imagick') && file_exists($svgPath) && count(@\Imagick::queryFormats("SVG")) === 1) { // http://www.php.net/manual/de/imagick.setresolution.php#85284 $svg = new \Imagick(); diff --git a/lib/private/request.php b/lib/private/request.php index ee3d2fd54db..a7e7bd0ea1d 100755 --- a/lib/private/request.php +++ b/lib/private/request.php @@ -11,6 +11,7 @@ class OC_Request { const USER_AGENT_IE = '/MSIE/'; // Android Chrome user agent: https://developers.google.com/chrome/mobile/docs/user-agent const USER_AGENT_ANDROID_MOBILE_CHROME = '#Android.*Chrome/[.0-9]*#'; + const USER_AGENT_FREEBOX = '#^Mozilla/5\.0$#'; /** * @brief Check overwrite condition diff --git a/lib/private/response.php b/lib/private/response.php index 5e941acbb4b..71c538fb311 100644 --- a/lib/private/response.php +++ b/lib/private/response.php @@ -153,7 +153,11 @@ class OC_Response { * @param string $type disposition type, either 'attachment' or 'inline' */ static public function setContentDispositionHeader( $filename, $type = 'attachment' ) { - if (OC_Request::isUserAgent(array(OC_Request::USER_AGENT_IE, OC_Request::USER_AGENT_ANDROID_MOBILE_CHROME))) { + if (OC_Request::isUserAgent(array( + OC_Request::USER_AGENT_IE, + OC_Request::USER_AGENT_ANDROID_MOBILE_CHROME, + OC_Request::USER_AGENT_FREEBOX + ))) { header( 'Content-Disposition: ' . rawurlencode($type) . '; filename="' . rawurlencode( $filename ) . '"' ); } else { header( 'Content-Disposition: ' . rawurlencode($type) . '; filename*=UTF-8\'\'' . rawurlencode( $filename ) diff --git a/lib/private/server.php b/lib/private/server.php index c9e593ec2ed..fc8f170dc4a 100644 --- a/lib/private/server.php +++ b/lib/private/server.php @@ -124,6 +124,9 @@ class Server extends SimpleContainer implements IServerContainer { $this->registerService('AllConfig', function($c) { return new \OC\AllConfig(); }); + $this->registerService('AppConfig', function ($c) { + return new \OC\AppConfig(\OC_DB::getConnection()); + }); $this->registerService('L10NFactory', function($c) { return new \OC\L10N\Factory(); }); @@ -270,6 +273,15 @@ class Server extends SimpleContainer implements IServerContainer { } /** + * Returns the app config manager + * + * @return \OCP\IAppConfig + */ + function getAppConfig(){ + return $this->query('AppConfig'); + } + + /** * get an L10N instance * @param $app string appid * @return \OC_L10N diff --git a/lib/private/setup/mysql.php b/lib/private/setup/mysql.php index d97b6d2602f..b2c28173b1c 100644 --- a/lib/private/setup/mysql.php +++ b/lib/private/setup/mysql.php @@ -3,13 +3,13 @@ namespace OC\Setup; class MySQL extends AbstractDatabase { - public $dbprettyname = 'MySQL'; + public $dbprettyname = 'MySQL/MariaDB'; public function setupDatabase($username) { //check if the database user has admin right $connection = @mysql_connect($this->dbhost, $this->dbuser, $this->dbpassword); if(!$connection) { - throw new \DatabaseSetupException($this->trans->t('MySQL username and/or password not valid'), + throw new \DatabaseSetupException($this->trans->t('MySQL/MariaDB username and/or password not valid'), $this->trans->t('You need to enter either an existing account or the administrator.')); } $oldUser=\OC_Config::getValue('dbuser', false); @@ -82,14 +82,14 @@ class MySQL extends AbstractDatabase { $query = "CREATE USER '$name'@'localhost' IDENTIFIED BY '$password'"; $result = mysql_query($query, $connection); if (!$result) { - throw new \DatabaseSetupException($this->trans->t("MySQL user '%s'@'localhost' exists already.", array($name)), - $this->trans->t("Drop this user from MySQL", array($name))); + throw new \DatabaseSetupException($this->trans->t("MySQL/MariaDB user '%s'@'localhost' exists already.", array($name)), + $this->trans->t("Drop this user from MySQL/MariaDB", array($name))); } $query = "CREATE USER '$name'@'%' IDENTIFIED BY '$password'"; $result = mysql_query($query, $connection); if (!$result) { - throw new \DatabaseSetupException($this->trans->t("MySQL user '%s'@'%%' already exists", array($name)), - $this->trans->t("Drop this user from MySQL.")); + throw new \DatabaseSetupException($this->trans->t("MySQL/MariaDB user '%s'@'%%' already exists", array($name)), + $this->trans->t("Drop this user from MySQL/MariaDB.")); } } } diff --git a/lib/private/share/searchresultsorter.php b/lib/private/share/searchresultsorter.php new file mode 100644 index 00000000000..fbf77179097 --- /dev/null +++ b/lib/private/share/searchresultsorter.php @@ -0,0 +1,59 @@ +<?php +/** + * Copyright (c) 2014 Arthur Schiwon <blizzz@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + * + */ +namespace OC\Share; + +class SearchResultSorter { + private $search; + private $encoding; + private $key; + private $log; + + /** + * @param $search the search term as was given by the user + * @param $key the array key containing the value that should be compared + * against + * @param $encoding optional, encoding to use, defaults to UTF-8 + * @param $log optional, an \OC\Log instance + */ + public function __construct($search, $key, \OC\Log $log = null, $encoding = 'UTF-8') { + $this->encoding = $encoding; + $this->key = $key; + $this->log = $log; + $this->search = mb_strtolower($search, $this->encoding); + } + + /** + * User and Group names matching the search term at the beginning shall appear + * on top of the share dialog. Following entries in alphabetical order. + * Callback function for usort. http://php.net/usort + */ + public function sort($a, $b) { + if(!isset($a[$this->key]) || !isset($b[$this->key])) { + if(!is_null($this->log)) { + $this->log->error('Sharing dialogue: cannot sort due to ' . + 'missing array key', array('app' => 'core')); + } + return 0; + } + $nameA = mb_strtolower($a[$this->key], $this->encoding); + $nameB = mb_strtolower($b[$this->key], $this->encoding); + $i = mb_strpos($nameA, $this->search, 0, $this->encoding); + $j = mb_strpos($nameB, $this->search, 0, $this->encoding); + + if($i === $j || $i > 0 && $j > 0) { + return strcmp(mb_strtolower($nameA, $this->encoding), + mb_strtolower($nameB, $this->encoding)); + } elseif ($i === 0) { + return -1; + } else { + return 1; + } + } +} + diff --git a/lib/private/user.php b/lib/private/user.php index c78fb094c4d..a8e7967783e 100644 --- a/lib/private/user.php +++ b/lib/private/user.php @@ -205,6 +205,9 @@ class OC_User { // Delete user files in /data/ OC_Helper::rmdirr(\OC_User::getHome($uid)); + // Delete the users entry in the storage table + \OC\Files\Cache\Storage::remove('home::' . $uid); + // Remove it from the Cache self::getManager()->delete($uid); } diff --git a/lib/public/files/fileinfo.php b/lib/public/files/fileinfo.php new file mode 100644 index 00000000000..68ce45d3fa1 --- /dev/null +++ b/lib/public/files/fileinfo.php @@ -0,0 +1,138 @@ +<?php +/** + * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ +namespace OCP\Files; + +interface FileInfo { + const TYPE_FILE = 'file'; + const TYPE_FOLDER = 'folder'; + + /** + * Get the Etag of the file or folder + * + * @return string + */ + public function getEtag(); + + /** + * Get the size in bytes for the file or folder + * + * @return int + */ + public function getSize(); + + /** + * Get the last modified date as timestamp for the file or folder + * + * @return int + */ + public function getMtime(); + + /** + * Get the name of the file or folder + * + * @return string + */ + public function getName(); + + /** + * Get the path relative to the storage + * + * @return string + */ + public function getInternalPath(); + + /** + * Get the absolute path + * + * @return string + */ + public function getPath(); + + /** + * Get the full mimetype of the file or folder i.e. 'image/png' + * + * @return string + */ + public function getMimetype(); + + /** + * Get the first part of the mimetype of the file or folder i.e. 'image' + * + * @return string + */ + public function getMimePart(); + + /** + * Get the storage the file or folder is storage on + * + * @return \OCP\Files\Storage + */ + public function getStorage(); + + /** + * Get the file id of the file or folder + * + * @return int + */ + public function getId(); + + /** + * Check whether the file is encrypted + * + * @return bool + */ + public function isEncrypted(); + + /** + * Get the permissions of the file or folder as bitmasked combination of the following constants + * \OCP\PERMISSION_CREATE + * \OCP\PERMISSION_READ + * \OCP\PERMISSION_UPDATE + * \OCP\PERMISSION_DELETE + * \OCP\PERMISSION_SHARE + * \OCP\PERMISSION_ALL + * + * @return int + */ + public function getPermissions(); + + /** + * Check whether this is a file or a folder + * + * @return \OCP\Files\FileInfo::TYPE_FILE | \OCP\Files\FileInfo::TYPE_FOLDER + */ + public function getType(); + + /** + * Check if the file or folder is readable + * + * @return bool + */ + public function isReadable(); + + /** + * Check if a file is writable + * + * @return bool + */ + public function isUpdateable(); + + /** + * Check if a file or folder can be deleted + * + * @return bool + */ + public function isDeletable(); + + /** + * Check if a file or folder can be shared + * + * @return bool + */ + public function isShareable(); +} diff --git a/lib/public/files/storage.php b/lib/public/files/storage.php index 01a15851d46..5ec8ac6245c 100644 --- a/lib/public/files/storage.php +++ b/lib/public/files/storage.php @@ -316,4 +316,15 @@ interface Storage { * @return string */ public function getETag($path); + + /** + * Returns whether the storage is local, which means that files + * are stored on the local filesystem instead of remotely. + * Calling getLocalFile() for local storages should always + * return the local files, whereas for non-local storages + * it might return a temporary file. + * + * @return bool true if the files are stored locally, false otherwise + */ + public function isLocal(); } diff --git a/lib/public/iappconfig.php b/lib/public/iappconfig.php new file mode 100644 index 00000000000..3b6484c09d5 --- /dev/null +++ b/lib/public/iappconfig.php @@ -0,0 +1,91 @@ +<?php +/** + * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ +namespace OCP; + +/** + * This class provides an easy way for apps to store config values in the + * database. + */ +interface IAppConfig { + /** + * @brief check if a key is set in the appconfig + * @param string $app + * @param string $key + * @return bool + */ + public function hasKey($app, $key); + + /** + * @brief Gets the config value + * @param string $app app + * @param string $key key + * @param string $default = null, default value if the key does not exist + * @return string the value or $default + * + * This function gets a value from the appconfig table. If the key does + * not exist the default value will be returned + */ + public function getValue($app, $key, $default = null); + + /** + * @brief Deletes a key + * @param string $app app + * @param string $key key + * @return bool + * + * Deletes a key. + */ + public function deleteKey($app, $key); + + /** + * @brief Get the available keys for an app + * @param string $app the app we are looking for + * @return array with key names + * + * This function gets all keys of an app. Please note that the values are + * not returned. + */ + public function getKeys($app); + + /** + * get multiply values, either the app or key can be used as wildcard by setting it to false + * + * @param app + * @param key + * @return array + */ + public function getValues($app, $key); + + /** + * @brief sets a value in the appconfig + * @param string $app app + * @param string $key key + * @param string $value value + * + * Sets a value. If the key did not exist before it will be created. + */ + public function setValue($app, $key, $value); + + /** + * @brief Get all apps using the config + * @return array with app ids + * + * This function returns a list of all apps that have at least one + * entry in the appconfig table. + */ + public function getApps(); + + /** + * @brief Remove app from appconfig + * @param string $app app + * @return bool + * + * Removes all keys in appconfig belonging to the app. + */ + public function deleteApp($app); +} diff --git a/lib/public/iservercontainer.php b/lib/public/iservercontainer.php index 5473f3ee334..dcb00caf496 100644 --- a/lib/public/iservercontainer.php +++ b/lib/public/iservercontainer.php @@ -114,6 +114,13 @@ interface IServerContainer { function getConfig(); /** + * Returns the app config manager + * + * @return \OCP\IAppConfig + */ + function getAppConfig(); + + /** * get an L10N instance * @param $app string appid * @return \OCP\IL10N diff --git a/lib/public/share.php b/lib/public/share.php index 1225cfa0d43..f6c44a8322b 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -1153,7 +1153,7 @@ class Share { $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `*PREFIX*share`.`parent`, `uid_owner`, ' .'`share_type`, `share_with`, `file_source`, `path`, `file_target`, ' .'`permissions`, `expiration`, `storage`, `*PREFIX*filecache`.`parent` as `file_parent`, ' - .'`name`, `mtime`, `mimetype`, `mimepart`, `size`, `encrypted`, `etag`, `mail_send`'; + .'`name`, `mtime`, `mimetype`, `mimepart`, `size`, `unencrypted_size`, `encrypted`, `etag`, `mail_send`'; } else { $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `item_target`, `*PREFIX*share`.`parent`, `share_type`, `share_with`, `uid_owner`, diff --git a/lib/public/util.php b/lib/public/util.php index d8497e29cfc..570283e2a8a 100644 --- a/lib/public/util.php +++ b/lib/public/util.php @@ -121,7 +121,7 @@ class Util { /** * get l10n object * @param string $application - * @return OC_L10N + * @return \OC_L10N */ public static function getL10N( $application ) { return \OC_L10N::get( $application ); @@ -460,11 +460,12 @@ class Util { /** * calculates the maximum upload size respecting system settings, free space and user quota * - * @param $dir the current folder where the user currently operates + * @param string $dir the current folder where the user currently operates + * @param int $free the number of bytes free on the storage holding $dir, if not set this will be received from the storage directly * @return number of bytes representing */ - public static function maxUploadFilesize($dir) { - return \OC_Helper::maxUploadFilesize($dir); + public static function maxUploadFilesize($dir, $free = null) { + return \OC_Helper::maxUploadFilesize($dir, $free); } /** diff --git a/settings/js/personal.js b/settings/js/personal.js index e6e1d538a19..3b876467756 100644 --- a/settings/js/personal.js +++ b/settings/js/personal.js @@ -158,7 +158,7 @@ $(document).ready(function(){ if(typeof timeout !== 'undefined'){ clearTimeout(timeout); } - timeout = setTimeout('changeDisplayName()',1000); + timeout = setTimeout(changeDisplayName, 1000); } }); @@ -173,7 +173,7 @@ $(document).ready(function(){ if(typeof timeout !== 'undefined'){ clearTimeout(timeout); } - timeout = setTimeout('changeEmailAddress()',1000); + timeout = setTimeout(changeEmailAddress, 1000); } }); diff --git a/tests/lib/appconfig.php b/tests/lib/appconfig.php index 23dd2549e32..6ae790a9edd 100644 --- a/tests/lib/appconfig.php +++ b/tests/lib/appconfig.php @@ -1,6 +1,7 @@ <?php /** * Copyright (c) 2013 Christopher Schäpers <christopher@schaepers.it> + * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl> * This file is licensed under the Affero General Public License version 3 or * later. * See the COPYING-README file. @@ -41,6 +42,7 @@ class Test_Appconfig extends PHPUnit_Framework_TestCase { while ($row = $result->fetchRow()) { $expected[] = $row['appid']; } + sort($expected); $apps = \OC_Appconfig::getApps(); $this->assertEquals($expected, $apps); } @@ -52,6 +54,7 @@ class Test_Appconfig extends PHPUnit_Framework_TestCase { while($row = $result->fetchRow()) { $expected[] = $row["configkey"]; } + sort($expected); $keys = \OC_Appconfig::getKeys('testapp'); $this->assertEquals($expected, $keys); } diff --git a/tests/lib/group/manager.php b/tests/lib/group/manager.php index 9d3adf51a0c..90f0e1b35e2 100644 --- a/tests/lib/group/manager.php +++ b/tests/lib/group/manager.php @@ -116,16 +116,22 @@ class Manager extends \PHPUnit_Framework_TestCase { /** * @var \PHPUnit_Framework_MockObject_MockObject | \OC_Group_Backend $backend */ + $backendGroupCreated = false; $backend = $this->getMock('\OC_Group_Database'); $backend->expects($this->any()) ->method('groupExists') ->with('group1') - ->will($this->returnValue(false)); + ->will($this->returnCallback(function () use (&$backendGroupCreated) { + return $backendGroupCreated; + })); $backend->expects($this->once()) ->method('implementsActions') ->will($this->returnValue(true)); $backend->expects($this->once()) - ->method('createGroup'); + ->method('createGroup') + ->will($this->returnCallback(function () use (&$backendGroupCreated) { + $backendGroupCreated = true; + }));; /** * @var \OC\User\Manager $userManager @@ -170,6 +176,10 @@ class Manager extends \PHPUnit_Framework_TestCase { ->method('getGroups') ->with('1') ->will($this->returnValue(array('group1'))); + $backend->expects($this->once()) + ->method('groupExists') + ->with('group1') + ->will($this->returnValue(true)); /** * @var \OC\User\Manager $userManager @@ -193,6 +203,9 @@ class Manager extends \PHPUnit_Framework_TestCase { ->method('getGroups') ->with('1') ->will($this->returnValue(array('group1'))); + $backend1->expects($this->any()) + ->method('groupExists') + ->will($this->returnValue(true)); /** * @var \PHPUnit_Framework_MockObject_MockObject | \OC_Group_Backend $backend2 @@ -202,6 +215,9 @@ class Manager extends \PHPUnit_Framework_TestCase { ->method('getGroups') ->with('1') ->will($this->returnValue(array('group12', 'group1'))); + $backend2->expects($this->any()) + ->method('groupExists') + ->will($this->returnValue(true)); /** * @var \OC\User\Manager $userManager @@ -228,6 +244,9 @@ class Manager extends \PHPUnit_Framework_TestCase { ->method('getGroups') ->with('1', 2, 1) ->will($this->returnValue(array('group1'))); + $backend1->expects($this->any()) + ->method('groupExists') + ->will($this->returnValue(true)); /** * @var \PHPUnit_Framework_MockObject_MockObject | \OC_Group_Backend $backend2 @@ -237,6 +256,9 @@ class Manager extends \PHPUnit_Framework_TestCase { ->method('getGroups') ->with('1', 1, 0) ->will($this->returnValue(array('group12'))); + $backend2->expects($this->any()) + ->method('groupExists') + ->will($this->returnValue(true)); /** * @var \OC\User\Manager $userManager @@ -263,6 +285,10 @@ class Manager extends \PHPUnit_Framework_TestCase { ->method('getUserGroups') ->with('user1') ->will($this->returnValue(array('group1'))); + $backend->expects($this->any()) + ->method('groupExists') + ->with('group1') + ->will($this->returnValue(true)); /** * @var \OC\User\Manager $userManager @@ -286,6 +312,10 @@ class Manager extends \PHPUnit_Framework_TestCase { ->method('getUserGroups') ->with('user1') ->will($this->returnValue(array('group1'))); + $backend1->expects($this->any()) + ->method('groupExists') + ->will($this->returnValue(true)); + /** * @var \PHPUnit_Framework_MockObject_MockObject | \OC_Group_Backend $backend2 */ @@ -294,6 +324,9 @@ class Manager extends \PHPUnit_Framework_TestCase { ->method('getUserGroups') ->with('user1') ->will($this->returnValue(array('group1', 'group2'))); + $backend1->expects($this->any()) + ->method('groupExists') + ->will($this->returnValue(true)); /** * @var \OC\User\Manager $userManager diff --git a/tests/lib/request.php b/tests/lib/request.php index c6401a57144..1d77acc70ae 100644 --- a/tests/lib/request.php +++ b/tests/lib/request.php @@ -118,6 +118,21 @@ class Test_Request extends PHPUnit_Framework_TestCase { ), true ), + array( + 'Mozilla/5.0 (X11; Linux i686; rv:24.0) Gecko/20100101 Firefox/24.0', + OC_Request::USER_AGENT_FREEBOX, + false + ), + array( + 'Mozilla/5.0', + OC_Request::USER_AGENT_FREEBOX, + true + ), + array( + 'Fake Mozilla/5.0', + OC_Request::USER_AGENT_FREEBOX, + false + ), ); } } diff --git a/tests/lib/share/searchresultsorter.php b/tests/lib/share/searchresultsorter.php new file mode 100644 index 00000000000..eaf93400a7d --- /dev/null +++ b/tests/lib/share/searchresultsorter.php @@ -0,0 +1,47 @@ +<?php +/** +* ownCloud +* +* @author Arthur Schiwon +* @copyright 2014 Arthur Schiwon <blizzz@owncloud.com> +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE +* License as published by the Free Software Foundation; either +* version 3 of the License, or any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU AFFERO GENERAL PUBLIC LICENSE for more details. +* +* You should have received a copy of the GNU Affero General Public +* License along with this library. If not, see <http://www.gnu.org/licenses/>. +*/ + +class Test_Share_Search extends \PHPUnit_Framework_TestCase { + public function testSort() { + $search = 'lin'; + $sorter = new \OC\Share\SearchResultSorter($search, 'foobar'); + + $result = array( + array('foobar' => 'woot'), + array('foobar' => 'linux'), + array('foobar' => 'Linus'), + array('foobar' => 'Bicyclerepairwoman'), + ); + + usort($result, array($sorter, 'sort')); + $this->assertTrue($result[0]['foobar'] === 'Linus'); + $this->assertTrue($result[1]['foobar'] === 'linux'); + $this->assertTrue($result[2]['foobar'] === 'Bicyclerepairwoman'); + $this->assertTrue($result[3]['foobar'] === 'woot'); + } + + /** + * @expectedException PHPUnit_Framework_Error + */ + public function testSortWrongLog() { + $sorter = new \OC\Share\SearchResultSorter('foo', 'bar', 'UTF-8', 'foobar'); + } +} |