Merge pull request #1786 from owncloud/shared-folder-etags
Include etags for the root of the shared folder
This commit is contained in:
commit
049a4df259
6 changed files with 219 additions and 53 deletions
|
@ -5,8 +5,14 @@ OC::$CLASSPATH['OC_Share_Backend_Folder'] = 'files_sharing/lib/share/folder.php'
|
|||
OC::$CLASSPATH['OC\Files\Storage\Shared'] = 'files_sharing/lib/sharedstorage.php';
|
||||
OC::$CLASSPATH['OC\Files\Cache\Shared_Cache'] = 'files_sharing/lib/cache.php';
|
||||
OC::$CLASSPATH['OC\Files\Cache\Shared_Permissions'] = 'files_sharing/lib/permissions.php';
|
||||
OC::$CLASSPATH['OC\Files\Cache\Shared_Updater'] = 'files_sharing/lib/updater.php';
|
||||
OC::$CLASSPATH['OC\Files\Cache\Shared_Watcher'] = 'files_sharing/lib/watcher.php';
|
||||
OCP\Util::connectHook('OC_Filesystem', 'setup', '\OC\Files\Storage\Shared', 'setup');
|
||||
OCP\Share::registerBackend('file', 'OC_Share_Backend_File');
|
||||
OCP\Share::registerBackend('folder', 'OC_Share_Backend_Folder', 'file');
|
||||
OCP\Util::addScript('files_sharing', 'share');
|
||||
\OC_Hook::connect('OC_Filesystem', 'post_write', '\OC\Files\Cache\Shared_Updater', 'writeHook');
|
||||
\OC_Hook::connect('OC_Filesystem', 'post_delete', '\OC\Files\Cache\Shared_Updater', 'deleteHook');
|
||||
\OC_Hook::connect('OC_Filesystem', 'post_rename', '\OC\Files\Cache\Shared_Updater', 'renameHook');
|
||||
\OC_Hook::connect('OCP\Share', 'post_shared', '\OC\Files\Cache\Shared_Updater', 'shareHook');
|
||||
\OC_Hook::connect('OCP\Share', 'pre_unshare', '\OC\Files\Cache\Shared_Updater', 'shareHook');
|
|
@ -28,10 +28,11 @@ namespace OC\Files\Cache;
|
|||
*/
|
||||
class Shared_Cache extends Cache {
|
||||
|
||||
private $storage;
|
||||
private $files = array();
|
||||
|
||||
public function __construct($storage) {
|
||||
|
||||
$this->storage = $storage;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -41,16 +42,19 @@ class Shared_Cache extends Cache {
|
|||
*/
|
||||
private function getSourceCache($target) {
|
||||
$source = \OC_Share_Backend_File::getSource($target);
|
||||
if (isset($source['path'])) {
|
||||
$source['path'] = '/' . $source['uid_owner'] . '/' . $source['path'];
|
||||
\OC\Files\Filesystem::initMountPoints($source['uid_owner']);
|
||||
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source['path']);
|
||||
if ($storage) {
|
||||
$this->files[$target] = $internalPath;
|
||||
$cache = $storage->getCache();
|
||||
$this->storageId = $storage->getId();
|
||||
$this->numericId = $cache->getNumericStorageId();
|
||||
return $cache;
|
||||
if (isset($source['path']) && isset($source['fileOwner'])) {
|
||||
\OC\Files\Filesystem::initMountPoints($source['fileOwner']);
|
||||
$mount = \OC\Files\Mount::findByNumericId($source['storage']);
|
||||
if ($mount) {
|
||||
$fullPath = $mount->getMountPoint().$source['path'];
|
||||
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($fullPath);
|
||||
if ($storage) {
|
||||
$this->files[$target] = $internalPath;
|
||||
$cache = $storage->getCache();
|
||||
$this->storageId = $storage->getId();
|
||||
$this->numericId = $cache->getNumericStorageId();
|
||||
return $cache;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -64,7 +68,14 @@ class Shared_Cache extends Cache {
|
|||
*/
|
||||
public function get($file) {
|
||||
if ($file == '') {
|
||||
return \OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_File::FORMAT_FILE_APP_ROOT);
|
||||
$data = \OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_File::FORMAT_FILE_APP_ROOT);
|
||||
$etag = \OCP\Config::getUserValue(\OCP\User::getUser(), 'files_sharing', 'etag');
|
||||
if (!isset($etag)) {
|
||||
$etag = $this->storage->getETag('');
|
||||
\OCP\Config::setUserValue(\OCP\User::getUser(), 'files_sharing', 'etag', $etag);
|
||||
}
|
||||
$data['etag'] = $etag;
|
||||
return $data;
|
||||
} else if (is_string($file)) {
|
||||
if ($cache = $this->getSourceCache($file)) {
|
||||
return $cache->get($this->files[$file]);
|
||||
|
@ -118,7 +129,9 @@ class Shared_Cache extends Cache {
|
|||
* @return int file id
|
||||
*/
|
||||
public function put($file, array $data) {
|
||||
if ($cache = $this->getSourceCache($file)) {
|
||||
if ($file === '' && isset($data['etag'])) {
|
||||
return \OCP\Config::setUserValue(\OCP\User::getUser(), 'files_sharing', 'etag', $data['etag']);
|
||||
} else if ($cache = $this->getSourceCache($file)) {
|
||||
return $cache->put($this->files[$file], $data);
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -93,6 +93,7 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent {
|
|||
$file['size'] = $item['size'];
|
||||
$file['mtime'] = $item['mtime'];
|
||||
$file['encrypted'] = $item['encrypted'];
|
||||
$file['etag'] = $item['etag'];
|
||||
$files[] = $file;
|
||||
}
|
||||
return $files;
|
||||
|
|
|
@ -45,7 +45,18 @@ class Shared extends \OC\Files\Storage\Common {
|
|||
*/
|
||||
private function getFile($target) {
|
||||
if (!isset($this->files[$target])) {
|
||||
$this->files[$target] = \OC_Share_Backend_File::getSource($target);
|
||||
// Check for partial files
|
||||
if (pathinfo($target, PATHINFO_EXTENSION) === 'part') {
|
||||
$source = \OC_Share_Backend_File::getSource(substr($target, 0, -5));
|
||||
if ($source) {
|
||||
$source['path'] .= '.part';
|
||||
// All partial files have delete permission
|
||||
$source['permissions'] |= \OCP\PERMISSION_DELETE;
|
||||
}
|
||||
} else {
|
||||
$source = \OC_Share_Backend_File::getSource($target);
|
||||
}
|
||||
$this->files[$target] = $source;
|
||||
}
|
||||
return $this->files[$target];
|
||||
}
|
||||
|
@ -280,34 +291,43 @@ class Shared extends \OC\Files\Storage\Common {
|
|||
}
|
||||
|
||||
public function rename($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))) {
|
||||
$newSource = $this->getSourcePath(dirname($path2)).'/'.basename($path2);
|
||||
if (dirname($path1) == dirname($path2)) {
|
||||
// Rename the file if UPDATE permission is granted
|
||||
if ($this->isUpdatable($path1)) {
|
||||
list($storage, $oldInternalPath) = \OC\Files\Filesystem::resolvePath($oldSource);
|
||||
list( , $newInternalPath) = \OC\Files\Filesystem::resolvePath($newSource);
|
||||
return $storage->rename($oldInternalPath, $newInternalPath);
|
||||
}
|
||||
} else {
|
||||
// Move the file if DELETE and CREATE permissions are granted
|
||||
if ($this->isDeletable($path1) && $this->isCreatable(dirname($path2))) {
|
||||
// Get the root shared folder
|
||||
$folder1 = substr($path1, 0, $pos1);
|
||||
$folder2 = substr($path2, 0, $pos2);
|
||||
// Copy and unlink the file if it exists in a different shared folder
|
||||
if ($folder1 != $folder2) {
|
||||
if ($this->copy($path1, $path2)) {
|
||||
return $this->unlink($path1);
|
||||
}
|
||||
} else {
|
||||
// Check for partial files
|
||||
if (pathinfo($path1, PATHINFO_EXTENSION) === 'part') {
|
||||
if ($oldSource = $this->getSourcePath($path1)) {
|
||||
list($storage, $oldInternalPath) = \OC\Files\Filesystem::resolvePath($oldSource);
|
||||
$newInternalPath = substr($oldInternalPath, 0, -5);
|
||||
return $storage->rename($oldInternalPath, $newInternalPath);
|
||||
}
|
||||
} else {
|
||||
// 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))) {
|
||||
$newSource = $this->getSourcePath(dirname($path2)).'/'.basename($path2);
|
||||
if (dirname($path1) == dirname($path2)) {
|
||||
// Rename the file if UPDATE permission is granted
|
||||
if ($this->isUpdatable($path1)) {
|
||||
list($storage, $oldInternalPath) = \OC\Files\Filesystem::resolvePath($oldSource);
|
||||
list( , $newInternalPath) = \OC\Files\Filesystem::resolvePath($newSource);
|
||||
return $storage->rename($oldInternalPath, $newInternalPath);
|
||||
}
|
||||
} else {
|
||||
// Move the file if DELETE and CREATE permissions are granted
|
||||
if ($this->isDeletable($path1) && $this->isCreatable(dirname($path2))) {
|
||||
// Get the root shared folder
|
||||
$folder1 = substr($path1, 0, $pos1);
|
||||
$folder2 = substr($path2, 0, $pos2);
|
||||
// Copy and unlink the file if it exists in a different shared folder
|
||||
if ($folder1 != $folder2) {
|
||||
if ($this->copy($path1, $path2)) {
|
||||
return $this->unlink($path1);
|
||||
}
|
||||
} else {
|
||||
list($storage, $oldInternalPath) = \OC\Files\Filesystem::resolvePath($oldSource);
|
||||
list( , $newInternalPath) = \OC\Files\Filesystem::resolvePath($newSource);
|
||||
return $storage->rename($oldInternalPath, $newInternalPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -371,7 +391,7 @@ class Shared extends \OC\Files\Storage\Common {
|
|||
|
||||
public function free_space($path) {
|
||||
if ($path == '') {
|
||||
return -1;
|
||||
return \OC\Files\FREE_SPACE_UNKNOWN;
|
||||
}
|
||||
$source = $this->getSourcePath($path);
|
||||
if ($source) {
|
||||
|
|
102
apps/files_sharing/lib/updater.php
Normal file
102
apps/files_sharing/lib/updater.php
Normal file
|
@ -0,0 +1,102 @@
|
|||
<?php
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Michael Gapczynski
|
||||
* @copyright 2013 Michael Gapczynski mtgap@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/>.
|
||||
*/
|
||||
|
||||
namespace OC\Files\Cache;
|
||||
|
||||
class Shared_Updater {
|
||||
|
||||
/**
|
||||
* Correct the parent folders' ETags for all users shared the file at $target
|
||||
*
|
||||
* @param string $target
|
||||
*/
|
||||
static public function correctFolders($target) {
|
||||
$uid = \OCP\User::getUser();
|
||||
$uidOwner = \OC\Files\Filesystem::getOwner($target);
|
||||
$info = \OC\Files\Filesystem::getFileInfo($target);
|
||||
// Correct Shared folders of other users shared with
|
||||
$users = \OCP\Share::getUsersItemShared('file', $info['fileid'], $uidOwner, true);
|
||||
if (!empty($users)) {
|
||||
while (!empty($users)) {
|
||||
$reshareUsers = array();
|
||||
foreach ($users as $user) {
|
||||
$etag = \OC\Files\Filesystem::getETag('');
|
||||
\OCP\Config::setUserValue($user, 'files_sharing', 'etag', $etag);
|
||||
// Look for reshares
|
||||
$reshareUsers = array_merge($reshareUsers, \OCP\Share::getUsersItemShared('file', $info['fileid'], $user, true));
|
||||
}
|
||||
$users = $reshareUsers;
|
||||
}
|
||||
// Correct folders of shared file owner
|
||||
$target = substr($target, 8);
|
||||
if ($uidOwner !== $uid && $source = \OC_Share_Backend_File::getSource($target)) {
|
||||
\OC\Files\Filesystem::initMountPoints($uidOwner);
|
||||
$source = '/'.$uidOwner.'/'.$source['path'];
|
||||
\OC\Files\Cache\Updater::correctFolder($source, $info['mtime']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $params
|
||||
*/
|
||||
static public function writeHook($params) {
|
||||
self::correctFolders($params['path']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $params
|
||||
*/
|
||||
static public function renameHook($params) {
|
||||
self::correctFolders($params['oldpath']);
|
||||
self::correctFolders($params['newpath']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $params
|
||||
*/
|
||||
static public function deleteHook($params) {
|
||||
self::correctFolders($params['path']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $params
|
||||
*/
|
||||
static public function shareHook($params) {
|
||||
if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') {
|
||||
$uidOwner = \OCP\User::getUser();
|
||||
$users = \OCP\Share::getUsersItemShared($params['itemType'], $params['fileSource'], $uidOwner, true);
|
||||
if (!empty($users)) {
|
||||
while (!empty($users)) {
|
||||
$reshareUsers = array();
|
||||
foreach ($users as $user) {
|
||||
$etag = \OC\Files\Filesystem::getETag('');
|
||||
\OCP\Config::setUserValue($user, 'files_sharing', 'etag', $etag);
|
||||
// Look for reshares
|
||||
$reshareUsers = array_merge($reshareUsers, \OCP\Share::getUsersItemShared('file', $params['fileSource'], $user, true));
|
||||
}
|
||||
$users = $reshareUsers;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -198,6 +198,29 @@ class Share {
|
|||
$parameters, -1, $includeCollections);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all users an item is shared with
|
||||
* @param string Item type
|
||||
* @param string Item source
|
||||
* @param string Owner
|
||||
* @param bool Include collections
|
||||
* @return Return array of users
|
||||
*/
|
||||
public static function getUsersItemShared($itemType, $itemSource, $uidOwner, $includeCollections = false) {
|
||||
$users = array();
|
||||
$items = self::getItems($itemType, $itemSource, null, null, $uidOwner, self::FORMAT_NONE, null, -1, $includeCollections);
|
||||
if ($items) {
|
||||
foreach ($items as $item) {
|
||||
if ((int)$item['share_type'] === self::SHARE_TYPE_USER) {
|
||||
$users[] = $item['share_with'];
|
||||
} else if ((int)$item['share_type'] === self::SHARE_TYPE_GROUP) {
|
||||
$users = array_merge($users, \OC_Group::usersInGroup($item['share_with']));
|
||||
}
|
||||
}
|
||||
}
|
||||
return $users;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Share an item with a user, group, or via private link
|
||||
* @param string Item type
|
||||
|
@ -383,6 +406,7 @@ class Share {
|
|||
\OC_Hook::emit('OCP\Share', 'pre_unshare', array(
|
||||
'itemType' => $itemType,
|
||||
'itemSource' => $itemSource,
|
||||
'fileSource' => $item['file_source'],
|
||||
'shareType' => $shareType,
|
||||
'shareWith' => $shareWith,
|
||||
));
|
||||
|
@ -1102,20 +1126,6 @@ class Share {
|
|||
} else {
|
||||
$fileTarget = null;
|
||||
}
|
||||
\OC_Hook::emit('OCP\Share', 'post_shared', array(
|
||||
'itemType' => $itemType,
|
||||
'itemSource' => $itemSource,
|
||||
'itemTarget' => $itemTarget,
|
||||
'parent' => $parent,
|
||||
'shareType' => self::$shareTypeGroupUserUnique,
|
||||
'shareWith' => $uid,
|
||||
'uidOwner' => $uidOwner,
|
||||
'permissions' => $permissions,
|
||||
'fileSource' => $fileSource,
|
||||
'fileTarget' => $fileTarget,
|
||||
'id' => $parent,
|
||||
'token' => $token
|
||||
));
|
||||
// Insert an extra row for the group share if the item or file target is unique for this user
|
||||
if ($itemTarget != $groupItemTarget || (isset($fileSource) && $fileTarget != $groupFileTarget)) {
|
||||
$query->execute(array($itemType, $itemSource, $itemTarget, $parent,
|
||||
|
@ -1124,6 +1134,20 @@ class Share {
|
|||
$id = \OC_DB::insertid('*PREFIX*share');
|
||||
}
|
||||
}
|
||||
\OC_Hook::emit('OCP\Share', 'post_shared', array(
|
||||
'itemType' => $itemType,
|
||||
'itemSource' => $itemSource,
|
||||
'itemTarget' => $groupItemTarget,
|
||||
'parent' => $parent,
|
||||
'shareType' => $shareType,
|
||||
'shareWith' => $uid,
|
||||
'uidOwner' => $uidOwner,
|
||||
'permissions' => $permissions,
|
||||
'fileSource' => $fileSource,
|
||||
'fileTarget' => $groupFileTarget,
|
||||
'id' => $parent,
|
||||
'token' => $token
|
||||
));
|
||||
if ($parentFolder === true) {
|
||||
// Return parent folders to preserve file target paths for potential children
|
||||
return $parentFolders;
|
||||
|
|
Loading…
Reference in a new issue