summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/files/css/files.css24
-rw-r--r--apps/files/js/admin.js19
-rw-r--r--apps/files/js/filelist.js42
-rw-r--r--apps/files/js/files.js10
-rw-r--r--apps/files/lib/helper.php18
-rw-r--r--apps/files/templates/index.php17
-rw-r--r--apps/files/tests/ajax_rename.php8
-rw-r--r--apps/files_encryption/hooks/hooks.php17
-rw-r--r--apps/files_encryption/tests/hooks.php55
-rwxr-xr-xapps/files_encryption/tests/share.php70
-rwxr-xr-xapps/files_external/lib/config.php14
-rw-r--r--apps/files_external/tests/mountconfig.php25
-rw-r--r--apps/files_sharing/lib/cache.php12
-rw-r--r--apps/files_sharing/public.php3
-rw-r--r--apps/files_sharing/tests/cache.php137
-rw-r--r--apps/files_trashbin/js/filelist.js32
-rw-r--r--apps/user_ldap/group_ldap.php78
-rw-r--r--apps/user_ldap/lib/configuration.php3
-rw-r--r--apps/user_ldap/templates/settings.php1
19 files changed, 507 insertions, 78 deletions
diff --git a/apps/files/css/files.css b/apps/files/css/files.css
index 3ad167054c2..af863aca33e 100644
--- a/apps/files/css/files.css
+++ b/apps/files/css/files.css
@@ -20,7 +20,7 @@
padding: 10px;
font-weight: normal;
}
-#new>a {
+#new > a {
padding: 14px 10px;
position: relative;
top: 7px;
@@ -30,7 +30,7 @@
border-bottom-right-radius: 0;
border-bottom: none;
}
-#new>ul {
+#new > ul {
display: none;
position: fixed;
min-width: 112px;
@@ -39,16 +39,26 @@
padding-bottom: 0;
margin-top: 14px;
margin-left: -1px;
- text-align:left;
+ text-align: left;
background: #f8f8f8;
border: 1px solid #ddd;
border-radius: 5px;
border-top-left-radius: 0;
- box-shadow:0 2px 7px rgba(170,170,170,.4);
+ box-shadow: 0 2px 7px rgba(170,170,170,.4);
+}
+#new > ul > li {
+ height: 36px;
+ margin: 5px;
+ padding-left: 42px;
+ padding-bottom: 2px;
+ background-position: initial;
+ cursor: pointer;
+}
+#new > ul > li > p {
+ cursor: pointer;
+ padding-top: 7px;
+ padding-bottom: 7px;
}
-#new>ul>li { height:36px; margin:5px; padding-left:48px; padding-bottom:2px;
- background-repeat:no-repeat; cursor:pointer; }
-#new>ul>li>p { cursor:pointer; padding-top: 7px; padding-bottom: 7px;}
#new .error, #fileList .error {
color: #e9322d;
diff --git a/apps/files/js/admin.js b/apps/files/js/admin.js
index f735079fcbe..842b73c0cae 100644
--- a/apps/files/js/admin.js
+++ b/apps/files/js/admin.js
@@ -8,19 +8,22 @@
*
*/
-function switchPublicFolder()
-{
+function switchPublicFolder() {
var publicEnable = $('#publicEnable').is(':checked');
- var sharingaimGroup = $('input:radio[name=sharingaim]'); //find all radiobuttons of that group
+ // find all radiobuttons of that group
+ var sharingaimGroup = $('input:radio[name=sharingaim]');
$.each(sharingaimGroup, function(index, sharingaimItem) {
- sharingaimItem.disabled = !publicEnable; //set all buttons to the correct state
+ // set all buttons to the correct state
+ sharingaimItem.disabled = !publicEnable;
});
}
-$(document).ready(function(){
- switchPublicFolder(); // Execute the function after loading DOM tree
- $('#publicEnable').click(function(){
- switchPublicFolder(); // To get rid of onClick()
+$(document).ready(function() {
+ // Execute the function after loading DOM tree
+ switchPublicFolder();
+ $('#publicEnable').click(function() {
+ // To get rid of onClick()
+ switchPublicFolder();
});
$('#allowZipDownload').bind('change', function() {
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js
index d6cffde05de..550c10dba3e 100644
--- a/apps/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -11,6 +11,7 @@
/* global OC, t, n, FileList, FileActions, Files */
/* global procesSelection, dragOptions, SVGSupport, replaceSVG */
window.FileList={
+ appName: t('files', 'Files'),
useUndo:true,
postProcessList: function() {
$('#fileList tr').each(function() {
@@ -19,6 +20,21 @@ window.FileList={
});
},
/**
+ * Sets a new page title
+ */
+ setPageTitle: function(title){
+ if (title) {
+ title += ' - ';
+ } else {
+ title = '';
+ }
+ title += FileList.appName;
+ // Sets the page title with the " - ownCloud" suffix as in templates
+ window.document.title = title + ' - ' + oc_defaults.title;
+
+ return true;
+ },
+ /**
* Returns the tr element for a given file name
*/
findFileEl: function(fileName){
@@ -129,7 +145,7 @@ window.FileList={
if (loading) {
imgurl = OC.imagePath('core', 'loading.gif');
} else {
- imgurl = OC.imagePath('core', 'filetypes/file.png');
+ imgurl = OC.imagePath('core', 'filetypes/file');
}
var tr = this.createRow(
'file',
@@ -157,7 +173,7 @@ window.FileList={
var tr = this.createRow(
'dir',
name,
- OC.imagePath('core', 'filetypes/folder.png'),
+ OC.imagePath('core', 'filetypes/folder'),
OC.linkTo('files', 'index.php')+"?dir="+ encodeURIComponent($('#dir').val()+'/'+name).replace(/%2F/g, '/'),
size,
lastModified,
@@ -204,7 +220,16 @@ window.FileList={
return OC.linkTo('files', 'index.php')+"?dir="+ encodeURIComponent(dir).replace(/%2F/g, '/');
},
setCurrentDir: function(targetDir, changeUrl) {
- var url;
+ var url,
+ baseDir = OC.basename(targetDir);
+
+ if (baseDir !== '') {
+ FileList.setPageTitle(baseDir);
+ }
+ else {
+ FileList.setPageTitle();
+ }
+
$('#dir').val(targetDir);
if (changeUrl !== false) {
if (window.history.pushState && changeUrl !== false) {
@@ -847,7 +872,8 @@ window.FileList={
};
$(document).ready(function() {
- var isPublic = !!$('#isPublic').val();
+ var baseDir,
+ isPublic = !!$('#isPublic').val();
// handle upload events
var file_upload_start = $('#file_upload_start');
@@ -943,7 +969,7 @@ $(document).ready(function() {
uploadtext.attr('currentUploads', currentUploads);
var translatedText = n('files', 'Uploading %n file', 'Uploading %n files', currentUploads);
if (currentUploads === 0) {
- var img = OC.imagePath('core', 'filetypes/folder.png');
+ var img = OC.imagePath('core', 'filetypes/folder');
data.context.find('td.filename').attr('style','background-image:url('+img+')');
uploadtext.text(translatedText);
uploadtext.hide();
@@ -1003,7 +1029,7 @@ $(document).ready(function() {
if (data.errorThrown === 'abort') {
//cleanup uploading to a dir
var uploadtext = $('tr .uploadtext');
- var img = OC.imagePath('core', 'filetypes/folder.png');
+ var img = OC.imagePath('core', 'filetypes/folder');
uploadtext.parents('td.filename').attr('style','background-image:url('+img+')');
uploadtext.fadeOut();
uploadtext.attr('currentUploads', 0);
@@ -1016,7 +1042,7 @@ $(document).ready(function() {
if (data.errorThrown === 'abort') {
//cleanup uploading to a dir
var uploadtext = $('tr .uploadtext');
- var img = OC.imagePath('core', 'filetypes/folder.png');
+ var img = OC.imagePath('core', 'filetypes/folder');
uploadtext.parents('td.filename').attr('style','background-image:url('+img+')');
uploadtext.fadeOut();
uploadtext.attr('currentUploads', 0);
@@ -1132,5 +1158,7 @@ $(document).ready(function() {
}
}
+ FileList.setCurrentDir(parseCurrentDirFromUrl(), false);
+
FileList.createFileSummary();
});
diff --git a/apps/files/js/files.js b/apps/files/js/files.js
index fbac601f67a..f4546120702 100644
--- a/apps/files/js/files.js
+++ b/apps/files/js/files.js
@@ -734,6 +734,9 @@ Files.getMimeIcon = function(mime, ready) {
ready(Files.getMimeIcon.cache[mime]);
} else {
$.get( OC.filePath('files','ajax','mimeicon.php'), {mime: mime}, function(path) {
+ if(SVGSupport()){
+ path = path.substr(0, path.length-4) + '.svg';
+ }
Files.getMimeIcon.cache[mime]=path;
ready(Files.getMimeIcon.cache[mime]);
});
@@ -783,13 +786,16 @@ Files.lazyLoadPreview = function(path, mime, ready, width, height, etag) {
}
previewURL = previewURL.replace('(', '%28');
previewURL = previewURL.replace(')', '%29');
+ previewURL += '&forceIcon=0';
// preload image to prevent delay
// this will make the browser cache the image
var img = new Image();
img.onload = function(){
- //set preview thumbnail URL
- ready(previewURL);
+ // if loading the preview image failed (no preview for the mimetype) then img.width will < 5
+ if (img.width > 5) {
+ ready(previewURL);
+ }
}
img.src = previewURL;
});
diff --git a/apps/files/lib/helper.php b/apps/files/lib/helper.php
index ac8a2ad3200..b9e41a352bc 100644
--- a/apps/files/lib/helper.php
+++ b/apps/files/lib/helper.php
@@ -22,6 +22,7 @@ class Helper
public static function determineIcon($file) {
if($file['type'] === 'dir') {
$dir = $file['directory'];
+ $icon = \OC_Helper::mimetypeIcon('dir');
$absPath = \OC\Files\Filesystem::getView()->getAbsolutePath($dir.'/'.$file['name']);
$mount = \OC\Files\Filesystem::getMountManager()->find($absPath);
if (!is_null($mount)) {
@@ -29,21 +30,22 @@ class Helper
if (!is_null($sid)) {
$sid = explode(':', $sid);
if ($sid[0] === 'shared') {
- return \OC_Helper::mimetypeIcon('dir-shared');
+ $icon = \OC_Helper::mimetypeIcon('dir-shared');
}
if ($sid[0] !== 'local' and $sid[0] !== 'home') {
- return \OC_Helper::mimetypeIcon('dir-external');
+ $icon = \OC_Helper::mimetypeIcon('dir-external');
}
}
}
- return \OC_Helper::mimetypeIcon('dir');
+ }else{
+ if($file['isPreviewAvailable']) {
+ $pathForPreview = $file['directory'] . '/' . $file['name'];
+ return \OC_Helper::previewIcon($pathForPreview) . '&c=' . $file['etag'];
+ }
+ $icon = \OC_Helper::mimetypeIcon($file['mimetype']);
}
- if($file['isPreviewAvailable']) {
- $pathForPreview = $file['directory'] . '/' . $file['name'];
- return \OC_Helper::previewIcon($pathForPreview) . '&c=' . $file['etag'];
- }
- return \OC_Helper::mimetypeIcon($file['mimetype']);
+ return substr($icon, 0, -3) . 'svg';
}
/**
diff --git a/apps/files/templates/index.php b/apps/files/templates/index.php
index 939043b2c9f..ed15e46a5ac 100644
--- a/apps/files/templates/index.php
+++ b/apps/files/templates/index.php
@@ -5,12 +5,17 @@
<div id="new" class="button">
<a><?php p($l->t('New'));?></a>
<ul>
- <li style="background-image:url('<?php p(OCP\mimetype_icon('text/plain')) ?>')"
- data-type='file' data-newname='<?php p($l->t('New text file')) ?>.txt'><p><?php p($l->t('Text file'));?></p></li>
- <li style="background-image:url('<?php p(OCP\mimetype_icon('dir')) ?>')"
- data-type='folder' data-newname='<?php p($l->t('New folder')) ?>'><p><?php p($l->t('Folder'));?></p></li>
- <li style="background-image:url('<?php p(OCP\image_path('core', 'places/link.svg')) ?>')"
- data-type='web'><p><?php p($l->t('From link'));?></p></li>
+ <li class="icon icon-filetype-text"
+ data-type="file" data-newname="<?php p($l->t('New text file')) ?>.txt">
+ <p><?php p($l->t('Text file'));?></p>
+ </li>
+ <li class="icon icon-filetype-folder"
+ data-type="folder" data-newname="<?php p($l->t('New folder')) ?>">
+ <p><?php p($l->t('Folder'));?></p>
+ </li>
+ <li class="icon icon-link" data-type="web">
+ <p><?php p($l->t('From link'));?></p>
+ </li>
</ul>
</div>
<?php endif;?>
diff --git a/apps/files/tests/ajax_rename.php b/apps/files/tests/ajax_rename.php
index a1a5c8983ba..e53c0fb3dd1 100644
--- a/apps/files/tests/ajax_rename.php
+++ b/apps/files/tests/ajax_rename.php
@@ -110,7 +110,9 @@ class Test_OC_Files_App_Rename extends \PHPUnit_Framework_TestCase {
$this->assertEquals('/test', $result['data']['directory']);
$this->assertEquals(18, $result['data']['size']);
$this->assertEquals('httpd/unix-directory', $result['data']['mime']);
- $this->assertEquals(\OC_Helper::mimetypeIcon('dir'), $result['data']['icon']);
+ $icon = \OC_Helper::mimetypeIcon('dir');
+ $icon = substr($icon, 0, -3) . 'svg';
+ $this->assertEquals($icon, $result['data']['icon']);
$this->assertFalse($result['data']['isPreviewAvailable']);
}
@@ -165,7 +167,9 @@ class Test_OC_Files_App_Rename extends \PHPUnit_Framework_TestCase {
$this->assertEquals(18, $result['data']['size']);
$this->assertEquals('httpd/unix-directory', $result['data']['mime']);
$this->assertEquals('abcdef', $result['data']['etag']);
- $this->assertEquals(\OC_Helper::mimetypeIcon('dir'), $result['data']['icon']);
+ $icon = \OC_Helper::mimetypeIcon('dir');
+ $icon = substr($icon, 0, -3) . 'svg';
+ $this->assertEquals($icon, $result['data']['icon']);
$this->assertFalse($result['data']['isPreviewAvailable']);
}
diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php
index 3af43f10264..0b6c5adf3fb 100644
--- a/apps/files_encryption/hooks/hooks.php
+++ b/apps/files_encryption/hooks/hooks.php
@@ -501,11 +501,20 @@ class Hooks {
* @param array $params with the old path and the new path
*/
public static function preRename($params) {
- $util = new Util(new \OC_FilesystemView('/'), \OCP\User::getUser());
+ $user = \OCP\User::getUser();
+ $view = new \OC_FilesystemView('/');
+ $util = new Util($view, $user);
list($ownerOld, $pathOld) = $util->getUidAndFilename($params['oldpath']);
- self::$renamedFiles[$params['oldpath']] = array(
- 'uid' => $ownerOld,
- 'path' => $pathOld);
+
+ // we only need to rename the keys if the rename happens on the same mountpoint
+ // otherwise we perform a stream copy, so we get a new set of keys
+ $mp1 = $view->getMountPoint('/' . $user . '/files/' . $params['oldpath']);
+ $mp2 = $view->getMountPoint('/' . $user . '/files/' . $params['newpath']);
+ if ($mp1 === $mp2) {
+ self::$renamedFiles[$params['oldpath']] = array(
+ 'uid' => $ownerOld,
+ 'path' => $pathOld);
+ }
}
/**
diff --git a/apps/files_encryption/tests/hooks.php b/apps/files_encryption/tests/hooks.php
index 7d926caea1b..d0e4b5f732e 100644
--- a/apps/files_encryption/tests/hooks.php
+++ b/apps/files_encryption/tests/hooks.php
@@ -47,6 +47,7 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase {
public $rootView; // view on /data/user
public $data;
public $filename;
+ public $folder;
public static function setUpBeforeClass() {
// reset backend
@@ -89,6 +90,7 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase {
// init short data
$this->data = 'hats';
$this->filename = 'enc_hooks_tests-' . uniqid() . '.txt';
+ $this->folder = 'enc_hooks_tests_folder-' . uniqid();
}
@@ -268,4 +270,57 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase {
}
}
+ /**
+ * @brief test rename operation
+ */
+ function testRenameHook() {
+
+ // save file with content
+ $cryptedFile = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->filename, $this->data);
+
+ // test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ // check if keys exists
+ $this->assertTrue($this->rootView->file_exists(
+ '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
+
+ $this->assertTrue($this->rootView->file_exists(
+ '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/'
+ . $this->filename . '.key'));
+
+ // make subfolder
+ $this->rootView->mkdir('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder);
+
+ $this->assertTrue($this->rootView->is_dir('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder));
+
+ // move the file out of the shared folder
+ $root = $this->rootView->getRoot();
+ $this->rootView->chroot('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/');
+ $this->rootView->rename($this->filename, '/' . $this->folder . '/' . $this->filename);
+ $this->rootView->chroot($root);
+
+ $this->assertFalse($this->rootView->file_exists('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->filename));
+ $this->assertTrue($this->rootView->file_exists('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder . '/' . $this->filename));
+
+ // keys should be renamed too
+ $this->assertFalse($this->rootView->file_exists(
+ '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
+ $this->assertFalse($this->rootView->file_exists(
+ '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/'
+ . $this->filename . '.key'));
+
+ $this->assertTrue($this->rootView->file_exists(
+ '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/' . $this->folder . '/'
+ . $this->filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
+ $this->assertTrue($this->rootView->file_exists(
+ '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->folder . '/'
+ . $this->filename . '.key'));
+
+ // cleanup
+ $this->rootView->unlink('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder);
+ }
+
}
diff --git a/apps/files_encryption/tests/share.php b/apps/files_encryption/tests/share.php
index 46a21dd55cd..be56968ac09 100755
--- a/apps/files_encryption/tests/share.php
+++ b/apps/files_encryption/tests/share.php
@@ -127,6 +127,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
\OC_User::deleteUser(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4);
}
+
/**
* @medium
* @param bool $withTeardown
@@ -498,6 +499,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
}
}
+
function testPublicShareFile() {
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
@@ -864,6 +866,13 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
\OCA\Encryption\Helper::adminDisableRecovery('test123');
$this->assertEquals(0, \OC::$server->getAppConfig()->getValue('files_encryption', 'recoveryAdminEnabled'));
+
+ //clean up, reset passwords
+ \OC_User::setPassword(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, 'test123');
+ $params = array('uid' => \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2,
+ 'password' => \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2,
+ 'recoveryPassword' => 'test123');
+ \OCA\Encryption\Hooks::setPassphrase($params);
}
/**
@@ -947,4 +956,65 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
$this->view->chroot('/');
}
+
+ /**
+ * @brief test moving a shared file out of the Shared folder
+ */
+ function testRename() {
+
+ // login as admin
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ // save file with content
+ $cryptedFile = file_put_contents('crypt:///' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename, $this->dataShort);
+
+ // test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ // get the file info from previous created file
+ $fileInfo = $this->view->getFileInfo(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
+
+ // check if we have a valid file info
+ $this->assertTrue($fileInfo instanceof \OC\Files\FileInfo);
+
+ // share the file
+ \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, OCP\PERMISSION_ALL);
+
+ // check if share key for user2exists
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
+
+
+ // login as user2
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
+
+ $this->assertTrue($this->view->file_exists('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/Shared/' . $this->filename));
+
+ // get file contents
+ $retrievedCryptedFile = $this->view->file_get_contents(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/Shared/' . $this->filename);
+
+ // check if data is the same as we previously written
+ $this->assertEquals($this->dataShort, $retrievedCryptedFile);
+
+ // move the file out of the shared folder
+ $this->view->rename('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/Shared/' . $this->filename,
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->filename);
+
+ // check if we can read the moved file
+ $retrievedRenamedFile = $this->view->file_get_contents(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->filename);
+
+ // check if data is the same as we previously written
+ $this->assertEquals($this->dataShort, $retrievedRenamedFile);
+
+ // the owners file should be deleted
+ $this->assertFalse($this->view->file_exists('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename));
+
+ // cleanup
+ $this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->filename);
+ }
+
}
diff --git a/apps/files_external/lib/config.php b/apps/files_external/lib/config.php
index b2109e5eacd..43275d36c06 100755
--- a/apps/files_external/lib/config.php
+++ b/apps/files_external/lib/config.php
@@ -277,15 +277,21 @@ class OC_Mount_Config {
$mountType,
$applicable,
$isPersonal = false) {
+ $backends = self::getBackends();
$mountPoint = OC\Files\Filesystem::normalizePath($mountPoint);
if ($mountPoint === '' || $mountPoint === '/' || $mountPoint == '/Shared') {
// can't mount at root or "Shared" folder
return false;
}
+
+ if (!isset($backends[$class])) {
+ // invalid backend
+ return false;
+ }
if ($isPersonal) {
// Verify that the mount point applies for the current user
// Prevent non-admin users from mounting local storage
- if ($applicable != OCP\User::getUser() || $class == '\OC\Files\Storage\Local') {
+ if ($applicable !== OCP\User::getUser() || strtolower($class) === '\oc\files\storage\local') {
return false;
}
$mountPoint = '/'.$applicable.'/files/'.ltrim($mountPoint, '/');
@@ -353,7 +359,8 @@ class OC_Mount_Config {
$jsonFile = OC_User::getHome(OCP\User::getUser()).'/mount.json';
} else {
$phpFile = OC::$SERVERROOT.'/config/mount.php';
- $jsonFile = \OC_Config::getValue("mount_file", \OC::$SERVERROOT . "/data/mount.json");
+ $datadir = \OC_Config::getValue('datadirectory', \OC::$SERVERROOT . '/data/');
+ $jsonFile = \OC_Config::getValue('mount_file', $datadir . '/mount.json');
}
if (is_file($jsonFile)) {
$mountPoints = json_decode(file_get_contents($jsonFile), true);
@@ -379,7 +386,8 @@ class OC_Mount_Config {
if ($isPersonal) {
$file = OC_User::getHome(OCP\User::getUser()).'/mount.json';
} else {
- $file = \OC_Config::getValue("mount_file", \OC::$SERVERROOT . "/data/mount.json");
+ $datadir = \OC_Config::getValue('datadirectory', \OC::$SERVERROOT . '/data/');
+ $file = \OC_Config::getValue('mount_file', $datadir . '/mount.json');
}
$content = json_encode($data);
@file_put_contents($file, $content);
diff --git a/apps/files_external/tests/mountconfig.php b/apps/files_external/tests/mountconfig.php
index 941aec680bb..24ebcf51346 100644
--- a/apps/files_external/tests/mountconfig.php
+++ b/apps/files_external/tests/mountconfig.php
@@ -48,4 +48,29 @@ class Test_Mount_Config extends \PHPUnit_Framework_TestCase {
$this->assertEquals(false, OC_Mount_Config::addMountPoint('/Shared', $storageClass, array(), $mountType, $applicable, $isPersonal));
}
+
+ public function testAddMountPointSingleUser() {
+ \OC_User::setUserId('test');
+ $mountType = 'user';
+ $applicable = 'test';
+ $isPersonal = true;
+ // local
+ $this->assertEquals(false, OC_Mount_Config::addMountPoint('/ext', '\OC\Files\storage\local', array(), $mountType, $applicable, $isPersonal));
+ // non-local
+ // FIXME: can't test this yet as the class (write operation) is not mockable
+ // $this->assertEquals(true, OC_Mount_Config::addMountPoint('/ext', '\OC\Files\Storage\SFTP', array(), $mountType, $applicable, $isPersonal));
+
+ }
+
+ public function testAddMountPointUnexistClass() {
+ \OC_User::setUserId('test');
+ $storageClass = 'Unexist_Storage';
+ $mountType = 'user';
+ $applicable = 'test';
+ $isPersonal = true;
+ // local
+ // non-local
+ $this->assertEquals(false, OC_Mount_Config::addMountPoint('/ext', $storageClass, array(), $mountType, $applicable, $isPersonal));
+
+ }
}
diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php
index aadc54e4a7f..4b0da0b002d 100644
--- a/apps/files_sharing/lib/cache.php
+++ b/apps/files_sharing/lib/cache.php
@@ -131,19 +131,15 @@ class Shared_Cache extends Cache {
foreach ($files as &$file) {
$file['mimetype'] = $this->getMimetype($file['mimetype']);
$file['mimepart'] = $this->getMimetype($file['mimepart']);
+ $file['usersPath'] = 'files/Shared/' . ltrim($file['path'], '/');
}
return $files;
} else {
- if ($cache = $this->getSourceCache($folder)) {
+ $cache = $this->getSourceCache($folder);
+ if ($cache) {
$sourceFolderContent = $cache->getFolderContents($this->files[$folder]);
foreach ($sourceFolderContent as $key => $c) {
- $ownerPathParts = explode('/', \OC_Filesystem::normalizePath($c['path']));
- $userPathParts = explode('/', \OC_Filesystem::normalizePath($folder));
- $usersPath = 'files/Shared/'.$userPathParts[1];
- foreach (array_slice($ownerPathParts, 3) as $part) {
- $usersPath .= '/'.$part;
- }
- $sourceFolderContent[$key]['usersPath'] = $usersPath;
+ $sourceFolderContent[$key]['usersPath'] = 'files/Shared/' . $folder . '/' . $c['name'];
}
return $sourceFolderContent;
diff --git a/apps/files_sharing/public.php b/apps/files_sharing/public.php
index e7a5f5024b8..fe61dd4d5a0 100644
--- a/apps/files_sharing/public.php
+++ b/apps/files_sharing/public.php
@@ -32,7 +32,8 @@ function determineIcon($file, $sharingRoot, $sharingToken) {
if($file['isPreviewAvailable']) {
return OCP\publicPreview_icon($relativePath, $sharingToken) . '&c=' . $file['etag'];
}
- return OCP\mimetype_icon($file['mimetype']);
+ $icon = OCP\mimetype_icon($file['mimetype']);
+ return substr($icon, 0, -3) . 'svg';
}
if (isset($_GET['t'])) {
diff --git a/apps/files_sharing/tests/cache.php b/apps/files_sharing/tests/cache.php
index 56a51c83f6b..a75e1860527 100644
--- a/apps/files_sharing/tests/cache.php
+++ b/apps/files_sharing/tests/cache.php
@@ -2,8 +2,9 @@
/**
* ownCloud
*
- * @author Vincent Petry
+ * @author Vincent Petry, Bjoern Schiessle
* @copyright 2014 Vincent Petry <pvince81@owncloud.com>
+ * 2014 Bjoern Schiessle <schiessle@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
@@ -23,13 +24,19 @@ require_once __DIR__ . '/base.php';
class Test_Files_Sharing_Cache extends Test_Files_Sharing_Base {
+ /**
+ * @var OC_FilesystemView
+ */
+ public $user2View;
+
function setUp() {
parent::setUp();
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
+ $this->user2View = new \OC\Files\View('/'. self::TEST_FILES_SHARING_API_USER2 . '/files');
+
// prepare user1's dir structure
- $textData = "dummy file data\n";
$this->view->mkdir('container');
$this->view->mkdir('container/shareddir');
$this->view->mkdir('container/shareddir/subdir');
@@ -115,20 +122,128 @@ class Test_Files_Sharing_Cache extends Test_Files_Sharing_Base {
$this->verifyFiles($check, $results);
}
+ function testGetFolderContentsInRoot() {
+ $results = $this->user2View->getDirectoryContent('/Shared/');
+
+ $this->verifyFiles(
+ array(
+ array(
+ 'name' => 'shareddir',
+ 'path' => '/shareddir',
+ 'mimetype' => 'httpd/unix-directory',
+ 'usersPath' => 'files/Shared/shareddir'
+ ),
+ array(
+ 'name' => 'shared single file.txt',
+ 'path' => '/shared single file.txt',
+ 'mimetype' => 'text/plain',
+ 'usersPath' => 'files/Shared/shared single file.txt'
+ ),
+ ),
+ $results
+ );
+ }
+
+ function testGetFolderContentsInSubdir() {
+ $results = $this->user2View->getDirectoryContent('/Shared/shareddir');
+
+ $this->verifyFiles(
+ array(
+ array(
+ 'name' => 'bar.txt',
+ 'path' => 'files/container/shareddir/bar.txt',
+ 'mimetype' => 'text/plain',
+ 'usersPath' => 'files/Shared/shareddir/bar.txt'
+ ),
+ array(
+ 'name' => 'emptydir',
+ 'path' => 'files/container/shareddir/emptydir',
+ 'mimetype' => 'httpd/unix-directory',
+ 'usersPath' => 'files/Shared/shareddir/emptydir'
+ ),
+ array(
+ 'name' => 'subdir',
+ 'path' => 'files/container/shareddir/subdir',
+ 'mimetype' => 'httpd/unix-directory',
+ 'usersPath' => 'files/Shared/shareddir/subdir'
+ ),
+ ),
+ $results
+ );
+ }
+
+ function testGetFolderContentsWhenSubSubdirShared() {
+ self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
+
+ $fileinfo = $this->view->getFileInfo('container/shareddir/subdir');
+ \OCP\Share::shareItem('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
+ self::TEST_FILES_SHARING_API_USER3, 31);
+
+ self::loginHelper(self::TEST_FILES_SHARING_API_USER3);
+
+ $thirdView = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER3 . '/files');
+ $results = $thirdView->getDirectoryContent('/Shared/subdir');
+
+ $this->verifyFiles(
+ array(
+ array(
+ 'name' => 'another too.txt',
+ 'path' => 'files/container/shareddir/subdir/another too.txt',
+ 'mimetype' => 'text/plain',
+ 'usersPath' => 'files/Shared/subdir/another too.txt'
+ ),
+ array(
+ 'name' => 'another.txt',
+ 'path' => 'files/container/shareddir/subdir/another.txt',
+ 'mimetype' => 'text/plain',
+ 'usersPath' => 'files/Shared/subdir/another.txt'
+ ),
+ array(
+ 'name' => 'not a text file.xml',
+ 'path' => 'files/container/shareddir/subdir/not a text file.xml',
+ 'mimetype' => 'application/xml',
+ 'usersPath' => 'files/Shared/subdir/not a text file.xml'
+ ),
+ ),
+ $results
+ );
+
+ self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
+
+ \OCP\Share::unshare('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
+ self::TEST_FILES_SHARING_API_USER3);
+ }
+
/**
- * Checks that all provided attributes exist in the files list,
- * only the values provided in $examples will be used to check against
- * the file list. The files order also needs to be the same.
+ * Check if 'results' contains the expected 'examples' only.
*
* @param array $examples array of example files
- * @param array $files array of files
+ * @param array $results array of files
*/
- private function verifyFiles($examples, $files) {
- $this->assertEquals(count($examples), count($files));
- foreach ($files as $i => $file) {
- foreach ($examples[$i] as $key => $value) {
- $this->assertEquals($value, $file[$key]);
+ private function verifyFiles($examples, $results) {
+ $this->assertEquals(count($examples), count($results));
+
+ foreach ($examples as $example) {
+ foreach ($results as $key => $result) {
+ if ($result['name'] === $example['name']) {
+ $this->verifyKeys($example, $result);
+ unset($results[$key]);
+ break;
+ }
}
}
+ $this->assertTrue(empty($results));
}
+
+ /**
+ * @brief verify if each value from the result matches the expected result
+ * @param array $example array with the expected results
+ * @param array $result array with the results
+ */
+ private function verifyKeys($example, $result) {
+ foreach ($example as $key => $value) {
+ $this->assertEquals($value, $result[$key]);
+ }
+ }
+
}
diff --git a/apps/files_trashbin/js/filelist.js b/apps/files_trashbin/js/filelist.js
index f42abb6d029..a88459b0a9a 100644
--- a/apps/files_trashbin/js/filelist.js
+++ b/apps/files_trashbin/js/filelist.js
@@ -1,3 +1,4 @@
+/* globals OC, FileList, t */
// override reload with own ajax call
FileList.reload = function(){
FileList.showMask();
@@ -17,7 +18,36 @@ FileList.reload = function(){
FileList.reloadCallback(result);
}
});
-}
+};
+
+FileList.appName = t('files_trashbin', 'Deleted files');
+
+FileList._deletedRegExp = new RegExp(/^(.+)\.d[0-9]+$/);
+
+/**
+ * Convert a file name in the format filename.d12345 to the real file name.
+ * This will use basename.
+ * The name will not be changed if it has no ".d12345" suffix.
+ * @param name file name
+ * @return converted file name
+ */
+FileList.getDeletedFileName = function(name) {
+ name = OC.basename(name);
+ var match = FileList._deletedRegExp.exec(name);
+ if (match && match.length > 1) {
+ name = match[1];
+ }
+ return name;
+};
+var oldSetCurrentDir = FileList.setCurrentDir;
+FileList.setCurrentDir = function(targetDir) {
+ oldSetCurrentDir.apply(this, arguments);
+
+ var baseDir = OC.basename(targetDir);
+ if (baseDir !== '') {
+ FileList.setPageTitle(FileList.getDeletedFileName(baseDir));
+ }
+};
FileList.linkTo = function(dir){
return OC.linkTo('files_trashbin', 'index.php')+"?dir="+ encodeURIComponent(dir).replace(/%2F/g, '/');
diff --git a/apps/user_ldap/group_ldap.php b/apps/user_ldap/group_ldap.php
index 32e2cec5960..cef9ca3c4cf 100644
--- a/apps/user_ldap/group_ldap.php
+++ b/apps/user_ldap/group_ldap.php
@@ -61,8 +61,7 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
return false;
}
//usually, LDAP attributes are said to be case insensitive. But there are exceptions of course.
- $members = $this->access->readAttribute($dn_group,
- $this->access->connection->ldapGroupMemberAssocAttr);
+ $members = array_keys($this->_groupMembers($dn_group));
if(!$members) {
$this->access->connection->writeToCache('inGroup'.$uid.':'.$gid, false);
return false;
@@ -89,6 +88,39 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
return $isInGroup;
}
+ private function _groupMembers($dnGroup, &$seen = null) {
+ if ($seen === null) {
+ $seen = array();
+ }
+ $allMembers = array();
+ if (array_key_exists($dnGroup, $seen)) {
+ // avoid loops
+ return array();
+ }
+ // used extensively in cron job, caching makes sense for nested groups
+ $cacheKey = '_groupMembers'.$dnGroup;
+ if($this->access->connection->isCached($cacheKey)) {
+ return $this->access->connection->getFromCache($cacheKey);
+ }
+ $seen[$dnGroup] = 1;
+ $members = $this->access->readAttribute($dnGroup, $this->access->connection->ldapGroupMemberAssocAttr,
+ $this->access->connection->ldapGroupFilter);
+ if (is_array($members)) {
+ foreach ($members as $memberDN) {
+ $allMembers[$memberDN] = 1;
+ $nestedGroups = $this->access->connection->ldapNestedGroups;
+ if (!empty($nestedGroups)) {
+ $subMembers = $this->_groupMembers($memberDN, $seen);
+ if ($subMembers) {
+ $allMembers = array_merge($allMembers, $subMembers);
+ }
+ }
+ }
+ }
+ $this->access->connection->writeToCache($cacheKey, $allMembers);
+ return $allMembers;
+ }
+
/**
* @brief Get all groups a user belongs to
* @param $uid Name of the user
@@ -124,18 +156,45 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
$uid = $userDN;
}
- $filter = $this->access->combineFilterWithAnd(array(
- $this->access->connection->ldapGroupFilter,
- $this->access->connection->ldapGroupMemberAssocAttr.'='.$uid
- ));
- $groups = $this->access->fetchListOfGroups($filter,
- array($this->access->connection->ldapGroupDisplayName, 'dn'));
+ $groups = array_values($this->getGroupsByMember($uid));
$groups = array_unique($this->access->ownCloudGroupNames($groups), SORT_LOCALE_STRING);
$this->access->connection->writeToCache($cacheKey, $groups);
return $groups;
}
+ private function getGroupsByMember($dn, &$seen = null) {
+ if ($seen === null) {
+ $seen = array();
+ }
+ $allGroups = array();
+ if (array_key_exists($dn, $seen)) {
+ // avoid loops
+ return array();
+ }
+ $seen[$dn] = true;
+ $filter = $this->access->combineFilterWithAnd(array(
+ $this->access->connection->ldapGroupFilter,
+ $this->access->connection->ldapGroupMemberAssocAttr.'='.$dn
+ ));
+ $groups = $this->access->fetchListOfGroups($filter,
+ array($this->access->connection->ldapGroupDisplayName, 'dn'));
+ if (is_array($groups)) {
+ foreach ($groups as $groupobj) {
+ $groupDN = $groupobj['dn'];
+ $allGroups[$groupDN] = $groupobj;
+ $nestedGroups = $this->access->connection->ldapNestedGroups;
+ if (!empty($nestedGroups)) {
+ $supergroups = $this->getGroupsByMember($groupDN, $seen);
+ if (is_array($supergroups) && (count($supergroups)>0)) {
+ $allGroups = array_merge($allGroups, $supergroups);
+ }
+ }
+ }
+ }
+ return $allGroups;
+ }
+
/**
* @brief get a list of all users in a group
* @returns array with user ids
@@ -172,8 +231,7 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
return array();
}
- $members = $this->access->readAttribute($groupDN,
- $this->access->connection->ldapGroupMemberAssocAttr);
+ $members = array_keys($this->_groupMembers($groupDN));
if(!$members) {
//in case users could not be retrieved, return empty resultset
$this->access->connection->writeToCache($cachekey, array());
diff --git a/apps/user_ldap/lib/configuration.php b/apps/user_ldap/lib/configuration.php
index 954d0501fad..612a623e910 100644
--- a/apps/user_ldap/lib/configuration.php
+++ b/apps/user_ldap/lib/configuration.php
@@ -76,6 +76,7 @@ class Configuration {
'ldapExpertUUIDUserAttr' => null,
'ldapExpertUUIDGroupAttr' => null,
'lastJpegPhotoLookup' => null,
+ 'ldapNestedGroups' => false,
);
/**
@@ -342,6 +343,7 @@ class Configuration {
'ldap_expert_uuid_group_attr' => '',
'has_memberof_filter_support' => 0,
'last_jpegPhoto_lookup' => 0,
+ 'ldap_nested_groups' => 0,
);
}
@@ -393,6 +395,7 @@ class Configuration {
'ldap_expert_uuid_group_attr' => 'ldapExpertUUIDGroupAttr',
'has_memberof_filter_support' => 'hasMemberOfFilterSupport',
'last_jpegPhoto_lookup' => 'lastJpegPhotoLookup',
+ 'ldap_nested_groups' => 'ldapNestedGroups',
);
return $array;
}
diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php
index 3ccc7a860f5..79c4ae224c3 100644
--- a/apps/user_ldap/templates/settings.php
+++ b/apps/user_ldap/templates/settings.php
@@ -36,6 +36,7 @@
<p><label for="ldap_base_groups"><?php p($l->t('Base Group Tree'));?></label><textarea id="ldap_base_groups" name="ldap_base_groups" placeholder="<?php p($l->t('One Group Base DN per line'));?>" data-default="<?php p($_['ldap_base_groups_default']); ?>" title="<?php p($l->t('Base Group Tree'));?>"></textarea></p>
<p><label for="ldap_attributes_for_group_search"><?php p($l->t('Group Search Attributes'));?></label><textarea id="ldap_attributes_for_group_search" name="ldap_attributes_for_group_search" placeholder="<?php p($l->t('Optional; one attribute per line'));?>" data-default="<?php p($_['ldap_attributes_for_group_search_default']); ?>" title="<?php p($l->t('Group Search Attributes'));?>"></textarea></p>
<p><label for="ldap_group_member_assoc_attribute"><?php p($l->t('Group-Member association'));?></label><select id="ldap_group_member_assoc_attribute" name="ldap_group_member_assoc_attribute" data-default="<?php p($_['ldap_group_member_assoc_attribute_default']); ?>" ><option value="uniqueMember"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'uniqueMember')) p(' selected'); ?>>uniqueMember</option><option value="memberUid"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'memberUid')) p(' selected'); ?>>memberUid</option><option value="member"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'member')) p(' selected'); ?>>member (AD)</option></select></p>
+ <p><label for="ldap_nested_groups"><?php p($l->t('Nested Groups'));?></label><input type="checkbox" id="ldap_nested_groups" name="ldap_nested_groups" value="1" data-default="<?php p($_['ldap_nested_groups_default']); ?>" title="<?php p($l->t('When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)'));?>" /></p>
</div>
<h3><?php p($l->t('Special Attributes'));?></h3>
<div>