Merge pull request #8666 from owncloud/mount-remove
Support for (re)moving mountpoints
This commit is contained in:
commit
c47d4ebbac
|
@ -113,7 +113,7 @@ class Helper
|
||||||
if (\OC::$server->getPreviewManager()->isMimeSupported($i['mimetype'])) {
|
if (\OC::$server->getPreviewManager()->isMimeSupported($i['mimetype'])) {
|
||||||
$entry['isPreviewAvailable'] = true;
|
$entry['isPreviewAvailable'] = true;
|
||||||
}
|
}
|
||||||
$entry['name'] = $i['name'];
|
$entry['name'] = $i->getName();
|
||||||
$entry['permissions'] = $i['permissions'];
|
$entry['permissions'] = $i['permissions'];
|
||||||
$entry['mimetype'] = $i['mimetype'];
|
$entry['mimetype'] = $i['mimetype'];
|
||||||
$entry['size'] = $i['size'];
|
$entry['size'] = $i['size'];
|
||||||
|
|
|
@ -81,7 +81,7 @@ class Test_OC_Files_App_Rename extends \PHPUnit_Framework_TestCase {
|
||||||
$this->viewMock->expects($this->any())
|
$this->viewMock->expects($this->any())
|
||||||
->method('getFileInfo')
|
->method('getFileInfo')
|
||||||
->will($this->returnValue(new \OC\Files\FileInfo(
|
->will($this->returnValue(new \OC\Files\FileInfo(
|
||||||
'/',
|
'/new_name',
|
||||||
new \OC\Files\Storage\Local(array('datadir' => '/')),
|
new \OC\Files\Storage\Local(array('datadir' => '/')),
|
||||||
'/',
|
'/',
|
||||||
array(
|
array(
|
||||||
|
|
|
@ -17,7 +17,7 @@ class Test_Files_Helper extends \PHPUnit_Framework_TestCase {
|
||||||
|
|
||||||
private function makeFileInfo($name, $size, $mtime, $isDir = false) {
|
private function makeFileInfo($name, $size, $mtime, $isDir = false) {
|
||||||
return new \OC\Files\FileInfo(
|
return new \OC\Files\FileInfo(
|
||||||
'/',
|
'/' . $name,
|
||||||
null,
|
null,
|
||||||
'/',
|
'/',
|
||||||
array(
|
array(
|
||||||
|
|
|
@ -34,6 +34,8 @@ class Hooks {
|
||||||
private static $renamedFiles = array();
|
private static $renamedFiles = array();
|
||||||
// file for which we want to delete the keys after the delete operation was successful
|
// file for which we want to delete the keys after the delete operation was successful
|
||||||
private static $deleteFiles = array();
|
private static $deleteFiles = array();
|
||||||
|
// file for which we want to delete the keys after the delete operation was successful
|
||||||
|
private static $umountedFiles = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Startup encryption backend upon user login
|
* Startup encryption backend upon user login
|
||||||
|
@ -610,4 +612,57 @@ class Hooks {
|
||||||
'path' => $ownerPath);
|
'path' => $ownerPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remember files/folders which get unmounted
|
||||||
|
*/
|
||||||
|
public static function preUmount($params) {
|
||||||
|
$path = $params[\OC\Files\Filesystem::signal_param_path];
|
||||||
|
$user = \OCP\USER::getUser();
|
||||||
|
|
||||||
|
$view = new \OC\Files\View();
|
||||||
|
$itemType = $view->is_dir('/' . $user . '/files' . $path) ? 'folder' : 'file';
|
||||||
|
|
||||||
|
$util = new Util($view, $user);
|
||||||
|
list($owner, $ownerPath) = $util->getUidAndFilename($path);
|
||||||
|
|
||||||
|
self::$umountedFiles[$params[\OC\Files\Filesystem::signal_param_path]] = array(
|
||||||
|
'uid' => $owner,
|
||||||
|
'path' => $ownerPath,
|
||||||
|
'itemType' => $itemType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function postUmount($params) {
|
||||||
|
|
||||||
|
if (!isset(self::$umountedFiles[$params[\OC\Files\Filesystem::signal_param_path]])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$umountedFile = self::$umountedFiles[$params[\OC\Files\Filesystem::signal_param_path]];
|
||||||
|
$path = $umountedFile['path'];
|
||||||
|
$user = $umountedFile['uid'];
|
||||||
|
$itemType = $umountedFile['itemType'];
|
||||||
|
|
||||||
|
$view = new \OC\Files\View();
|
||||||
|
$util = new Util($view, $user);
|
||||||
|
|
||||||
|
// we don't need to remember the file any longer
|
||||||
|
unset(self::$umountedFiles[$params[\OC\Files\Filesystem::signal_param_path]]);
|
||||||
|
|
||||||
|
// if we unshare a folder we need a list of all (sub-)files
|
||||||
|
if ($itemType === 'folder') {
|
||||||
|
$allFiles = $util->getAllFiles($path);
|
||||||
|
} else {
|
||||||
|
$allFiles = array($path);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($allFiles as $path) {
|
||||||
|
|
||||||
|
// check if the user still has access to the file, otherwise delete share key
|
||||||
|
$sharingUsers = \OCP\Share::getUsersSharingFile($path, $user);
|
||||||
|
if (!in_array(\OCP\User::getUser(), $sharingUsers['users'])) {
|
||||||
|
Keymanager::delShareKey($view, array(\OCP\User::getUser()), $path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,8 @@ class Helper {
|
||||||
\OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OCA\Encryption\Hooks', 'postRename');
|
\OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OCA\Encryption\Hooks', 'postRename');
|
||||||
\OCP\Util::connectHook('OC_Filesystem', 'post_delete', 'OCA\Encryption\Hooks', 'postDelete');
|
\OCP\Util::connectHook('OC_Filesystem', 'post_delete', 'OCA\Encryption\Hooks', 'postDelete');
|
||||||
\OCP\Util::connectHook('OC_Filesystem', 'delete', 'OCA\Encryption\Hooks', 'preDelete');
|
\OCP\Util::connectHook('OC_Filesystem', 'delete', 'OCA\Encryption\Hooks', 'preDelete');
|
||||||
|
\OCP\Util::connectHook('OC_Filesystem', 'post_umount', 'OCA\Encryption\Hooks', 'postUmount');
|
||||||
|
\OCP\Util::connectHook('OC_Filesystem', 'umount', 'OCA\Encryption\Hooks', 'preUmount');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -257,14 +257,14 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase {
|
||||||
|
|
||||||
$this->assertTrue($result);
|
$this->assertTrue($result);
|
||||||
|
|
||||||
// now keys from user1s home should be gone
|
// share key for user2 from user1s home should be gone, all other keys should still exists
|
||||||
$this->assertFalse($this->rootView->file_exists(
|
$this->assertTrue($this->rootView->file_exists(
|
||||||
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
|
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
|
||||||
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
|
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
|
||||||
$this->assertFalse($this->rootView->file_exists(
|
$this->assertFalse($this->rootView->file_exists(
|
||||||
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
|
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
|
||||||
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey'));
|
. $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey'));
|
||||||
$this->assertFalse($this->rootView->file_exists(
|
$this->assertTrue($this->rootView->file_exists(
|
||||||
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
|
self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
|
||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
|
|
|
@ -104,8 +104,15 @@ class OC_Mount_Config {
|
||||||
*/
|
*/
|
||||||
public static function initMountPointsHook($data) {
|
public static function initMountPointsHook($data) {
|
||||||
$mountPoints = self::getAbsoluteMountPoints($data['user']);
|
$mountPoints = self::getAbsoluteMountPoints($data['user']);
|
||||||
|
$loader = \OC\Files\Filesystem::getLoader();
|
||||||
|
$manager = \OC\Files\Filesystem::getMountManager();
|
||||||
foreach ($mountPoints as $mountPoint => $options) {
|
foreach ($mountPoints as $mountPoint => $options) {
|
||||||
\OC\Files\Filesystem::mount($options['class'], $options['options'], $mountPoint);
|
if ($options['personal']){
|
||||||
|
$mount = new \OCA\Files_External\PersonalMount($options['class'], $mountPoint, $options['options'], $loader);
|
||||||
|
} else{
|
||||||
|
$mount = new \OC\Files\Mount\Mount($options['class'], $mountPoint, $options['options'], $loader);
|
||||||
|
}
|
||||||
|
$manager->addMount($mount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,6 +142,7 @@ class OC_Mount_Config {
|
||||||
// Global mount points (is this redundant?)
|
// Global mount points (is this redundant?)
|
||||||
if (isset($mountConfig[self::MOUNT_TYPE_GLOBAL])) {
|
if (isset($mountConfig[self::MOUNT_TYPE_GLOBAL])) {
|
||||||
foreach ($mountConfig[self::MOUNT_TYPE_GLOBAL] as $mountPoint => $options) {
|
foreach ($mountConfig[self::MOUNT_TYPE_GLOBAL] as $mountPoint => $options) {
|
||||||
|
$options['personal'] = false;
|
||||||
$options['options'] = self::decryptPasswords($options['options']);
|
$options['options'] = self::decryptPasswords($options['options']);
|
||||||
if (!isset($options['priority'])) {
|
if (!isset($options['priority'])) {
|
||||||
$options['priority'] = $backends[$options['class']]['priority'];
|
$options['priority'] = $backends[$options['class']]['priority'];
|
||||||
|
@ -178,6 +186,7 @@ class OC_Mount_Config {
|
||||||
foreach ($options as &$option) {
|
foreach ($options as &$option) {
|
||||||
$option = self::setUserVars($user, $option);
|
$option = self::setUserVars($user, $option);
|
||||||
}
|
}
|
||||||
|
$options['personal'] = false;
|
||||||
$options['options'] = self::decryptPasswords($options['options']);
|
$options['options'] = self::decryptPasswords($options['options']);
|
||||||
if (!isset($options['priority'])) {
|
if (!isset($options['priority'])) {
|
||||||
$options['priority'] = $backends[$options['class']]['priority'];
|
$options['priority'] = $backends[$options['class']]['priority'];
|
||||||
|
@ -203,6 +212,7 @@ class OC_Mount_Config {
|
||||||
foreach ($options as &$option) {
|
foreach ($options as &$option) {
|
||||||
$option = self::setUserVars($user, $option);
|
$option = self::setUserVars($user, $option);
|
||||||
}
|
}
|
||||||
|
$options['personal'] = false;
|
||||||
$options['options'] = self::decryptPasswords($options['options']);
|
$options['options'] = self::decryptPasswords($options['options']);
|
||||||
if (!isset($options['priority'])) {
|
if (!isset($options['priority'])) {
|
||||||
$options['priority'] = $backends[$options['class']]['priority'];
|
$options['priority'] = $backends[$options['class']]['priority'];
|
||||||
|
@ -224,6 +234,7 @@ class OC_Mount_Config {
|
||||||
$mountConfig = self::readData($user);
|
$mountConfig = self::readData($user);
|
||||||
if (isset($mountConfig[self::MOUNT_TYPE_USER][$user])) {
|
if (isset($mountConfig[self::MOUNT_TYPE_USER][$user])) {
|
||||||
foreach ($mountConfig[self::MOUNT_TYPE_USER][$user] as $mountPoint => $options) {
|
foreach ($mountConfig[self::MOUNT_TYPE_USER][$user] as $mountPoint => $options) {
|
||||||
|
$options['personal'] = true;
|
||||||
$options['options'] = self::decryptPasswords($options['options']);
|
$options['options'] = self::decryptPasswords($options['options']);
|
||||||
|
|
||||||
// Always override previous config
|
// Always override previous config
|
||||||
|
@ -506,6 +517,7 @@ class OC_Mount_Config {
|
||||||
} else {
|
} else {
|
||||||
$mountPoint = '/$user/files/'.ltrim($mountPoint, '/');
|
$mountPoint = '/$user/files/'.ltrim($mountPoint, '/');
|
||||||
}
|
}
|
||||||
|
$mountPoint = \OC\Files\Filesystem::normalizePath($mountPoint);
|
||||||
$mountPoints = self::readData($isPersonal ? OCP\User::getUser() : NULL);
|
$mountPoints = self::readData($isPersonal ? OCP\User::getUser() : NULL);
|
||||||
// Remove mount point
|
// Remove mount point
|
||||||
unset($mountPoints[$mountType][$applicable][$mountPoint]);
|
unset($mountPoints[$mountType][$applicable][$mountPoint]);
|
||||||
|
@ -520,6 +532,28 @@ class OC_Mount_Config {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param string $mountPoint Mount point
|
||||||
|
* @param string $target The new mount point
|
||||||
|
* @param string $mountType MOUNT_TYPE_GROUP | MOUNT_TYPE_USER
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function movePersonalMountPoint($mountPoint, $target, $mountType) {
|
||||||
|
$mountPoint = rtrim($mountPoint, '/');
|
||||||
|
$user = OCP\User::getUser();
|
||||||
|
$mountPoints = self::readData($user);
|
||||||
|
if (!isset($mountPoints[$mountType][$user][$mountPoint])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$mountPoints[$mountType][$user][$target] = $mountPoints[$mountType][$user][$mountPoint];
|
||||||
|
// Remove old mount point
|
||||||
|
unset($mountPoints[$mountType][$user][$mountPoint]);
|
||||||
|
|
||||||
|
self::writeData($user, $mountPoints);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the mount points in the config file into an array
|
* Read the mount points in the config file into an array
|
||||||
* @param string|null $user If not null, personal for $user, otherwise system
|
* @param string|null $user If not null, personal for $user, otherwise system
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2012 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 OCA\Files_External;
|
||||||
|
|
||||||
|
use OC\Files\Mount\Mount;
|
||||||
|
use OC\Files\Mount\MoveableMount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Person mount points can be moved by the user
|
||||||
|
*/
|
||||||
|
class PersonalMount extends Mount implements MoveableMount {
|
||||||
|
/**
|
||||||
|
* Move the mount point to $target
|
||||||
|
*
|
||||||
|
* @param string $target the target mount point
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function moveMount($target) {
|
||||||
|
$result = \OC_Mount_Config::movePersonalMountPoint($this->getMountPoint(), $target, \OC_Mount_Config::MOUNT_TYPE_USER);
|
||||||
|
$this->setMountPoint($target);
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the mount points
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function removeMount() {
|
||||||
|
$user = \OCP\User::getUser();
|
||||||
|
$relativeMountPoint = substr($this->getMountPoint(), strlen('/' . $user . '/files/'));
|
||||||
|
return \OC_Mount_Config::removeMountPoint($relativeMountPoint, \OC_Mount_Config::MOUNT_TYPE_USER, $user , true);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
$installedVersion = OCP\Config::getAppValue('files_sharing', 'installed_version');
|
$installedVersion = OCP\Config::getAppValue('files_sharing', 'installed_version');
|
||||||
|
|
||||||
|
if (version_compare($installedVersion, '0.5', '<')) {
|
||||||
|
updateFilePermissions();
|
||||||
|
}
|
||||||
|
|
||||||
if (version_compare($installedVersion, '0.4', '<')) {
|
if (version_compare($installedVersion, '0.4', '<')) {
|
||||||
removeSharedFolder();
|
removeSharedFolder();
|
||||||
}
|
}
|
||||||
|
@ -11,6 +16,39 @@ if (version_compare($installedVersion, '0.3.5.6', '<')) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* it is no longer possible to share single files with delete permissions. User
|
||||||
|
* should only be able to unshare single files but never to delete them.
|
||||||
|
*/
|
||||||
|
function updateFilePermissions($chunkSize = 99) {
|
||||||
|
$query = OCP\DB::prepare('SELECT * FROM `*PREFIX*share` WHERE `item_type` = ?');
|
||||||
|
$result = $query->execute(array('file'));
|
||||||
|
|
||||||
|
$updatedRows = array();
|
||||||
|
|
||||||
|
while ($row = $result->fetchRow()) {
|
||||||
|
if ($row['permissions'] & \OCP\PERMISSION_DELETE) {
|
||||||
|
$updatedRows[$row['id']] = (int)$row['permissions'] & ~\OCP\PERMISSION_DELETE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$chunkedPermissionList = array_chunk($updatedRows, $chunkSize, true);
|
||||||
|
|
||||||
|
foreach ($chunkedPermissionList as $subList) {
|
||||||
|
$statement = "UPDATE `*PREFIX*share` SET `permissions` = CASE `id` ";
|
||||||
|
//update share table
|
||||||
|
$ids = implode(',', array_keys($subList));
|
||||||
|
foreach ($subList as $id => $permission) {
|
||||||
|
$statement .= "WHEN " . $id . " THEN " . $permission . " ";
|
||||||
|
}
|
||||||
|
$statement .= ' END WHERE `id` IN (' . $ids . ')';
|
||||||
|
|
||||||
|
$query = OCP\DB::prepare($statement);
|
||||||
|
$query->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* update script for the removal of the logical "Shared" folder, we create physical "Shared" folder and
|
* update script for the removal of the logical "Shared" folder, we create physical "Shared" folder and
|
||||||
* update the users file_target so that it doesn't make any difference for the user
|
* update the users file_target so that it doesn't make any difference for the user
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
0.4.1
|
0.5
|
||||||
|
|
|
@ -18,12 +18,17 @@
|
||||||
var oldCreateRow = OCA.Files.FileList.prototype._createRow;
|
var oldCreateRow = OCA.Files.FileList.prototype._createRow;
|
||||||
OCA.Files.FileList.prototype._createRow = function(fileData) {
|
OCA.Files.FileList.prototype._createRow = function(fileData) {
|
||||||
var tr = oldCreateRow.apply(this, arguments);
|
var tr = oldCreateRow.apply(this, arguments);
|
||||||
|
var sharePermissions = fileData.permissions;
|
||||||
|
if (fileData.type === 'file') {
|
||||||
|
// files can't be shared with delete permissions
|
||||||
|
sharePermissions = sharePermissions & ~OC.PERMISSION_DELETE;
|
||||||
|
}
|
||||||
|
tr.attr('data-share-permissions', sharePermissions);
|
||||||
if (fileData.shareOwner) {
|
if (fileData.shareOwner) {
|
||||||
tr.attr('data-share-owner', fileData.shareOwner);
|
tr.attr('data-share-owner', fileData.shareOwner);
|
||||||
// user should always be able to rename a mount point
|
// user should always be able to rename a mount point
|
||||||
if (fileData.isShareMountPoint) {
|
if (fileData.isShareMountPoint) {
|
||||||
tr.attr('data-permissions', fileData.permissions | OC.PERMISSION_UPDATE);
|
tr.attr('data-permissions', fileData.permissions | OC.PERMISSION_UPDATE);
|
||||||
tr.attr('data-reshare-permissions', fileData.permissions);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fileData.recipientsDisplayName) {
|
if (fileData.recipientsDisplayName) {
|
||||||
|
@ -94,7 +99,7 @@
|
||||||
if ($tr.data('type') === 'dir') {
|
if ($tr.data('type') === 'dir') {
|
||||||
itemType = 'folder';
|
itemType = 'folder';
|
||||||
}
|
}
|
||||||
var possiblePermissions = $tr.data('reshare-permissions');
|
var possiblePermissions = $tr.data('share-permissions');
|
||||||
if (_.isUndefined(possiblePermissions)) {
|
if (_.isUndefined(possiblePermissions)) {
|
||||||
possiblePermissions = $tr.data('permissions');
|
possiblePermissions = $tr.data('permissions');
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,11 @@ class Shared_Cache extends Cache {
|
||||||
$data['is_share_mount_point'] = true;
|
$data['is_share_mount_point'] = true;
|
||||||
}
|
}
|
||||||
$data['uid_owner'] = $this->storage->getOwner($file);
|
$data['uid_owner'] = $this->storage->getOwner($file);
|
||||||
|
if (isset($data['permissions'])) {
|
||||||
|
$data['permissions'] = $data['permissions'] & $this->storage->getPermissions('');
|
||||||
|
} else {
|
||||||
|
$data['permissions'] = $this->storage->getPermissions('');
|
||||||
|
}
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -130,6 +135,7 @@ class Shared_Cache extends Cache {
|
||||||
$data['name'] = basename($this->storage->getMountPoint());
|
$data['name'] = basename($this->storage->getMountPoint());
|
||||||
$data['is_share_mount_point'] = true;
|
$data['is_share_mount_point'] = true;
|
||||||
}
|
}
|
||||||
|
$data['permissions'] = $data['permissions'] & $this->storage->getPermissions('');
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -157,6 +163,7 @@ class Shared_Cache extends Cache {
|
||||||
$sourceFolderContent[$key]['path'] = $dir . $c['name'];
|
$sourceFolderContent[$key]['path'] = $dir . $c['name'];
|
||||||
$sourceFolderContent[$key]['uid_owner'] = $parent['uid_owner'];
|
$sourceFolderContent[$key]['uid_owner'] = $parent['uid_owner'];
|
||||||
$sourceFolderContent[$key]['displayname_owner'] = $parent['uid_owner'];
|
$sourceFolderContent[$key]['displayname_owner'] = $parent['uid_owner'];
|
||||||
|
$sourceFolderContent[$key]['permissions'] = $sourceFolderContent[$key]['permissions'] & $this->storage->getPermissions('');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $sourceFolderContent;
|
return $sourceFolderContent;
|
||||||
|
|
|
@ -0,0 +1,161 @@
|
||||||
|
<?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 OCA\Files_Sharing;
|
||||||
|
|
||||||
|
use OC\Files\Filesystem;
|
||||||
|
use OC\Files\Mount\Mount;
|
||||||
|
use OC\Files\Mount\MoveableMount;
|
||||||
|
use OC\Files\Storage\Shared;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shared mount points can be moved by the user
|
||||||
|
*/
|
||||||
|
class SharedMount extends Mount implements MoveableMount {
|
||||||
|
/**
|
||||||
|
* @var \OC\Files\Storage\Shared $storage
|
||||||
|
*/
|
||||||
|
protected $storage = null;
|
||||||
|
|
||||||
|
public function __construct($storage, $mountpoint, $arguments = null, $loader = null) {
|
||||||
|
// first update the mount point before creating the parent
|
||||||
|
$newMountPoint = self::verifyMountPoint($arguments['share']);
|
||||||
|
$absMountPoint = '/' . \OCP\User::getUser() . '/files' . $newMountPoint;
|
||||||
|
parent::__construct($storage, $absMountPoint, $arguments, $loader);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check if the parent folder exists otherwise move the mount point up
|
||||||
|
*/
|
||||||
|
private static function verifyMountPoint(&$share) {
|
||||||
|
|
||||||
|
$mountPoint = basename($share['file_target']);
|
||||||
|
$parent = dirname($share['file_target']);
|
||||||
|
|
||||||
|
while (!\OC\Files\Filesystem::is_dir($parent)) {
|
||||||
|
$parent = dirname($parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
$newMountPoint = \OCA\Files_Sharing\Helper::generateUniqueTarget(
|
||||||
|
\OC\Files\Filesystem::normalizePath($parent . '/' . $mountPoint),
|
||||||
|
array(),
|
||||||
|
new \OC\Files\View('/' . \OCP\User::getUser() . '/files')
|
||||||
|
);
|
||||||
|
|
||||||
|
if($newMountPoint !== $share['file_target']) {
|
||||||
|
self::updateFileTarget($newMountPoint, $share);
|
||||||
|
$share['file_target'] = $newMountPoint;
|
||||||
|
$share['unique_name'] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $newMountPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* update fileTarget in the database if the mount point changed
|
||||||
|
* @param string $newPath
|
||||||
|
* @param array $share reference to the share which should be modified
|
||||||
|
* @return type
|
||||||
|
*/
|
||||||
|
private static function updateFileTarget($newPath, &$share) {
|
||||||
|
// if the user renames a mount point from a group share we need to create a new db entry
|
||||||
|
// for the unique name
|
||||||
|
if ($share['share_type'] === \OCP\Share::SHARE_TYPE_GROUP && empty($share['unique_name'])) {
|
||||||
|
$query = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`item_type`, `item_source`, `item_target`,'
|
||||||
|
.' `share_type`, `share_with`, `uid_owner`, `permissions`, `stime`, `file_source`,'
|
||||||
|
.' `file_target`, `token`, `parent`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)');
|
||||||
|
$arguments = array($share['item_type'], $share['item_source'], $share['item_target'],
|
||||||
|
2, \OCP\User::getUser(), $share['uid_owner'], $share['permissions'], $share['stime'], $share['file_source'],
|
||||||
|
$newPath, $share['token'], $share['id']);
|
||||||
|
} else {
|
||||||
|
// rename mount point
|
||||||
|
$query = \OC_DB::prepare(
|
||||||
|
'Update `*PREFIX*share`
|
||||||
|
SET `file_target` = ?
|
||||||
|
WHERE `id` = ?'
|
||||||
|
);
|
||||||
|
$arguments = array($newPath, $share['id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $query->execute($arguments);
|
||||||
|
|
||||||
|
return $result === 1 ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a path to be relative to the /user/files/ directory
|
||||||
|
*
|
||||||
|
* @param string $path the absolute path
|
||||||
|
* @return string e.g. turns '/admin/files/test.txt' into '/test.txt'
|
||||||
|
*/
|
||||||
|
private function stripUserFilesPath($path) {
|
||||||
|
$trimmed = ltrim($path, '/');
|
||||||
|
$split = explode('/', $trimmed);
|
||||||
|
|
||||||
|
// it is not a file relative to data/user/files
|
||||||
|
if (count($split) < 3 || $split[1] !== 'files') {
|
||||||
|
\OCP\Util::writeLog('file sharing',
|
||||||
|
'Can not strip userid and "files/" from path: ' . $path,
|
||||||
|
\OCP\Util::DEBUG);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip 'user' and 'files'
|
||||||
|
$sliced = array_slice($split, 2);
|
||||||
|
$relPath = implode('/', $sliced);
|
||||||
|
|
||||||
|
return '/' . $relPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move the mount point to $target
|
||||||
|
*
|
||||||
|
* @param string $target the target mount point
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function moveMount($target) {
|
||||||
|
// it shouldn't be possible to move a Shared storage into another one
|
||||||
|
list($targetStorage,) = Filesystem::resolvePath($target);
|
||||||
|
if ($targetStorage instanceof Shared) {
|
||||||
|
\OCP\Util::writeLog('file sharing',
|
||||||
|
'It is not allowed to move one mount point into another one',
|
||||||
|
\OCP\Util::DEBUG);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$relTargetPath = $this->stripUserFilesPath($target);
|
||||||
|
$share = $this->storage->getShare();
|
||||||
|
|
||||||
|
$result = $this->updateFileTarget($relTargetPath, $share);
|
||||||
|
|
||||||
|
if ($result) {
|
||||||
|
$this->setMountPoint($target);
|
||||||
|
$this->storage->setUniqueName();
|
||||||
|
$this->storage->setMountPoint($relTargetPath);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
\OCP\Util::writeLog('file sharing',
|
||||||
|
'Could not rename mount point for shared folder "' . $this->getMountPoint() . '" to "' . $target . '"',
|
||||||
|
\OCP\Util::ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the mount points
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function removeMount() {
|
||||||
|
$storage = $this->getStorage();
|
||||||
|
$result = \OCP\Share::unshareFromSelf($storage->getItemType(), $storage->getMountPoint());
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace OC\Files\Storage;
|
namespace OC\Files\Storage;
|
||||||
|
use OC\Files\Filesystem;
|
||||||
|
use OCA\Files_Sharing\SharedMount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert target path to source path and pass the function call to the correct storage provider
|
* Convert target path to source path and pass the function call to the correct storage provider
|
||||||
|
@ -104,8 +106,8 @@ class Shared extends \OC\Files\Storage\Common {
|
||||||
*/
|
*/
|
||||||
public function getPermissions($target = '') {
|
public function getPermissions($target = '') {
|
||||||
$permissions = $this->share['permissions'];
|
$permissions = $this->share['permissions'];
|
||||||
// part file are always have delete permissions
|
// part files and the mount point always have delete permissions
|
||||||
if (pathinfo($target, PATHINFO_EXTENSION) === 'part') {
|
if ($target === '' || pathinfo($target, PATHINFO_EXTENSION) === 'part') {
|
||||||
$permissions |= \OCP\PERMISSION_DELETE;
|
$permissions |= \OCP\PERMISSION_DELETE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +128,18 @@ class Shared extends \OC\Files\Storage\Common {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete the directory if DELETE permission is granted
|
||||||
|
* @param string $path
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
public function rmdir($path) {
|
public function rmdir($path) {
|
||||||
|
|
||||||
|
// never delete a share mount point
|
||||||
|
if(empty($path)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (($source = $this->getSourcePath($path)) && $this->isDeletable($path)) {
|
if (($source = $this->getSourcePath($path)) && $this->isDeletable($path)) {
|
||||||
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
|
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
|
||||||
return $storage->rmdir($internalPath);
|
return $storage->rmdir($internalPath);
|
||||||
|
@ -254,9 +267,17 @@ class Shared extends \OC\Files\Storage\Common {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete the file if DELETE permission is granted
|
||||||
|
* @param string $path
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
public function unlink($path) {
|
public function unlink($path) {
|
||||||
// Delete the file if DELETE permission is granted
|
|
||||||
$path = ($path === false) ? '' : $path;
|
// never delete a share mount point
|
||||||
|
if (empty($path)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if ($source = $this->getSourcePath($path)) {
|
if ($source = $this->getSourcePath($path)) {
|
||||||
if ($this->isDeletable($path)) {
|
if ($this->isDeletable($path)) {
|
||||||
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
|
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
|
||||||
|
@ -266,124 +287,14 @@ class Shared extends \OC\Files\Storage\Common {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Format a path to be relative to the /user/files/ directory
|
|
||||||
* @param string $path the absolute path
|
|
||||||
* @return string e.g. turns '/admin/files/test.txt' into '/test.txt'
|
|
||||||
*/
|
|
||||||
private static function stripUserFilesPath($path) {
|
|
||||||
$trimmed = ltrim($path, '/');
|
|
||||||
$split = explode('/', $trimmed);
|
|
||||||
|
|
||||||
// it is not a file relative to data/user/files
|
|
||||||
if (count($split) < 3 || $split[1] !== 'files') {
|
|
||||||
\OCP\Util::writeLog('file sharing',
|
|
||||||
'Can not strip userid and "files/" from path: ' . $path,
|
|
||||||
\OCP\Util::DEBUG);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// skip 'user' and 'files'
|
|
||||||
$sliced = array_slice($split, 2);
|
|
||||||
$relPath = implode('/', $sliced);
|
|
||||||
|
|
||||||
return '/' . $relPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* rename a shared folder/file
|
|
||||||
* @param string $sourcePath
|
|
||||||
* @param string $targetPath
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
private function renameMountPoint($sourcePath, $targetPath) {
|
|
||||||
|
|
||||||
// it shouldn't be possible to move a Shared storage into another one
|
|
||||||
list($targetStorage, ) = \OC\Files\Filesystem::resolvePath($targetPath);
|
|
||||||
if ($targetStorage->instanceOfStorage('\OC\Files\Storage\Shared')) {
|
|
||||||
\OCP\Util::writeLog('file sharing',
|
|
||||||
'It is not allowed to move one mount point into another one',
|
|
||||||
\OCP\Util::DEBUG);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$relTargetPath = $this->stripUserFilesPath($targetPath);
|
|
||||||
|
|
||||||
if ($relTargetPath === false) {
|
|
||||||
\OCP\Util::writeLog('file sharing', 'Wrong target path given: ' . $targetPath, \OCP\Util::ERROR);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = self::updateFileTarget($relTargetPath, $this->share);
|
|
||||||
|
|
||||||
if ($result) {
|
|
||||||
// update the mount manager with the new paths
|
|
||||||
$mountManager = \OC\Files\Filesystem::getMountManager();
|
|
||||||
$mount = $mountManager->find($sourcePath);
|
|
||||||
$mount->setMountPoint($targetPath . '/');
|
|
||||||
$mountManager->addMount($mount);
|
|
||||||
$mountManager->removeMount($sourcePath . '/');
|
|
||||||
$this->setUniqueName();
|
|
||||||
$this->setMountPoint($relTargetPath);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
\OCP\Util::writeLog('file sharing',
|
|
||||||
'Could not rename mount point for shared folder "' . $sourcePath . '" to "' . $targetPath . '"',
|
|
||||||
\OCP\Util::ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (bool)$result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @update fileTarget in the database if the mount point changed
|
|
||||||
* @param string $newPath
|
|
||||||
* @param array $share reference to the share which should be modified
|
|
||||||
* @return type
|
|
||||||
*/
|
|
||||||
private static function updateFileTarget($newPath, &$share) {
|
|
||||||
// if the user renames a mount point from a group share we need to create a new db entry
|
|
||||||
// for the unique name
|
|
||||||
if ($share['share_type'] === \OCP\Share::SHARE_TYPE_GROUP &&
|
|
||||||
(isset($share['unique_name']) && $share['unique_name'])) {
|
|
||||||
$query = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`item_type`, `item_source`, `item_target`,'
|
|
||||||
.' `share_type`, `share_with`, `uid_owner`, `permissions`, `stime`, `file_source`,'
|
|
||||||
.' `file_target`, `token`, `parent`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)');
|
|
||||||
$arguments = array($share['item_type'], $share['item_source'], $share['item_target'],
|
|
||||||
2, \OCP\User::getUser(), $share['uid_owner'], $share['permissions'], $share['stime'], $share['file_source'],
|
|
||||||
$newPath, $share['token'], $share['id']);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// rename mount point
|
|
||||||
$query = \OC_DB::prepare(
|
|
||||||
'Update `*PREFIX*share`
|
|
||||||
SET `file_target` = ?
|
|
||||||
WHERE `id` = ?'
|
|
||||||
);
|
|
||||||
$arguments = array($newPath, $share['id']);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $query->execute($arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function rename($path1, $path2) {
|
public function rename($path1, $path2) {
|
||||||
|
|
||||||
$sourceMountPoint = \OC\Files\Filesystem::getMountPoint($path1);
|
// we need the paths relative to data/user/files
|
||||||
$targetMountPoint = \OC\Files\Filesystem::getMountPoint($path2);
|
$relPath1 = $this->getMountPoint() . '/' . $path1;
|
||||||
$relPath1 = \OCA\Files_Sharing\Helper::stripUserFilesPath($path1);
|
$relPath2 = $this->getMountPoint() . '/' . $path2;
|
||||||
$relPath2 = \OCA\Files_Sharing\Helper::stripUserFilesPath($path2);
|
|
||||||
|
|
||||||
// if we renamed the mount point we need to adjust the file_target in the
|
// check for update permissions on the share
|
||||||
// database
|
if ($this->isUpdatable('')) {
|
||||||
if (\OC\Files\Filesystem::normalizePath($sourceMountPoint) === \OC\Files\Filesystem::normalizePath($path1)) {
|
|
||||||
return $this->renameMountPoint($path1, $path2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if ( // Within the same mount point, we only need UPDATE permissions
|
|
||||||
($sourceMountPoint === $targetMountPoint && $this->isUpdatable($sourceMountPoint)) ||
|
|
||||||
// otherwise DELETE and CREATE permissions required
|
|
||||||
($this->isDeletable($path1) && $this->isCreatable(dirname($path2)))) {
|
|
||||||
|
|
||||||
$pathinfo = pathinfo($relPath1);
|
$pathinfo = pathinfo($relPath1);
|
||||||
// for part files we need to ask for the owner and path from the parent directory because
|
// for part files we need to ask for the owner and path from the parent directory because
|
||||||
|
@ -486,44 +397,25 @@ class Shared extends \OC\Files\Storage\Common {
|
||||||
|
|
||||||
public static function setup($options) {
|
public static function setup($options) {
|
||||||
$shares = \OCP\Share::getItemsSharedWith('file');
|
$shares = \OCP\Share::getItemsSharedWith('file');
|
||||||
|
$manager = Filesystem::getMountManager();
|
||||||
|
$loader = Filesystem::getLoader();
|
||||||
if (!\OCP\User::isLoggedIn() || \OCP\User::getUser() != $options['user']
|
if (!\OCP\User::isLoggedIn() || \OCP\User::getUser() != $options['user']
|
||||||
|| $shares
|
|| $shares
|
||||||
) {
|
) {
|
||||||
foreach ($shares as $share) {
|
foreach ($shares as $share) {
|
||||||
self::verifyMountPoint($share);
|
// don't mount shares where we have no permissions
|
||||||
\OC\Files\Filesystem::mount('\OC\Files\Storage\Shared',
|
if ($share['permissions'] > 0) {
|
||||||
|
$mount = new SharedMount(
|
||||||
|
'\OC\Files\Storage\Shared',
|
||||||
|
$options['user_dir'] . '/' . $share['file_target'],
|
||||||
array(
|
array(
|
||||||
'share' => $share,
|
'share' => $share,
|
||||||
),
|
),
|
||||||
$options['user_dir'] . '/' . $share['file_target']);
|
$loader
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* check if the parent folder exists otherwise move the mount point up
|
|
||||||
*
|
|
||||||
* @param array $share reference to the share we want to check
|
|
||||||
*/
|
|
||||||
private static function verifyMountPoint(&$share) {
|
|
||||||
$mountPoint = basename($share['file_target']);
|
|
||||||
$parent = dirname($share['file_target']);
|
|
||||||
|
|
||||||
while (!\OC\Files\Filesystem::is_dir($parent)) {
|
|
||||||
$parent = dirname($parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
$newMountPoint = \OCA\Files_Sharing\Helper::generateUniqueTarget(
|
|
||||||
\OC\Files\Filesystem::normalizePath($parent . '/' . $mountPoint),
|
|
||||||
array(),
|
|
||||||
new \OC\Files\View('/' . \OCP\User::getUser() . '/files')
|
|
||||||
);
|
);
|
||||||
|
$manager->addMount($mount);
|
||||||
if($newMountPoint !== $share['file_target']) {
|
}
|
||||||
|
}
|
||||||
self::updateFileTarget($newMountPoint, $share);
|
|
||||||
$share['file_target'] = $newMountPoint;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -536,28 +428,54 @@ class Shared extends \OC\Files\Storage\Common {
|
||||||
return $this->share['file_target'];
|
return $this->share['file_target'];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function setMountPoint($path) {
|
public function setMountPoint($path) {
|
||||||
$this->share['file_target'] = $path;
|
$this->share['file_target'] = $path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getShareType() {
|
||||||
|
return $this->share['share_type'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* does the group share already has a user specific unique name
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function uniqueNameSet() {
|
||||||
|
return (isset($this->share['unique_name']) && $this->share['unique_name']);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the share now uses a unique name of this user
|
* the share now uses a unique name of this user
|
||||||
*
|
*
|
||||||
* @brief the share now uses a unique name of this user
|
* @brief the share now uses a unique name of this user
|
||||||
*/
|
*/
|
||||||
private function setUniqueName() {
|
public function setUniqueName() {
|
||||||
$this->share['unique_name'] = true;
|
$this->share['unique_name'] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief get the user who shared the file
|
* get share ID
|
||||||
*
|
* @return integer unique share ID
|
||||||
|
*/
|
||||||
|
public function getShareId() {
|
||||||
|
return $this->share['id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the user who shared the file
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getSharedFrom() {
|
public function getSharedFrom() {
|
||||||
return $this->share['uid_owner'];
|
return $this->share['uid_owner'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getShare() {
|
||||||
|
return $this->share;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return share type, can be "file" or "folder"
|
* return share type, can be "file" or "folder"
|
||||||
* @return string
|
* @return string
|
||||||
|
|
|
@ -784,7 +784,7 @@ class Test_Files_Sharing_Api extends Test_Files_Sharing_Base {
|
||||||
$fileInfo = $this->view->getFileInfo($this->filename);
|
$fileInfo = $this->view->getFileInfo($this->filename);
|
||||||
|
|
||||||
$result = \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
|
$result = \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
|
||||||
\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2, 31);
|
\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2, \OCP\PERMISSION_ALL);
|
||||||
|
|
||||||
// share was successful?
|
// share was successful?
|
||||||
$this->assertTrue($result);
|
$this->assertTrue($result);
|
||||||
|
@ -816,9 +816,11 @@ class Test_Files_Sharing_Api extends Test_Files_Sharing_Base {
|
||||||
$this->assertTrue(is_array($linkShare));
|
$this->assertTrue(is_array($linkShare));
|
||||||
$this->assertTrue(is_array($userShare));
|
$this->assertTrue(is_array($userShare));
|
||||||
|
|
||||||
// update permissions
|
// check if share have expected permissions, single shared files never have
|
||||||
|
// delete permissions
|
||||||
|
$this->assertEquals(\OCP\PERMISSION_ALL & ~\OCP\PERMISSION_DELETE, $userShare['permissions']);
|
||||||
|
|
||||||
$this->assertEquals('31', $userShare['permissions']);
|
// update permissions
|
||||||
|
|
||||||
$params = array();
|
$params = array();
|
||||||
$params['id'] = $userShare['id'];
|
$params['id'] = $userShare['id'];
|
||||||
|
@ -893,7 +895,7 @@ class Test_Files_Sharing_Api extends Test_Files_Sharing_Base {
|
||||||
$items = \OCP\Share::getItemShared('file', null);
|
$items = \OCP\Share::getItemShared('file', null);
|
||||||
|
|
||||||
// make sure that we found a link share and a user share
|
// make sure that we found a link share and a user share
|
||||||
$this->assertEquals(count($items), 1);
|
$this->assertEquals(1, count($items));
|
||||||
|
|
||||||
$linkShare = null;
|
$linkShare = null;
|
||||||
|
|
||||||
|
|
|
@ -111,5 +111,10 @@ class Test_Files_Sharing_Permissions extends Test_Files_Sharing_Base {
|
||||||
$this->assertEquals(7, $contents[0]['permissions']);
|
$this->assertEquals(7, $contents[0]['permissions']);
|
||||||
$this->assertEquals('textfile1.txt', $contents[1]['name']);
|
$this->assertEquals('textfile1.txt', $contents[1]['name']);
|
||||||
$this->assertEquals(7, $contents[1]['permissions']);
|
$this->assertEquals(7, $contents[1]['permissions']);
|
||||||
|
|
||||||
|
// the share mount point should always have delete permissions to allow the user
|
||||||
|
// to unmount it
|
||||||
|
$restrictedShare = $this->secondView->getFileInfo('files/shareddirrestricted');
|
||||||
|
$this->assertEquals(7 | \OCP\PERMISSION_DELETE, $restrictedShare['permissions']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,173 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* ownCloud
|
||||||
|
*
|
||||||
|
* @author Bjoern Schiessle
|
||||||
|
* @copyright 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
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once __DIR__ . '/base.php';
|
||||||
|
|
||||||
|
use OCA\Files\Share;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Test_Files_Sharing
|
||||||
|
*/
|
||||||
|
class Test_Files_Sharing extends Test_Files_Sharing_Base {
|
||||||
|
|
||||||
|
const TEST_FOLDER_NAME = '/folder_share_api_test';
|
||||||
|
|
||||||
|
private static $tempStorage;
|
||||||
|
|
||||||
|
function setUp() {
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->folder = self::TEST_FOLDER_NAME;
|
||||||
|
$this->subfolder = '/subfolder_share_api_test';
|
||||||
|
$this->subsubfolder = '/subsubfolder_share_api_test';
|
||||||
|
|
||||||
|
$this->filename = '/share-api-test.txt';
|
||||||
|
|
||||||
|
// save file with content
|
||||||
|
$this->view->file_put_contents($this->filename, $this->data);
|
||||||
|
$this->view->mkdir($this->folder);
|
||||||
|
$this->view->mkdir($this->folder . $this->subfolder);
|
||||||
|
$this->view->mkdir($this->folder . $this->subfolder . $this->subsubfolder);
|
||||||
|
$this->view->file_put_contents($this->folder.$this->filename, $this->data);
|
||||||
|
$this->view->file_put_contents($this->folder . $this->subfolder . $this->filename, $this->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
function tearDown() {
|
||||||
|
$this->view->unlink($this->filename);
|
||||||
|
$this->view->deleteAll($this->folder);
|
||||||
|
|
||||||
|
self::$tempStorage = null;
|
||||||
|
|
||||||
|
parent::tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testUnshareFromSelf() {
|
||||||
|
|
||||||
|
\OC_Group::createGroup('testGroup');
|
||||||
|
\OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER2, 'testGroup');
|
||||||
|
\OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER3, 'testGroup');
|
||||||
|
|
||||||
|
$fileinfo = $this->view->getFileInfo($this->filename);
|
||||||
|
|
||||||
|
$pathinfo = pathinfo($this->filename);
|
||||||
|
|
||||||
|
$duplicate = '/' . $pathinfo['filename'] . ' (2).' . $pathinfo['extension'];
|
||||||
|
|
||||||
|
$result = \OCP\Share::shareItem('file', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
|
||||||
|
\Test_Files_Sharing::TEST_FILES_SHARING_API_USER2, 31);
|
||||||
|
|
||||||
|
$this->assertTrue($result);
|
||||||
|
|
||||||
|
$result = \OCP\Share::shareItem('file', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_GROUP,
|
||||||
|
'testGroup', 31);
|
||||||
|
|
||||||
|
$this->assertTrue($result);
|
||||||
|
|
||||||
|
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||||
|
$this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename));
|
||||||
|
$this->assertTrue(\OC\Files\Filesystem::file_exists($duplicate));
|
||||||
|
|
||||||
|
self::loginHelper(self::TEST_FILES_SHARING_API_USER3);
|
||||||
|
$this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename));
|
||||||
|
$this->assertFalse(\OC\Files\Filesystem::file_exists($duplicate));
|
||||||
|
|
||||||
|
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||||
|
\OC\Files\Filesystem::unlink($this->filename);
|
||||||
|
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||||
|
$this->assertFalse(\OC\Files\Filesystem::file_exists($this->filename));
|
||||||
|
$this->assertTrue(\OC\Files\Filesystem::file_exists($duplicate));
|
||||||
|
|
||||||
|
// for user3 nothing should change
|
||||||
|
self::loginHelper(self::TEST_FILES_SHARING_API_USER3);
|
||||||
|
$this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename));
|
||||||
|
$this->assertFalse(\OC\Files\Filesystem::file_exists($duplicate));
|
||||||
|
|
||||||
|
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||||
|
\OC\Files\Filesystem::unlink($duplicate);
|
||||||
|
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||||
|
$this->assertFalse(\OC\Files\Filesystem::file_exists($this->filename));
|
||||||
|
$this->assertFalse(\OC\Files\Filesystem::file_exists($duplicate));
|
||||||
|
|
||||||
|
// for user3 nothing should change
|
||||||
|
self::loginHelper(self::TEST_FILES_SHARING_API_USER3);
|
||||||
|
$this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename));
|
||||||
|
$this->assertFalse(\OC\Files\Filesystem::file_exists($duplicate));
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
|
||||||
|
\OCP\Share::unshare('file', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_GROUP,
|
||||||
|
'testGroup');
|
||||||
|
\OCP\Share::unshare('file', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
|
||||||
|
self::TEST_FILES_SHARING_API_USER2);
|
||||||
|
\OC_Group::removeFromGroup(self::TEST_FILES_SHARING_API_USER2, 'testGroup');
|
||||||
|
\OC_Group::removeFromGroup(self::TEST_FILES_SHARING_API_USER2, 'testGroup');
|
||||||
|
\OC_Group::deleteGroup('testGroup');
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shared files should never have delete permissions
|
||||||
|
* @dataProvider DataProviderTestFileSharePermissions
|
||||||
|
*/
|
||||||
|
function testFileSharePermissions($permission, $expectedPermissions) {
|
||||||
|
|
||||||
|
$fileinfo = $this->view->getFileInfo($this->filename);
|
||||||
|
|
||||||
|
$result = \OCP\Share::shareItem('file', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
|
||||||
|
\Test_Files_Sharing::TEST_FILES_SHARING_API_USER2, $permission);
|
||||||
|
|
||||||
|
$this->assertTrue($result);
|
||||||
|
|
||||||
|
$result = \OCP\Share::getItemShared('file', null);
|
||||||
|
|
||||||
|
$this->assertTrue(is_array($result));
|
||||||
|
|
||||||
|
// test should return exactly one shares created from testCreateShare()
|
||||||
|
$this->assertTrue(count($result) === 1);
|
||||||
|
|
||||||
|
$share = reset($result);
|
||||||
|
$this->assertSame($expectedPermissions, $share['permissions']);
|
||||||
|
|
||||||
|
\OCP\Share::unshare('file', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
|
||||||
|
\Test_Files_Sharing::TEST_FILES_SHARING_API_USER2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function DataProviderTestFileSharePermissions() {
|
||||||
|
$permission1 = \OCP\PERMISSION_ALL;
|
||||||
|
$permission2 = \OCP\PERMISSION_DELETE;
|
||||||
|
$permission3 = \OCP\PERMISSION_READ;
|
||||||
|
$permission4 = \OCP\PERMISSION_READ | \OCP\PERMISSION_UPDATE;
|
||||||
|
$permission5 = \OCP\PERMISSION_READ | \OCP\PERMISSION_DELETE;
|
||||||
|
$permission6 = \OCP\PERMISSION_READ | \OCP\PERMISSION_UPDATE | \OCP\PERMISSION_DELETE;
|
||||||
|
|
||||||
|
return array(
|
||||||
|
array($permission1, \OCP\PERMISSION_ALL & ~\OCP\PERMISSION_DELETE),
|
||||||
|
array($permission2, 0),
|
||||||
|
array($permission3, $permission3),
|
||||||
|
array($permission4, $permission4),
|
||||||
|
array($permission5, $permission3),
|
||||||
|
array($permission6, $permission4),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,197 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* ownCloud
|
||||||
|
*
|
||||||
|
* @author Bjoern Schiessle
|
||||||
|
* @copyright 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
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once __DIR__ . '/base.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Test_Files_Sharing_Api
|
||||||
|
*/
|
||||||
|
class Test_Files_Sharing_Mount extends Test_Files_Sharing_Base {
|
||||||
|
|
||||||
|
function setUp() {
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->folder = '/folder_share_storage_test';
|
||||||
|
|
||||||
|
$this->filename = '/share-api-storage.txt';
|
||||||
|
|
||||||
|
|
||||||
|
$this->view->mkdir($this->folder);
|
||||||
|
|
||||||
|
// save file with content
|
||||||
|
$this->view->file_put_contents($this->filename, "root file");
|
||||||
|
$this->view->file_put_contents($this->folder . $this->filename, "file in subfolder");
|
||||||
|
}
|
||||||
|
|
||||||
|
function tearDown() {
|
||||||
|
$this->view->unlink($this->folder);
|
||||||
|
$this->view->unlink($this->filename);
|
||||||
|
|
||||||
|
parent::tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test if the mount point moves up if the parent folder no longer exists
|
||||||
|
*/
|
||||||
|
function testShareMountLoseParentFolder() {
|
||||||
|
|
||||||
|
// share to user
|
||||||
|
$fileinfo = $this->view->getFileInfo($this->folder);
|
||||||
|
$result = \OCP\Share::shareItem('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
|
||||||
|
self::TEST_FILES_SHARING_API_USER2, 31);
|
||||||
|
|
||||||
|
$statement = "UPDATE `*PREFIX*share` SET `file_target` = ? where `share_with` = ?";
|
||||||
|
$query = \OC_DB::prepare($statement);
|
||||||
|
$arguments = array('/foo/bar' . $this->folder, self::TEST_FILES_SHARING_API_USER2);
|
||||||
|
$query->execute($arguments);
|
||||||
|
|
||||||
|
$query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share`');
|
||||||
|
$result = $query->execute();
|
||||||
|
|
||||||
|
$shares = $result->fetchAll();
|
||||||
|
|
||||||
|
$this->assertSame(1, count($shares));
|
||||||
|
|
||||||
|
$share = reset($shares);
|
||||||
|
$this->assertSame('/foo/bar' . $this->folder, $share['file_target']);
|
||||||
|
|
||||||
|
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||||
|
|
||||||
|
// share should have moved up
|
||||||
|
|
||||||
|
$query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share`');
|
||||||
|
$result = $query->execute();
|
||||||
|
|
||||||
|
$shares = $result->fetchAll();
|
||||||
|
|
||||||
|
$this->assertSame(1, count($shares));
|
||||||
|
|
||||||
|
$share = reset($shares);
|
||||||
|
$this->assertSame($this->folder, $share['file_target']);
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
|
||||||
|
\OCP\Share::unshare('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER, self::TEST_FILES_SHARING_API_USER2);
|
||||||
|
$this->view->unlink($this->folder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @medium
|
||||||
|
*/
|
||||||
|
function testDeleteParentOfMountPoint() {
|
||||||
|
|
||||||
|
// share to user
|
||||||
|
$fileinfo = $this->view->getFileInfo($this->folder);
|
||||||
|
$result = \OCP\Share::shareItem('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
|
||||||
|
self::TEST_FILES_SHARING_API_USER2, 31);
|
||||||
|
|
||||||
|
$this->assertTrue($result);
|
||||||
|
|
||||||
|
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||||
|
$user2View = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files');
|
||||||
|
$this->assertTrue($user2View->file_exists($this->folder));
|
||||||
|
|
||||||
|
// create a local folder
|
||||||
|
$result = $user2View->mkdir('localfolder');
|
||||||
|
$this->assertTrue($result);
|
||||||
|
|
||||||
|
// move mount point to local folder
|
||||||
|
$result = $user2View->rename($this->folder, '/localfolder/' . $this->folder);
|
||||||
|
$this->assertTrue($result);
|
||||||
|
|
||||||
|
// mount point in the root folder should no longer exist
|
||||||
|
$this->assertFalse($user2View->is_dir($this->folder));
|
||||||
|
|
||||||
|
// delete the local folder
|
||||||
|
$result = $user2View->unlink('/localfolder');
|
||||||
|
$this->assertTrue($result);
|
||||||
|
|
||||||
|
//enforce reload of the mount points
|
||||||
|
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||||
|
|
||||||
|
//mount point should be back at the root
|
||||||
|
$this->assertTrue($user2View->is_dir($this->folder));
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
|
||||||
|
$this->view->unlink($this->folder);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testMoveSharedFile() {
|
||||||
|
$fileinfo = $this->view->getFileInfo($this->filename);
|
||||||
|
$result = \OCP\Share::shareItem('file', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
|
||||||
|
self::TEST_FILES_SHARING_API_USER2, 31);
|
||||||
|
|
||||||
|
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||||
|
|
||||||
|
\OC\Files\Filesystem::rename($this->filename, "newFileName");
|
||||||
|
|
||||||
|
$this->assertTrue(\OC\Files\Filesystem::file_exists('newFileName'));
|
||||||
|
$this->assertFalse(\OC\Files\Filesystem::file_exists($this->filename));
|
||||||
|
|
||||||
|
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
|
||||||
|
$this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename));
|
||||||
|
$this->assertFalse(\OC\Files\Filesystem::file_exists("newFileName"));
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
\OCP\Share::unshare('file', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER, self::TEST_FILES_SHARING_API_USER2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* share file with a group if a user renames the file the filename should not change
|
||||||
|
* for the other users
|
||||||
|
*/
|
||||||
|
function testMoveGroupShare () {
|
||||||
|
\OC_Group::createGroup('testGroup');
|
||||||
|
\OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER1, 'testGroup');
|
||||||
|
\OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER2, 'testGroup');
|
||||||
|
\OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER3, 'testGroup');
|
||||||
|
|
||||||
|
$fileinfo = $this->view->getFileInfo($this->filename);
|
||||||
|
$result = \OCP\Share::shareItem('file', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_GROUP,
|
||||||
|
"testGroup", 31);
|
||||||
|
|
||||||
|
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||||
|
|
||||||
|
$this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename));
|
||||||
|
|
||||||
|
\OC\Files\Filesystem::rename($this->filename, "newFileName");
|
||||||
|
|
||||||
|
$this->assertTrue(\OC\Files\Filesystem::file_exists('newFileName'));
|
||||||
|
$this->assertFalse(\OC\Files\Filesystem::file_exists($this->filename));
|
||||||
|
|
||||||
|
self::loginHelper(self::TEST_FILES_SHARING_API_USER3);
|
||||||
|
$this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename));
|
||||||
|
$this->assertFalse(\OC\Files\Filesystem::file_exists("newFileName"));
|
||||||
|
|
||||||
|
self::loginHelper(self::TEST_FILES_SHARING_API_USER3);
|
||||||
|
$this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename));
|
||||||
|
$this->assertFalse(\OC\Files\Filesystem::file_exists("newFileName"));
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
\OCP\Share::unshare('file', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_GROUP, 'testGroup');
|
||||||
|
\OC_Group::removeFromGroup(self::TEST_FILES_SHARING_API_USER1, 'testGroup');
|
||||||
|
\OC_Group::removeFromGroup(self::TEST_FILES_SHARING_API_USER2, 'testGroup');
|
||||||
|
\OC_Group::removeFromGroup(self::TEST_FILES_SHARING_API_USER3, 'testGroup');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,233 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* ownCloud
|
||||||
|
*
|
||||||
|
* @author Morris Jobke, Bjoern Schiessle
|
||||||
|
* @copyright 2014 Morris Jobke <morris.jobke@gmail.com>
|
||||||
|
* 2014 Bjoern Schiessle <schiessle@ownlcoud.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/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../appinfo/update.php';
|
||||||
|
require_once __DIR__ . '/base.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Test_Files_Sharing_Update
|
||||||
|
*/
|
||||||
|
class Test_Files_Sharing_Update_Routine extends Test_Files_Sharing_Base {
|
||||||
|
|
||||||
|
const TEST_FOLDER_NAME = '/folder_share_api_test';
|
||||||
|
|
||||||
|
function setUp() {
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->folder = self::TEST_FOLDER_NAME;
|
||||||
|
|
||||||
|
$this->filename = '/share-api-test.txt';
|
||||||
|
|
||||||
|
// save file with content
|
||||||
|
$this->view->file_put_contents($this->filename, $this->data);
|
||||||
|
$this->view->mkdir($this->folder);
|
||||||
|
$this->view->file_put_contents($this->folder . '/' . $this->filename, $this->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
function tearDown() {
|
||||||
|
$this->view->unlink($this->filename);
|
||||||
|
$this->view->deleteAll($this->folder);
|
||||||
|
|
||||||
|
$removeShares = \OC_DB::prepare('DELETE FROM `*PREFIX*share`');
|
||||||
|
$removeShares->execute();
|
||||||
|
$removeItems = \OC_DB::prepare('DELETE FROM `*PREFIX*filecache`');
|
||||||
|
$removeItems->execute();
|
||||||
|
|
||||||
|
parent::tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test update of file permission. The update should remove from all shared
|
||||||
|
* files the delete permission
|
||||||
|
*/
|
||||||
|
function testUpdateFilePermissions() {
|
||||||
|
|
||||||
|
self::prepareDBUpdateFilePermissions();
|
||||||
|
// run the update routine to update the share permission
|
||||||
|
updateFilePermissions(2);
|
||||||
|
|
||||||
|
// verify results
|
||||||
|
$query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share`');
|
||||||
|
$result = $query->execute(array());
|
||||||
|
|
||||||
|
while ($row = $result->fetchRow()) {
|
||||||
|
if ($row['item_type'] === 'file') {
|
||||||
|
// for all files the delete permission should be removed
|
||||||
|
$this->assertSame(0, (int)$row['permissions'] & \OCP\PERMISSION_DELETE);
|
||||||
|
} else {
|
||||||
|
// for all other the permission shouldn't change
|
||||||
|
$this->assertSame(31, (int)$row['permissions'] & \OCP\PERMISSION_ALL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanup
|
||||||
|
$this->cleanupSharedTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @medium
|
||||||
|
*/
|
||||||
|
function testRemoveBrokenShares() {
|
||||||
|
|
||||||
|
$this->prepareFileCache();
|
||||||
|
|
||||||
|
// check if there are just 3 shares (see setUp - precondition: empty table)
|
||||||
|
$countShares = \OC_DB::prepare('SELECT COUNT(`id`) FROM `*PREFIX*share`');
|
||||||
|
$result = $countShares->execute()->fetchOne();
|
||||||
|
$this->assertEquals(3, $result);
|
||||||
|
|
||||||
|
// check if there are just 2 items (see setUp - precondition: empty table)
|
||||||
|
$countItems = \OC_DB::prepare('SELECT COUNT(`fileid`) FROM `*PREFIX*filecache`');
|
||||||
|
$result = $countItems->execute()->fetchOne();
|
||||||
|
$this->assertEquals(2, $result);
|
||||||
|
|
||||||
|
// execute actual code which should be tested
|
||||||
|
\OC\Files\Cache\Shared_Updater::fixBrokenSharesOnAppUpdate();
|
||||||
|
|
||||||
|
// check if there are just 2 shares (one gets killed by the code as there is no filecache entry for this)
|
||||||
|
$countShares = \OC_DB::prepare('SELECT COUNT(`id`) FROM `*PREFIX*share`');
|
||||||
|
$result = $countShares->execute()->fetchOne();
|
||||||
|
$this->assertEquals(2, $result);
|
||||||
|
|
||||||
|
// check if the share of file '200' is removed as there is no entry for this in filecache table
|
||||||
|
$countShares = \OC_DB::prepare('SELECT COUNT(`id`) FROM `*PREFIX*share` WHERE `file_source` = 200');
|
||||||
|
$result = $countShares->execute()->fetchOne();
|
||||||
|
$this->assertEquals(0, $result);
|
||||||
|
|
||||||
|
// check if there are just 2 items
|
||||||
|
$countItems = \OC_DB::prepare('SELECT COUNT(`fileid`) FROM `*PREFIX*filecache`');
|
||||||
|
$result = $countItems->execute()->fetchOne();
|
||||||
|
$this->assertEquals(2, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test update for the removal of the logical "Shared" folder. It should update
|
||||||
|
* the file_target for every share and create a physical "Shared" folder for each user
|
||||||
|
*/
|
||||||
|
function testRemoveSharedFolder() {
|
||||||
|
self::prepareDB();
|
||||||
|
// run the update routine to remove the shared folder and replace it with a real folder
|
||||||
|
removeSharedFolder(false, 2);
|
||||||
|
|
||||||
|
// verify results
|
||||||
|
$query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share`');
|
||||||
|
$result = $query->execute(array());
|
||||||
|
|
||||||
|
$newDBContent = $result->fetchAll();
|
||||||
|
|
||||||
|
foreach ($newDBContent as $row) {
|
||||||
|
if ((int)$row['share_type'] === \OCP\Share::SHARE_TYPE_USER) {
|
||||||
|
$this->assertSame('/Shared', substr($row['file_target'], 0, strlen('/Shared')));
|
||||||
|
} else {
|
||||||
|
$this->assertSame('/ShouldNotChange', $row['file_target']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanup
|
||||||
|
$this->cleanupSharedTable();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function cleanupSharedTable() {
|
||||||
|
$query = \OC_DB::prepare('DELETE FROM `*PREFIX*share`');
|
||||||
|
$query->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prepare sharing table for testRemoveSharedFolder()
|
||||||
|
*/
|
||||||
|
private function prepareDB() {
|
||||||
|
$this->cleanupSharedTable();
|
||||||
|
// add items except one - because this is the test case for the broken share table
|
||||||
|
$addItems = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`share_type`, `item_type`, ' .
|
||||||
|
'`share_with`, `uid_owner` , `file_target`) ' .
|
||||||
|
'VALUES (?, ?, ?, ?, ?)');
|
||||||
|
$items = array(
|
||||||
|
array(\OCP\Share::SHARE_TYPE_USER, 'file', 'user1', 'admin' , '/foo'),
|
||||||
|
array(\OCP\Share::SHARE_TYPE_USER, 'folder', 'user2', 'admin', '/foo2'),
|
||||||
|
array(\OCP\Share::SHARE_TYPE_USER, 'file', 'user3', 'admin', '/foo3'),
|
||||||
|
array(\OCP\Share::SHARE_TYPE_USER, 'folder', 'user4', 'admin', '/foo4'),
|
||||||
|
array(\OCP\Share::SHARE_TYPE_LINK, 'file', 'user1', 'admin', '/ShouldNotChange'),
|
||||||
|
array(\OCP\Share::SHARE_TYPE_CONTACT, 'contact', 'admin', 'user1', '/ShouldNotChange'),
|
||||||
|
|
||||||
|
);
|
||||||
|
foreach($items as $item) {
|
||||||
|
// the number is used as path_hash
|
||||||
|
$addItems->execute($item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prepare sharing table for testUpdateFilePermissions()
|
||||||
|
*/
|
||||||
|
private function prepareDBUpdateFilePermissions() {
|
||||||
|
$this->cleanupSharedTable();
|
||||||
|
// add items except one - because this is the test case for the broken share table
|
||||||
|
$addItems = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`share_type`, `item_type`, ' .
|
||||||
|
'`share_with`, `uid_owner` , `file_target`, `permissions`) ' .
|
||||||
|
'VALUES (?, ?, ?, ?, ?, ?)');
|
||||||
|
$items = array(
|
||||||
|
array(\OCP\Share::SHARE_TYPE_LINK, 'file', 'user1', 'admin', '/foo', \OCP\PERMISSION_ALL),
|
||||||
|
array(\OCP\Share::SHARE_TYPE_CONTACT, 'contact', 'admin', 'user1', '/foo', \OCP\PERMISSION_ALL),
|
||||||
|
array(\OCP\Share::SHARE_TYPE_USER, 'folder', 'user4', 'admin', '/foo', \OCP\PERMISSION_ALL),
|
||||||
|
array(\OCP\Share::SHARE_TYPE_USER, 'file', 'user3', 'admin', '/foo3', \OCP\PERMISSION_ALL),
|
||||||
|
array(\OCP\Share::SHARE_TYPE_USER, 'file', 'user1', 'admin' , '/foo', \OCP\PERMISSION_DELETE),
|
||||||
|
array(\OCP\Share::SHARE_TYPE_USER, 'file', 'user1', 'admin' , '/foo', \OCP\PERMISSION_READ & \OCP\PERMISSION_DELETE),
|
||||||
|
array(\OCP\Share::SHARE_TYPE_USER, 'file', 'user1', 'admin' , '/foo', \OCP\PERMISSION_SHARE & \OCP\PERMISSION_UPDATE),
|
||||||
|
array(\OCP\Share::SHARE_TYPE_USER, 'file', 'user1', 'admin' , '/foo', \OCP\PERMISSION_ALL),
|
||||||
|
array(\OCP\Share::SHARE_TYPE_USER, 'file', 'user1', 'admin' , '/foo', \OCP\PERMISSION_SHARE & \OCP\PERMISSION_READ & \OCP\PERMISSION_DELETE),
|
||||||
|
);
|
||||||
|
foreach($items as $item) {
|
||||||
|
// the number is used as path_hash
|
||||||
|
$addItems->execute($item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prepare file cache for testRemoveBrokenShares()
|
||||||
|
*/
|
||||||
|
private function prepareFileCache() {
|
||||||
|
// some previous tests didn't clean up and therefore this has to be done here
|
||||||
|
// FIXME: DIRTY HACK - TODO: find tests, that don't clean up and fix it there
|
||||||
|
$this->tearDown();
|
||||||
|
|
||||||
|
// add items except one - because this is the test case for the broken share table
|
||||||
|
$addItems = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache` (`storage`, `path_hash`, ' .
|
||||||
|
'`parent`, `mimetype`, `mimepart`, `size`, `mtime`, `storage_mtime`) ' .
|
||||||
|
'VALUES (1, ?, 1, 1, 1, 1, 1, 1)');
|
||||||
|
$items = array(1, 3);
|
||||||
|
$fileIds = array();
|
||||||
|
foreach($items as $item) {
|
||||||
|
// the number is used as path_hash
|
||||||
|
$addItems->execute(array($item));
|
||||||
|
$fileIds[] = \OC_DB::insertId('*PREFIX*filecache');
|
||||||
|
}
|
||||||
|
|
||||||
|
$addShares = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`file_source`, `item_type`, `uid_owner`) VALUES (?, \'file\', 1)');
|
||||||
|
// the number is used as item_source
|
||||||
|
$addShares->execute(array($fileIds[0]));
|
||||||
|
$addShares->execute(array(200)); // id of "deleted" file
|
||||||
|
$addShares->execute(array($fileIds[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -47,11 +47,6 @@ class Test_Files_Sharing_Updater extends Test_Files_Sharing_Base {
|
||||||
$this->view->unlink($this->filename);
|
$this->view->unlink($this->filename);
|
||||||
$this->view->deleteAll($this->folder);
|
$this->view->deleteAll($this->folder);
|
||||||
|
|
||||||
$removeShares = \OC_DB::prepare('DELETE FROM `*PREFIX*share`');
|
|
||||||
$removeShares->execute();
|
|
||||||
$removeItems = \OC_DB::prepare('DELETE FROM `*PREFIX*filecache`');
|
|
||||||
$removeItems->execute();
|
|
||||||
|
|
||||||
parent::tearDown();
|
parent::tearDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,124 +106,4 @@ class Test_Files_Sharing_Updater extends Test_Files_Sharing_Base {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @medium
|
|
||||||
*/
|
|
||||||
function testRemoveBrokenShares() {
|
|
||||||
|
|
||||||
$this->prepareFileCache();
|
|
||||||
|
|
||||||
// check if there are just 3 shares (see setUp - precondition: empty table)
|
|
||||||
$countShares = \OC_DB::prepare('SELECT COUNT(`id`) FROM `*PREFIX*share`');
|
|
||||||
$result = $countShares->execute()->fetchOne();
|
|
||||||
$this->assertEquals(3, $result);
|
|
||||||
|
|
||||||
// check if there are just 2 items (see setUp - precondition: empty table)
|
|
||||||
$countItems = \OC_DB::prepare('SELECT COUNT(`fileid`) FROM `*PREFIX*filecache`');
|
|
||||||
$result = $countItems->execute()->fetchOne();
|
|
||||||
$this->assertEquals(2, $result);
|
|
||||||
|
|
||||||
// execute actual code which should be tested
|
|
||||||
\OC\Files\Cache\Shared_Updater::fixBrokenSharesOnAppUpdate();
|
|
||||||
|
|
||||||
// check if there are just 2 shares (one gets killed by the code as there is no filecache entry for this)
|
|
||||||
$countShares = \OC_DB::prepare('SELECT COUNT(`id`) FROM `*PREFIX*share`');
|
|
||||||
$result = $countShares->execute()->fetchOne();
|
|
||||||
$this->assertEquals(2, $result);
|
|
||||||
|
|
||||||
// check if the share of file '200' is removed as there is no entry for this in filecache table
|
|
||||||
$countShares = \OC_DB::prepare('SELECT COUNT(`id`) FROM `*PREFIX*share` WHERE `file_source` = 200');
|
|
||||||
$result = $countShares->execute()->fetchOne();
|
|
||||||
$this->assertEquals(0, $result);
|
|
||||||
|
|
||||||
// check if there are just 2 items
|
|
||||||
$countItems = \OC_DB::prepare('SELECT COUNT(`fileid`) FROM `*PREFIX*filecache`');
|
|
||||||
$result = $countItems->execute()->fetchOne();
|
|
||||||
$this->assertEquals(2, $result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* test update for the removal of the logical "Shared" folder. It should update
|
|
||||||
* the file_target for every share and create a physical "Shared" folder for each user
|
|
||||||
*/
|
|
||||||
function testRemoveSharedFolder() {
|
|
||||||
self::prepareDB();
|
|
||||||
// run the update routine to remove the shared folder and replace it with a real folder
|
|
||||||
removeSharedFolder(false, 2);
|
|
||||||
|
|
||||||
// verify results
|
|
||||||
$query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share`');
|
|
||||||
$result = $query->execute(array());
|
|
||||||
|
|
||||||
$newDBContent = $result->fetchAll();
|
|
||||||
|
|
||||||
foreach ($newDBContent as $row) {
|
|
||||||
if ((int)$row['share_type'] === \OCP\Share::SHARE_TYPE_USER) {
|
|
||||||
$this->assertSame('/Shared', substr($row['file_target'], 0, strlen('/Shared')));
|
|
||||||
} else {
|
|
||||||
$this->assertSame('/ShouldNotChange', $row['file_target']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// cleanup
|
|
||||||
$this->cleanupSharedTable();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private function cleanupSharedTable() {
|
|
||||||
$query = \OC_DB::prepare('DELETE FROM `*PREFIX*share`');
|
|
||||||
$query->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* prepare sharing table for testRemoveSharedFolder()
|
|
||||||
*/
|
|
||||||
private function prepareDB() {
|
|
||||||
$this->cleanupSharedTable();
|
|
||||||
// add items except one - because this is the test case for the broken share table
|
|
||||||
$addItems = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`share_type`, `item_type`, ' .
|
|
||||||
'`share_with`, `uid_owner` , `file_target`) ' .
|
|
||||||
'VALUES (?, ?, ?, ?, ?)');
|
|
||||||
$items = array(
|
|
||||||
array(\OCP\Share::SHARE_TYPE_USER, 'file', 'user1', 'admin' , '/foo'),
|
|
||||||
array(\OCP\Share::SHARE_TYPE_USER, 'folder', 'user2', 'admin', '/foo2'),
|
|
||||||
array(\OCP\Share::SHARE_TYPE_USER, 'file', 'user3', 'admin', '/foo3'),
|
|
||||||
array(\OCP\Share::SHARE_TYPE_USER, 'folder', 'user4', 'admin', '/foo4'),
|
|
||||||
array(\OCP\Share::SHARE_TYPE_LINK, 'file', 'user1', 'admin', '/ShouldNotChange'),
|
|
||||||
array(\OCP\Share::SHARE_TYPE_CONTACT, 'contact', 'admin', 'user1', '/ShouldNotChange'),
|
|
||||||
|
|
||||||
);
|
|
||||||
foreach($items as $item) {
|
|
||||||
// the number is used as path_hash
|
|
||||||
$addItems->execute($item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* prepare file cache for testRemoveBrokenShares()
|
|
||||||
*/
|
|
||||||
private function prepareFileCache() {
|
|
||||||
// some previous tests didn't clean up and therefore this has to be done here
|
|
||||||
// FIXME: DIRTY HACK - TODO: find tests, that don't clean up and fix it there
|
|
||||||
$this->tearDown();
|
|
||||||
|
|
||||||
// add items except one - because this is the test case for the broken share table
|
|
||||||
$addItems = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache` (`storage`, `path_hash`, ' .
|
|
||||||
'`parent`, `mimetype`, `mimepart`, `size`, `mtime`, `storage_mtime`) ' .
|
|
||||||
'VALUES (1, ?, 1, 1, 1, 1, 1, 1)');
|
|
||||||
$items = array(1, 3);
|
|
||||||
$fileIds = array();
|
|
||||||
foreach($items as $item) {
|
|
||||||
// the number is used as path_hash
|
|
||||||
$addItems->execute(array($item));
|
|
||||||
$fileIds[] = \OC_DB::insertId('*PREFIX*filecache');
|
|
||||||
}
|
|
||||||
|
|
||||||
$addShares = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`file_source`, `item_type`, `uid_owner`) VALUES (?, \'file\', 1)');
|
|
||||||
// the number is used as item_source
|
|
||||||
$addShares->execute(array($fileIds[0]));
|
|
||||||
$addShares->execute(array(200)); // id of "deleted" file
|
|
||||||
$addShares->execute(array($fileIds[1]));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,10 +126,6 @@ class ObjectTree extends \Sabre\DAV\ObjectTree {
|
||||||
throw new \Sabre\DAV\Exception\Forbidden();
|
throw new \Sabre\DAV\Exception\Forbidden();
|
||||||
}
|
}
|
||||||
if ($sourceDir !== $destinationDir) {
|
if ($sourceDir !== $destinationDir) {
|
||||||
// for a full move we need update privileges on sourcePath and sourceDir as well as destinationDir
|
|
||||||
if (ltrim($destinationDir, '/') === '') {
|
|
||||||
throw new \Sabre\DAV\Exception\Forbidden();
|
|
||||||
}
|
|
||||||
if (!$this->fileView->isUpdatable($sourceDir)) {
|
if (!$this->fileView->isUpdatable($sourceDir)) {
|
||||||
throw new \Sabre\DAV\Exception\Forbidden();
|
throw new \Sabre\DAV\Exception\Forbidden();
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,10 @@ class Updater {
|
||||||
* @var string $internalTo
|
* @var string $internalTo
|
||||||
*/
|
*/
|
||||||
list($storageFrom, $internalFrom) = self::resolvePath($from);
|
list($storageFrom, $internalFrom) = self::resolvePath($from);
|
||||||
|
// if it's a moved mountpoint we dont need to do anything
|
||||||
|
if ($internalFrom === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
list($storageTo, $internalTo) = self::resolvePath($to);
|
list($storageTo, $internalTo) = self::resolvePath($to);
|
||||||
if ($storageFrom && $storageTo) {
|
if ($storageFrom && $storageTo) {
|
||||||
if ($storageFrom === $storageTo) {
|
if ($storageFrom === $storageTo) {
|
||||||
|
|
|
@ -108,7 +108,7 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getName() {
|
public function getName() {
|
||||||
return $this->data['name'];
|
return basename($this->getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -30,6 +30,15 @@ class Manager {
|
||||||
unset($this->mounts[$mountPoint]);
|
unset($this->mounts[$mountPoint]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $mountPoint
|
||||||
|
* @param string $target
|
||||||
|
*/
|
||||||
|
public function moveMount($mountPoint, $target){
|
||||||
|
$this->mounts[$target] = $this->mounts[$mountPoint];
|
||||||
|
unset($this->mounts[$mountPoint]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the mount for $path
|
* Find the mount for $path
|
||||||
*
|
*
|
||||||
|
|
|
@ -16,11 +16,11 @@ class Mount {
|
||||||
/**
|
/**
|
||||||
* @var \OC\Files\Storage\Storage $storage
|
* @var \OC\Files\Storage\Storage $storage
|
||||||
*/
|
*/
|
||||||
private $storage = null;
|
protected $storage = null;
|
||||||
private $class;
|
protected $class;
|
||||||
private $storageId;
|
protected $storageId;
|
||||||
private $arguments = array();
|
protected $arguments = array();
|
||||||
private $mountPoint;
|
protected $mountPoint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \OC\Files\Storage\Loader $loader
|
* @var \OC\Files\Storage\Loader $loader
|
||||||
|
@ -142,7 +142,8 @@ class Mount {
|
||||||
} else {
|
} else {
|
||||||
$internalPath = substr($path, strlen($this->mountPoint));
|
$internalPath = substr($path, strlen($this->mountPoint));
|
||||||
}
|
}
|
||||||
return $internalPath;
|
// substr returns false instead of an empty string, we always want a string
|
||||||
|
return (string)$internalPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2012 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\Mount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the mount point to be (re)moved by the user
|
||||||
|
*/
|
||||||
|
interface MoveableMount {
|
||||||
|
/**
|
||||||
|
* Move the mount point to $target
|
||||||
|
*
|
||||||
|
* @param string $target the target mount point
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function moveMount($target);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the mount points
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function removeMount();
|
||||||
|
}
|
|
@ -26,6 +26,7 @@
|
||||||
namespace OC\Files;
|
namespace OC\Files;
|
||||||
|
|
||||||
use OC\Files\Cache\Updater;
|
use OC\Files\Cache\Updater;
|
||||||
|
use OC\Files\Mount\MoveableMount;
|
||||||
|
|
||||||
class View {
|
class View {
|
||||||
private $fakeRoot = '';
|
private $fakeRoot = '';
|
||||||
|
@ -357,15 +358,28 @@ class View {
|
||||||
}
|
}
|
||||||
$postFix = (substr($path, -1, 1) === '/') ? '/' : '';
|
$postFix = (substr($path, -1, 1) === '/') ? '/' : '';
|
||||||
$absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
|
$absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
|
||||||
list($storage, $internalPath) = Filesystem::resolvePath($absolutePath . $postFix);
|
$mount = Filesystem::getMountManager()->find($absolutePath . $postFix);
|
||||||
if (!($storage instanceof \OC\Files\Storage\Shared) &&
|
if ($mount->getInternalPath($absolutePath) === '') {
|
||||||
(!$internalPath || $internalPath === '' || $internalPath === '/')
|
if ($mount instanceof MoveableMount) {
|
||||||
) {
|
\OC_Hook::emit(
|
||||||
|
Filesystem::CLASSNAME, "umount",
|
||||||
|
array(Filesystem::signal_param_path => $path)
|
||||||
|
);
|
||||||
|
$result = $mount->removeMount();
|
||||||
|
if ($result) {
|
||||||
|
\OC_Hook::emit(
|
||||||
|
Filesystem::CLASSNAME, "post_umount",
|
||||||
|
array(Filesystem::signal_param_path => $path)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
} else {
|
||||||
// do not allow deleting the storage's root / the mount point
|
// do not allow deleting the storage's root / the mount point
|
||||||
// because for some storages it might delete the whole contents
|
// because for some storages it might delete the whole contents
|
||||||
// but isn't supposed to work that way
|
// but isn't supposed to work that way
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return $this->basicOperation('unlink', $path, array('delete'));
|
return $this->basicOperation('unlink', $path, array('delete'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,18 +425,19 @@ class View {
|
||||||
if ($run) {
|
if ($run) {
|
||||||
$mp1 = $this->getMountPoint($path1 . $postFix1);
|
$mp1 = $this->getMountPoint($path1 . $postFix1);
|
||||||
$mp2 = $this->getMountPoint($path2 . $postFix2);
|
$mp2 = $this->getMountPoint($path2 . $postFix2);
|
||||||
list($storage1, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1);
|
$manager = Filesystem::getMountManager();
|
||||||
|
$mount = $manager->find($absolutePath1 . $postFix1);
|
||||||
|
$storage1 = $mount->getStorage();
|
||||||
|
$internalPath1 = $mount->getInternalPath($absolutePath1 . $postFix1);
|
||||||
list(, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2);
|
list(, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2);
|
||||||
// if source and target are on the same storage we can call the rename operation from the
|
if ($internalPath1 === '' and $mount instanceof MoveableMount) {
|
||||||
// storage. If it is a "Shared" file/folder we call always the rename operation of the
|
/**
|
||||||
// shared storage to handle mount point renaming, etc correctly
|
* @var \OC\Files\Mount\Mount | \OC\Files\Mount\MoveableMount $mount
|
||||||
if ($storage1 instanceof \OC\Files\Storage\Shared) {
|
*/
|
||||||
if ($storage1) {
|
$sourceMountPoint = $mount->getMountPoint();
|
||||||
$result = $storage1->rename($absolutePath1, $absolutePath2);
|
$result = $mount->moveMount($absolutePath2);
|
||||||
|
$manager->moveMount($sourceMountPoint, $mount->getMountPoint());
|
||||||
\OC_FileProxy::runPostProxies('rename', $absolutePath1, $absolutePath2);
|
\OC_FileProxy::runPostProxies('rename', $absolutePath1, $absolutePath2);
|
||||||
} else {
|
|
||||||
$result = false;
|
|
||||||
}
|
|
||||||
} elseif ($mp1 == $mp2) {
|
} elseif ($mp1 == $mp2) {
|
||||||
if ($storage1) {
|
if ($storage1) {
|
||||||
$result = $storage1->rename($internalPath1, $internalPath2);
|
$result = $storage1->rename($internalPath1, $internalPath2);
|
||||||
|
@ -888,10 +903,6 @@ class View {
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
$path = Filesystem::normalizePath($this->fakeRoot . '/' . $directory);
|
$path = Filesystem::normalizePath($this->fakeRoot . '/' . $directory);
|
||||||
/**
|
|
||||||
* @var \OC\Files\Storage\Storage $storage
|
|
||||||
* @var string $internalPath
|
|
||||||
*/
|
|
||||||
list($storage, $internalPath) = Filesystem::resolvePath($path);
|
list($storage, $internalPath) = Filesystem::resolvePath($path);
|
||||||
if ($storage) {
|
if ($storage) {
|
||||||
$cache = $storage->getCache($internalPath);
|
$cache = $storage->getCache($internalPath);
|
||||||
|
@ -924,9 +935,10 @@ class View {
|
||||||
}
|
}
|
||||||
|
|
||||||
//add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders
|
//add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders
|
||||||
$mountPoints = Filesystem::getMountPoints($path);
|
$mounts = Filesystem::getMountManager()->findIn($path);
|
||||||
$dirLength = strlen($path);
|
$dirLength = strlen($path);
|
||||||
foreach ($mountPoints as $mountPoint) {
|
foreach ($mounts as $mount) {
|
||||||
|
$mountPoint = $mount->getMountPoint();
|
||||||
$subStorage = Filesystem::getStorage($mountPoint);
|
$subStorage = Filesystem::getStorage($mountPoint);
|
||||||
if ($subStorage) {
|
if ($subStorage) {
|
||||||
$subCache = $subStorage->getCache('');
|
$subCache = $subStorage->getCache('');
|
||||||
|
@ -953,8 +965,8 @@ class View {
|
||||||
$permissions = $rootEntry['permissions'];
|
$permissions = $rootEntry['permissions'];
|
||||||
// do not allow renaming/deleting the mount point if they are not shared files/folders
|
// do not allow renaming/deleting the mount point if they are not shared files/folders
|
||||||
// for shared files/folders we use the permissions given by the owner
|
// for shared files/folders we use the permissions given by the owner
|
||||||
if ($subStorage instanceof \OC\Files\Storage\Shared) {
|
if ($mount instanceof MoveableMount) {
|
||||||
$rootEntry['permissions'] = $permissions;
|
$rootEntry['permissions'] = $permissions | \OCP\PERMISSION_UPDATE | \OCP\PERMISSION_DELETE;
|
||||||
} else {
|
} else {
|
||||||
$rootEntry['permissions'] = $permissions & (\OCP\PERMISSION_ALL - (\OCP\PERMISSION_UPDATE | \OCP\PERMISSION_DELETE));
|
$rootEntry['permissions'] = $permissions & (\OCP\PERMISSION_ALL - (\OCP\PERMISSION_UPDATE | \OCP\PERMISSION_DELETE));
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,12 @@ class OC_Hook{
|
||||||
self::$registered[$signalclass][$signalname] = array();
|
self::$registered[$signalclass][$signalname] = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dont connect hooks twice
|
||||||
|
foreach (self::$registered[$signalclass][$signalname] as $hook) {
|
||||||
|
if ($hook['class'] === $slotclass and $hook['name'] === $slotname) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
// Connect the hook handler to the requested emitter
|
// Connect the hook handler to the requested emitter
|
||||||
self::$registered[$signalclass][$signalname][] = array(
|
self::$registered[$signalclass][$signalname][] = array(
|
||||||
"class" => $slotclass,
|
"class" => $slotclass,
|
||||||
|
|
|
@ -166,27 +166,6 @@ class Helper extends \OC\Share\Constants {
|
||||||
// Reset parents array, only go through loop again if items are found
|
// Reset parents array, only go through loop again if items are found
|
||||||
$parents = array();
|
$parents = array();
|
||||||
while ($item = $result->fetchRow()) {
|
while ($item = $result->fetchRow()) {
|
||||||
// Search for a duplicate parent share, this occurs when an
|
|
||||||
// item is shared to the same user through a group and user or the
|
|
||||||
// same item is shared by different users
|
|
||||||
$userAndGroups = array_merge(array($item['uid_owner']), \OC_Group::getUserGroups($item['uid_owner']));
|
|
||||||
$query = \OC_DB::prepare('SELECT `id`, `permissions` FROM `*PREFIX*share`'
|
|
||||||
.' WHERE `item_type` = ?'
|
|
||||||
.' AND `item_target` = ?'
|
|
||||||
.' AND `share_type` IN (?,?,?)'
|
|
||||||
.' AND `share_with` IN (\''.implode('\',\'', $userAndGroups).'\')'
|
|
||||||
.' AND `uid_owner` != ? AND `id` != ?');
|
|
||||||
$duplicateParent = $query->execute(array($item['item_type'], $item['item_target'],
|
|
||||||
self::SHARE_TYPE_USER, self::SHARE_TYPE_GROUP, self::$shareTypeGroupUserUnique,
|
|
||||||
$item['uid_owner'], $item['parent']))->fetchRow();
|
|
||||||
if ($duplicateParent) {
|
|
||||||
// Change the parent to the other item id if share permission is granted
|
|
||||||
if ($duplicateParent['permissions'] & \OCP\PERMISSION_SHARE) {
|
|
||||||
$query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `parent` = ? WHERE `id` = ?');
|
|
||||||
$query->execute(array($duplicateParent['id'], $item['id']));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$ids[] = $item['id'];
|
$ids[] = $item['id'];
|
||||||
$parents[] = $item['id'];
|
$parents[] = $item['id'];
|
||||||
}
|
}
|
||||||
|
|
|
@ -519,6 +519,11 @@ class Share extends \OC\Share\Constants {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// single file shares should never have delete permissions
|
||||||
|
if ($itemType === 'file') {
|
||||||
|
$permissions = (int)$permissions & ~\OCP\PERMISSION_DELETE;
|
||||||
|
}
|
||||||
|
|
||||||
// Verify share type and sharing conditions are met
|
// Verify share type and sharing conditions are met
|
||||||
if ($shareType === self::SHARE_TYPE_USER) {
|
if ($shareType === self::SHARE_TYPE_USER) {
|
||||||
if ($shareWith == $uidOwner) {
|
if ($shareWith == $uidOwner) {
|
||||||
|
@ -712,33 +717,54 @@ class Share extends \OC\Share\Constants {
|
||||||
* Unsharing from self is not allowed for items inside collections
|
* Unsharing from self is not allowed for items inside collections
|
||||||
*/
|
*/
|
||||||
public static function unshareFromSelf($itemType, $itemTarget) {
|
public static function unshareFromSelf($itemType, $itemTarget) {
|
||||||
$item = self::getItemSharedWith($itemType, $itemTarget);
|
|
||||||
if (!empty($item)) {
|
$uid = \OCP\User::getUser();
|
||||||
if ((int)$item['share_type'] === self::SHARE_TYPE_GROUP) {
|
|
||||||
// Insert an extra row for the group share and set permission
|
if ($itemType === 'file' || $itemType === 'folder') {
|
||||||
// to 0 to prevent it from showing up for the user
|
$statement = 'SELECT * FROM `*PREFIX*share` WHERE `item_type` = ? and `file_target` = ?';
|
||||||
|
} else {
|
||||||
|
$statement = 'SELECT * FROM `*PREFIX*share` WHERE `item_type` = ? and `item_target` = ?';
|
||||||
|
}
|
||||||
|
|
||||||
|
$query = \OCP\DB::prepare($statement);
|
||||||
|
$result = $query->execute(array($itemType, $itemTarget));
|
||||||
|
|
||||||
|
$shares = $result->fetchAll();
|
||||||
|
|
||||||
|
$itemUnshared = false;
|
||||||
|
foreach ($shares as $share) {
|
||||||
|
if ((int)$share['share_type'] === \OCP\Share::SHARE_TYPE_USER &&
|
||||||
|
$share['share_with'] === $uid) {
|
||||||
|
Helper::delete($share['id']);
|
||||||
|
$itemUnshared = true;
|
||||||
|
break;
|
||||||
|
} elseif ((int)$share['share_type'] === \OCP\Share::SHARE_TYPE_GROUP) {
|
||||||
|
if (\OC_Group::inGroup($uid, $share['share_with'])) {
|
||||||
|
$groupShare = $share;
|
||||||
|
}
|
||||||
|
} elseif ((int)$share['share_type'] === self::$shareTypeGroupUserUnique &&
|
||||||
|
$share['share_with'] === $uid) {
|
||||||
|
$uniqueGroupShare = $share;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$itemUnshared && isset($groupShare)) {
|
||||||
$query = \OC_DB::prepare('INSERT INTO `*PREFIX*share`'
|
$query = \OC_DB::prepare('INSERT INTO `*PREFIX*share`'
|
||||||
.' (`item_type`, `item_source`, `item_target`, `parent`, `share_type`,'
|
.' (`item_type`, `item_source`, `item_target`, `parent`, `share_type`,'
|
||||||
.' `share_with`, `uid_owner`, `permissions`, `stime`, `file_source`, `file_target`)'
|
.' `share_with`, `uid_owner`, `permissions`, `stime`, `file_source`, `file_target`)'
|
||||||
.' VALUES (?,?,?,?,?,?,?,?,?,?,?)');
|
.' VALUES (?,?,?,?,?,?,?,?,?,?,?)');
|
||||||
$query->execute(array($item['item_type'], $item['item_source'], $item['item_target'],
|
$query->execute(array($groupShare['item_type'], $groupShare['item_source'], $groupShare['item_target'],
|
||||||
$item['id'], self::$shareTypeGroupUserUnique,
|
$groupShare['id'], self::$shareTypeGroupUserUnique,
|
||||||
\OC_User::getUser(), $item['uid_owner'], 0, $item['stime'], $item['file_source'],
|
\OC_User::getUser(), $groupShare['uid_owner'], 0, $groupShare['stime'], $groupShare['file_source'],
|
||||||
$item['file_target']));
|
$groupShare['file_target']));
|
||||||
\OC_DB::insertid('*PREFIX*share');
|
$itemUnshared = true;
|
||||||
// Delete all reshares by this user of the group share
|
} elseif (!$itemUnshared && isset($uniqueGroupShare)) {
|
||||||
Helper::delete($item['id'], true, \OC_User::getUser());
|
|
||||||
} else if ((int)$item['share_type'] === self::$shareTypeGroupUserUnique) {
|
|
||||||
// Set permission to 0 to prevent it from showing up for the user
|
|
||||||
$query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `permissions` = ? WHERE `id` = ?');
|
$query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `permissions` = ? WHERE `id` = ?');
|
||||||
$query->execute(array(0, $item['id']));
|
$query->execute(array(0, $uniqueGroupShare['id']));
|
||||||
Helper::delete($item['id'], true);
|
$itemUnshared = true;
|
||||||
} else {
|
|
||||||
Helper::delete($item['id']);
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
return $itemUnshared;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue