user should be able to rename/delete shared files if the owner allowed it

This commit is contained in:
Bjoern Schiessle 2014-04-04 18:32:49 +02:00
parent 72bbb9ca20
commit a02fb3722b
3 changed files with 129 additions and 11 deletions

View File

@ -89,6 +89,12 @@ class Shared_Cache extends Cache {
return $cache->get($this->files[$file]);
}
} else {
// if we are at the root of the mount point we want to return the
// cache information for the source item
if (!is_int($file) || $file === 0) {
$file = $this->storage->getSourceId();
$mountPoint = $this->storage->getMountPoint();
}
$query = \OC_DB::prepare(
'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`,'
. ' `size`, `mtime`, `encrypted`, `unencrypted_size`'
@ -110,6 +116,9 @@ class Shared_Cache extends Cache {
} else {
$data['size'] = (int)$data['size'];
}
if (isset($mountPoint)) {
$data['path'] = 'files/' . $mountPoint;
}
return $data;
}
return false;

View File

@ -30,17 +30,33 @@ class Shared extends \OC\Files\Storage\Common {
private $mountPoint; // mount point relative to data/user/files
private $type; // can be "file" or "folder"
private $shareId; // share Id to identify the share in the database
private $fileSource; // file cache ID of the shared item
private $files = array();
public function __construct($arguments) {
$this->mountPoint = $arguments['shareTarget'];
$this->type = $arguments['shareType'];
$this->shareId = $arguments['shareId'];
$this->fileSource = $arguments['fileSource'];
}
/**
* @breif get id of the mount point
* @return string
*/
public function getId() {
return 'shared::' . $this->mountPoint;
}
/**
* @breif get file cache of the shared item source
* @return string
*/
public function getSourceId() {
return $this->fileSource;
}
/**
* @brief Get the source file path, permissions, and owner for a shared file
* @param string Shared target file path
@ -289,11 +305,89 @@ class Shared extends \OC\Files\Storage\Common {
return false;
}
/**
* @brief 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;
}
/**
* @brief rename a shared foder/file
* @param string $sourcePath
* @param string $targetPath
* @return bool
*/
private function renameMountPoint($sourcePath, $targetPath) {
// it shoulbn't be possible to move a Shared storage into another one
list($targetStorage, ) = \OC\Files\Filesystem::resolvePath($targetPath);
if ($targetStorage instanceof \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);
// rename mount point
$query = \OC_DB::prepare(
'Update `*PREFIX*share`
SET `file_target` = ?
WHERE `id` = ?'
);
$result = $query->execute(array($relTargetPath, $this->shareId));
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 . '/');
} else {
\OCP\Util::writeLog('file sharing',
'Could not rename mount point for shared folder "' . $sourcePath . '" to "' . $targetPath . '"',
\OCP\Util::ERROR);
}
return $result;
}
public function rename($path1, $path2) {
$sourceMountPoint = \OC\Files\Filesystem::getMountPoint($path1);
// if we renamed the mount point we need to adjust the file_target in the
// database
if (strlen($sourceMountPoint) >= strlen($path1)) {
return $this->renameMountPoint($path1, $path2);
}
// Renaming/moving is only allowed within shared folders
$pos1 = strpos($path1, '/', 1);
$pos2 = strpos($path2, '/', 1);
if ($pos1 !== false && $pos2 !== false && ($oldSource = $this->getSourcePath($path1))) {
$oldSource = $this->getSourcePath($path1);
if ($oldSource) {
$newSource = $this->getSourcePath(dirname($path2)) . '/' . basename($path2);
// Within the same folder, we only need UPDATE permissions
if (dirname($path1) == dirname($path2) and $this->isUpdatable($path1)) {
@ -405,6 +499,8 @@ class Shared extends \OC\Files\Storage\Common {
array(
'shareTarget' => $share['file_target'],
'shareType' => $share['item_type'],
'shareId' => $share['id'],
'fileSource' => $share['file_source'],
),
$options['user_dir'] . '/' . $share['file_target']);
}

View File

@ -404,11 +404,21 @@ class View {
if ($run) {
$mp1 = $this->getMountPoint($path1 . $postFix1);
$mp2 = $this->getMountPoint($path2 . $postFix2);
list($storage1, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1);
list(, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2);
// if source and target are on the same storage we can call the rename operation from the
// 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
if ($mp1 == $mp2) {
list($storage, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1);
list(, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2);
if ($storage) {
$result = $storage->rename($internalPath1, $internalPath2);
if ($storage1) {
$result = $storage1->rename($internalPath1, $internalPath2);
\OC_FileProxy::runPostProxies('rename', $absolutePath1, $absolutePath2);
} else {
$result = false;
}
} elseif ($storage1 instanceof \OC\Files\Storage\Shared) {
if ($storage1) {
$result = $storage1->rename($absolutePath1, $absolutePath2);
\OC_FileProxy::runPostProxies('rename', $absolutePath1, $absolutePath2);
} else {
$result = false;
@ -417,7 +427,6 @@ class View {
if ($this->is_dir($path1)) {
$result = $this->copy($path1, $path2);
if ($result === true) {
list($storage1, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1);
$result = $storage1->unlink($internalPath1);
}
} else {
@ -431,7 +440,6 @@ class View {
fclose($target);
if ($result !== false) {
list($storage1, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1);
$storage1->unlink($internalPath1);
}
}
@ -972,8 +980,13 @@ class View {
$permissions = $subStorage->getPermissions($rootEntry['path']);
$subPermissionsCache->set($rootEntry['fileid'], $user, $permissions);
}
// do not allow renaming/deleting the mount point
$rootEntry['permissions'] = $permissions & (\OCP\PERMISSION_ALL - (\OCP\PERMISSION_UPDATE | \OCP\PERMISSION_DELETE));
// 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
if ($subStorage instanceof \OC\Files\Storage\Shared) {
$rootEntry['permissions'] = $permissions;
} else {
$rootEntry['permissions'] = $permissions & (\OCP\PERMISSION_ALL - (\OCP\PERMISSION_UPDATE | \OCP\PERMISSION_DELETE));
}
//remove any existing entry with the same name
foreach ($files as $i => $file) {