|
|
|
|
@ -27,19 +27,20 @@ namespace OCP;
|
|
|
|
|
*/
|
|
|
|
|
class Share {
|
|
|
|
|
|
|
|
|
|
const SHARETYPE_USER = 0;
|
|
|
|
|
const SHARETYPE_GROUP = 1;
|
|
|
|
|
|
|
|
|
|
const SHARE_TYPE_USER = 0;
|
|
|
|
|
const SHARE_TYPE_GROUP = 1;
|
|
|
|
|
const SHARETYPE_CONTACT = 2;
|
|
|
|
|
const SHARETYPE_PRIVATE_LINK = 3;
|
|
|
|
|
const SHARETYPE_PRIVATE_LINK = 4;
|
|
|
|
|
|
|
|
|
|
const PERMISSION_READ = 0;
|
|
|
|
|
const PERMISSION_UPDATE = 1;
|
|
|
|
|
const PERMISSION_DELETE = 2;
|
|
|
|
|
const PERMISSION_SHARE = 3;
|
|
|
|
|
|
|
|
|
|
private static $backendTypes = array();
|
|
|
|
|
|
|
|
|
|
private static $shareTypeUserAndGroups = -1;
|
|
|
|
|
private static $shareTypeGroupUserUnique = 3;
|
|
|
|
|
private static $backends = array();
|
|
|
|
|
private static $sharedFolder = '/Shared/';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Register a sharing backend class that extends OCP\Share_Backend for an item type
|
|
|
|
|
@ -113,7 +114,7 @@ class Share {
|
|
|
|
|
// Verify share type and sharing conditions are met
|
|
|
|
|
// TODO Doesn't handle types
|
|
|
|
|
switch ($shareType) {
|
|
|
|
|
case self::SHARETYPE_USER:
|
|
|
|
|
case self::SHARE_TYPE_USER:
|
|
|
|
|
\OC_Log::write('OCP\Share', 'share type '.$shareType, \OC_Log::ERROR);
|
|
|
|
|
if ($shareWith == $uidOwner) {
|
|
|
|
|
\OC_Log::write('OCP\Share', 'Sharing '.$item.' failed, because the user '.$shareWith.' is the item owner', \OC_Log::ERROR);
|
|
|
|
|
@ -133,10 +134,8 @@ class Share {
|
|
|
|
|
\OC_Log::write('OCP\Share', 'Sharing '.$item.' failed, because this item is already shared with the user '.$shareWith, \OC_Log::ERROR);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
$uidSharedWith = $shareWith;
|
|
|
|
|
$gidSharedWith = null;
|
|
|
|
|
break;
|
|
|
|
|
case self::SHARETYPE_GROUP:
|
|
|
|
|
case self::SHARE_TYPE_GROUP:
|
|
|
|
|
if (!\OC_Group::groupExists($shareWith)) {
|
|
|
|
|
\OC_Log::write('OCP\Share', 'Sharing '.$item.' failed, because the group '.$shareWith.' does not exist', \OC_Log::ERROR);
|
|
|
|
|
return false;
|
|
|
|
|
@ -148,8 +147,11 @@ class Share {
|
|
|
|
|
\OC_Log::write('OCP\Share', 'Sharing '.$item.' failed, because this item is already shared with the group '.$shareWith, \OC_Log::ERROR);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
$uidSharedWith = array_diff(\OC_Group::usersInGroup($shareWith), array($uidOwner));
|
|
|
|
|
$gidSharedWith = $shareWith;
|
|
|
|
|
// Convert share with into an array with the keys group and users
|
|
|
|
|
$group = $shareWith;
|
|
|
|
|
$shareWith = array();
|
|
|
|
|
$shareWith['group'] = $group;
|
|
|
|
|
$shareWith['users'] = array_diff(\OC_Group::usersInGroup($shareWith), array($uidOwner));
|
|
|
|
|
break;
|
|
|
|
|
case self::SHARETYPE_PRIVATE_LINK:
|
|
|
|
|
// TODO don't loop through folder conversion
|
|
|
|
|
@ -162,7 +164,7 @@ class Share {
|
|
|
|
|
}
|
|
|
|
|
// If the item is a folder, scan through the folder looking for equivalent item types
|
|
|
|
|
if ($itemType == 'folder') {
|
|
|
|
|
$parentFolder = self::put('folder', $item, $uidSharedWith, $gidSharedWith, $uidOwner, $permissions, true);
|
|
|
|
|
$parentFolder = self::put('folder', $item, $shareType, $shareWith, $uidOwner, $permissions, true);
|
|
|
|
|
if ($parentFolder && $files = \OC_Files::getDirectoryContent($item)) {
|
|
|
|
|
for ($i = 0; $i < count($files); $i++) {
|
|
|
|
|
$name = substr($files[$i]['name'], strpos($files[$i]['name'], $item) - strlen($item));
|
|
|
|
|
@ -171,7 +173,7 @@ class Share {
|
|
|
|
|
array_push($files, $children);
|
|
|
|
|
} else {
|
|
|
|
|
// Pass on to put() to check if this item should be converted, the item won't be inserted into the database unless it can be converted
|
|
|
|
|
self::put('file', $name, $uidSharedWith, $gidSharedWith, $uidOwner, $permissions, $parentFolder);
|
|
|
|
|
self::put('file', $name, $shareType, $shareWith, $uidOwner, $permissions, $parentFolder);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return $return;
|
|
|
|
|
@ -179,7 +181,7 @@ class Share {
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
|
// Put the item into the database
|
|
|
|
|
return self::put($itemType, $item, $uidSharedWith, $gidSharedWith, $uidOwner, $permissions);
|
|
|
|
|
return self::put($itemType, $item, $shareType, $shareWith, $uidOwner, $permissions);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -194,11 +196,11 @@ class Share {
|
|
|
|
|
public static function unshare($itemType, $item, $shareType, $shareWith) {
|
|
|
|
|
$uidOwner = \OC_User::getUser();
|
|
|
|
|
switch ($shareType) {
|
|
|
|
|
case self::SHARETYPE_USER:
|
|
|
|
|
case self::SHARE_TYPE_USER:
|
|
|
|
|
case self::SHARETYPE_PRIVATE_LINK:
|
|
|
|
|
$item = self::getItems($itemType, $item, $shareWith, null, $uidOwner, false, 1);
|
|
|
|
|
break;
|
|
|
|
|
case self::SHARETYPE_GROUP:
|
|
|
|
|
case self::SHARE_TYPE_GROUP:
|
|
|
|
|
$item = self::getItems($itemType, $item, null, $shareWith, $uidOwner, false, 1);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
@ -225,7 +227,7 @@ class Share {
|
|
|
|
|
if ($item['parent']) {
|
|
|
|
|
$query = \OC_DB::prepare('SELECT item_type FROM *PREFIX*sharing WHERE id = ? LIMIT 1');
|
|
|
|
|
$result = $query->execute(array($item['parent']))->fetchRow();
|
|
|
|
|
if (isset($result['item_type']) && $result['item_type'] = 'folder') {
|
|
|
|
|
if (isset($result['item_type']) && $result['item_type'] == 'folder') {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -293,11 +295,11 @@ class Share {
|
|
|
|
|
public static function setPermissions($itemType, $item, $shareType, $shareWith, $permissions) {
|
|
|
|
|
$uidOwner = \OC_User::getUser();
|
|
|
|
|
switch ($shareType) {
|
|
|
|
|
case self::SHARETYPE_USER:
|
|
|
|
|
case self::SHARE_TYPE_USER:
|
|
|
|
|
case self::SHARETYPE_PRIVATE_LINK:
|
|
|
|
|
$item = self::getItems($itemType, $item, $shareWith, null, $uidOwner, false, 1);
|
|
|
|
|
break;
|
|
|
|
|
case self::SHARETYPE_GROUP:
|
|
|
|
|
case self::SHARE_TYPE_GROUP:
|
|
|
|
|
$item = self::getItems($itemType, $item, null, $shareWith, $uidOwner, false, 1);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
@ -383,7 +385,7 @@ class Share {
|
|
|
|
|
* See public functions getItem(s)... for parameter usage
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
private static function getItems($itemType, $item = null, $uidSharedWith = null, $gidSharedWith = null, $uidOwner = null, $translate = true, $limit = -1) {
|
|
|
|
|
private static function getItems($itemType, $item = null, $shareType = null, $shareWith = null, $uidOwner = null, $format = true, $checkOnly = false, $limit = -1) {
|
|
|
|
|
if ($backend = self::getBackend($itemType)) {
|
|
|
|
|
// Check if there are any parent types that include this type of items, e.g. a music album contains songs
|
|
|
|
|
if (isset($itemType)) {
|
|
|
|
|
@ -401,20 +403,17 @@ class Share {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (isset($uidSharedWith)) {
|
|
|
|
|
if ($gidSharedWith === true) {
|
|
|
|
|
$where .= " AND (uid_shared_with = '".$uidSharedWith."'";
|
|
|
|
|
// Include group shares
|
|
|
|
|
$groups = \OC_Group::getUserGroups($uidSharedWith);
|
|
|
|
|
if (!empty($groups)) {
|
|
|
|
|
$groups = "'".implode("','", $groups)."'";
|
|
|
|
|
$where .= " OR gid_shared_with IN (".$groups.") AND (uid_shared_with IS NULL OR uid_shared_with = '".$uidSharedWith."'))";
|
|
|
|
|
}
|
|
|
|
|
if (isset($shareType) && isset($shareWith)) {
|
|
|
|
|
// Include all user and group items
|
|
|
|
|
if ($shareType == self::$shareTypeUserAndGroups) {
|
|
|
|
|
$where .= " AND share_type IN ('".self::SHARE_TYPE_USER."','".self::SHARE_TYPE_GROUP."','".self::$shareTypeGroupUserUnique."')";
|
|
|
|
|
$groups = \OC_Group::getUserGroups($shareWith);
|
|
|
|
|
$userAndGroups = array_merge(array($shareWith), $groups);
|
|
|
|
|
$where .= " AND share_with IN ('".implode("','", $userAndGroups)."')";
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
$where .= " AND uid_shared_with = '".$uidSharedWith."'";
|
|
|
|
|
$where .= " AND share_type = '".$shareType."' AND share_with = '".$shareWith."'";
|
|
|
|
|
}
|
|
|
|
|
} else if (isset($gidSharedWith)) {
|
|
|
|
|
$where .= " AND gid_shared_with = '".$gidSharedWith."' AND uid_shared_with IS NULL";
|
|
|
|
|
}
|
|
|
|
|
if (isset($uidOwner)) {
|
|
|
|
|
$where .= " AND uid_owner = '".$uidOwner."'";
|
|
|
|
|
@ -431,39 +430,45 @@ class Share {
|
|
|
|
|
}
|
|
|
|
|
$where .= " AND item_source = '".$itemSource."'";
|
|
|
|
|
} else {
|
|
|
|
|
$where .= " AND item_target = '".$item."'";
|
|
|
|
|
if ($itemType == 'file' && substr($item, -1) == '/') {
|
|
|
|
|
// Special case to select only the shared files inside the folder
|
|
|
|
|
$where .= " AND file_target LIKE '".$item."%/'";
|
|
|
|
|
} else {
|
|
|
|
|
$where .= " AND item_target = '".$item."'";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ($limit != -1) {
|
|
|
|
|
$where .= ' LIMIT '.$limit;
|
|
|
|
|
}
|
|
|
|
|
echo $where.'<br />';
|
|
|
|
|
$query = \OC_DB::prepare('SELECT * FROM *PREFIX*sharing '.$where);
|
|
|
|
|
$result = $query->execute();
|
|
|
|
|
$items = array();
|
|
|
|
|
while ($item = $result->fetchRow()) {
|
|
|
|
|
// Check if this is part of a group share and the user has a different target from the group share
|
|
|
|
|
if ($gidSharedWith === true && isset($item['gid_shared_with']) && isset($item['uid_shared_with'])) {
|
|
|
|
|
// Remove the default group share item from the array
|
|
|
|
|
if (!$checkOnly) {
|
|
|
|
|
$items = array();
|
|
|
|
|
while ($item = $result->fetchRow()) {
|
|
|
|
|
// Filter out duplicate group shares for users with unique targets
|
|
|
|
|
if ($item['share_type'] == self::$shareTypeGroupUserUnique) {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
if ($translate) {
|
|
|
|
|
if ($item['item_type'] != $itemType && $parentBackend = self::getBackend($item['item_type'])) {
|
|
|
|
|
if ($itemType == 'files') {
|
|
|
|
|
// TODO Don't get children, rather get file sources
|
|
|
|
|
}
|
|
|
|
|
// TODO add to array parent name
|
|
|
|
|
$children = $parentBackend->getChildren($item);
|
|
|
|
|
foreach ($children as $child) {
|
|
|
|
|
$items[] = $child;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
$sources[] = $item['item_source'];
|
|
|
|
|
if ($format) {
|
|
|
|
|
$shareInfo[$item['item_source']] = array('item_target' => $item['item_target'], 'permissions' => $item['permissions'], 'stime' => $item['stime']);
|
|
|
|
|
} else {
|
|
|
|
|
$items[] = $backend->translateItem($item);
|
|
|
|
|
$shareInfo[$item['item_source']][$item['id']] = array('item_target' => $item['item_target'], 'permissions' => $item['permissions'], 'stime' => $item['stime']);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!empty($items)) {
|
|
|
|
|
return $items;
|
|
|
|
|
if ($format) {
|
|
|
|
|
return $backend->formatItems($sources, $shareInfo);
|
|
|
|
|
} else {
|
|
|
|
|
// TODO wrap items back into share type, share with, permissions
|
|
|
|
|
$items = $backend->getItems($sources);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
if (!empty($items)) {
|
|
|
|
|
return $items;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return $result->fetchAll();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
@ -480,7 +485,7 @@ class Share {
|
|
|
|
|
* @param bool|array Parent folder target (optional)
|
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
private static function put($itemType, $item, $uidSharedWith, $gidSharedWith, $uidOwner, $permissions, $parentFolder = false) {
|
|
|
|
|
private static function put($itemType, $item, $shareType, $shareWith, $uidOwner, $permissions, $parentFolder = false) {
|
|
|
|
|
// Check file extension for an equivalent item type to convert to
|
|
|
|
|
if ($itemType == 'file') {
|
|
|
|
|
$extension = strtolower(substr($item, strrpos($item, '.') + 1));
|
|
|
|
|
@ -520,7 +525,7 @@ class Share {
|
|
|
|
|
}
|
|
|
|
|
$query = \OC_DB::prepare('INSERT INTO *PREFIX*sharing (item_type, item_source, item_target, parent, uid_shared_with, gid_shared_with, uid_owner, permissions, stime, file_source, file_target) VALUES (?,?,?,?,?,?,?,?,?,?,?)');
|
|
|
|
|
// Share with a group
|
|
|
|
|
if (isset($gidSharedWith)) {
|
|
|
|
|
if ($shareType == self::SHARE_TYPE_GROUP) {
|
|
|
|
|
if (isset($fileSource)) {
|
|
|
|
|
if ($parentFolder) {
|
|
|
|
|
if ($parentFolder === true) {
|
|
|
|
|
@ -542,11 +547,11 @@ class Share {
|
|
|
|
|
$groupFileTarget = null;
|
|
|
|
|
}
|
|
|
|
|
$groupItemTarget = $backend->generateTarget($item, false);
|
|
|
|
|
$query->execute(array($itemType, $itemSource, $groupItemTarget, $parent, null, $gidSharedWith, $uidOwner, $permissions, time(), $fileSource, $groupFileTarget));
|
|
|
|
|
$query->execute(array($itemType, $itemSource, $groupItemTarget, $parent, $shareType, $shareWith['group'], $uidOwner, $permissions, time(), $fileSource, $groupFileTarget));
|
|
|
|
|
// Save this id, any extra rows for this group share will need to reference it
|
|
|
|
|
$parent = \OC_DB::insertid('*PREFIX*sharing');
|
|
|
|
|
// Loop through all users of this group in case we need to add an extra row
|
|
|
|
|
foreach ($uidSharedWith as $uid) {
|
|
|
|
|
foreach ($shareWith['users'] as $uid) {
|
|
|
|
|
$itemTarget = $backend->generateTarget($item, $uid);
|
|
|
|
|
if (isset($fileSource)) {
|
|
|
|
|
if ($parentFolder) {
|
|
|
|
|
@ -567,7 +572,7 @@ class Share {
|
|
|
|
|
}
|
|
|
|
|
// 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, $uid, $gidSharedWith, $uidOwner, $permissions, time(), $fileSource, $fileTarget));
|
|
|
|
|
$query->execute(array($itemType, $itemSource, $itemTarget, $parent, self::$shareTypeGroupUserUnique, $uid, $uidOwner, $permissions, time(), $fileSource, $fileTarget));
|
|
|
|
|
$id = \OC_DB::insertid('*PREFIX*sharing');
|
|
|
|
|
}
|
|
|
|
|
if ($parentFolder === true) {
|
|
|
|
|
@ -579,7 +584,6 @@ class Share {
|
|
|
|
|
return $parentFolders;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Share with a user
|
|
|
|
|
$itemTarget = $backend->generateTarget($item, $uidSharedWith);
|
|
|
|
|
if (isset($fileSource)) {
|
|
|
|
|
if ($parentFolder) {
|
|
|
|
|
@ -596,7 +600,7 @@ class Share {
|
|
|
|
|
} else {
|
|
|
|
|
$fileTarget = null;
|
|
|
|
|
}
|
|
|
|
|
$query->execute(array($itemType, $itemSource, $itemTarget, $parent, $uidSharedWith, null, $uidOwner, $permissions, time(), $fileSource, $fileTarget));
|
|
|
|
|
$query->execute(array($itemType, $itemSource, $itemTarget, $parent, $shareType, $shareWith, $uidOwner, $permissions, time(), $fileSource, $fileTarget));
|
|
|
|
|
$id = \OC_DB::insertid('*PREFIX*sharing');
|
|
|
|
|
if ($parentFolder === true) {
|
|
|
|
|
$parentFolders['id'] = $id;
|
|
|
|
|
@ -668,6 +672,8 @@ abstract class Share_Backend {
|
|
|
|
|
public static $dependsOn;
|
|
|
|
|
public static $supportedFileExtensions = array();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Get the source of the item to be stored in the database
|
|
|
|
|
* @param string Item
|
|
|
|
|
@ -682,6 +688,8 @@ abstract class Share_Backend {
|
|
|
|
|
*/
|
|
|
|
|
public abstract function getSource($item, $uid);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Get a unique name of the item for the specified user
|
|
|
|
|
* @param string Item
|
|
|
|
|
@ -694,7 +702,24 @@ abstract class Share_Backend {
|
|
|
|
|
*/
|
|
|
|
|
public abstract function generateTarget($item, $uid, $exclude = null);
|
|
|
|
|
|
|
|
|
|
public abstract function transteItem($source);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief
|
|
|
|
|
* @param array
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
public abstract function getItems($sources);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief
|
|
|
|
|
* @param array
|
|
|
|
|
* @param array
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
public abstract function formatItems($sources, $shareInfo);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|