From 28866de44bbf5c5bc2b1e0689b5139047ba5273b Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Wed, 8 May 2013 16:22:08 +0200 Subject: [PATCH] Added pre_share hook Switched it for post_share hook in encryption hooks Stop a file from being shared if the encryption procedure fails for any users --- apps/files_encryption/appinfo/app.php | 2 +- apps/files_encryption/hooks/hooks.php | 17 ++- apps/files_encryption/lib/util.php | 9 +- lib/public/share.php | 169 ++++++++++++++++++-------- 4 files changed, 130 insertions(+), 67 deletions(-) diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php index a7253c4333..7f01aaeebe 100644 --- a/apps/files_encryption/appinfo/app.php +++ b/apps/files_encryption/appinfo/app.php @@ -16,7 +16,7 @@ OCP\Util::connectHook( 'OC_User', 'post_login', 'OCA\Encryption\Hooks', 'login' OCP\Util::connectHook( 'OC_User', 'pre_setPassword', 'OCA\Encryption\Hooks', 'setPassphrase' ); // Sharing-related hooks -OCP\Util::connectHook( 'OCP\Share', 'post_shared', 'OCA\Encryption\Hooks', 'postShared' ); +OCP\Util::connectHook( 'OCP\Share', 'pre_shared', 'OCA\Encryption\Hooks', 'preShared' ); OCP\Util::connectHook( 'OCP\Share', 'post_unshare', 'OCA\Encryption\Hooks', 'postUnshare' ); OCP\Util::connectHook( 'OCP\Share', 'post_unshareAll', 'OCA\Encryption\Hooks', 'postUnshareAll' ); diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index ddec839acd..1f642f4841 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -183,7 +183,7 @@ class Hooks { /** * @brief */ - public static function postShared( $params ) { + public static function preShared( $params ) { // NOTE: $params has keys: // [itemType] => file @@ -201,6 +201,7 @@ class Hooks { // [fileTarget] => /test8 // [id] => 10 // [token] => + // [run] => whether emitting script should continue to run // TODO: Should other kinds of item be encrypted too? if ( $params['itemType'] === 'file' || $params['itemType'] === 'folder' ) { @@ -249,7 +250,7 @@ class Hooks { // rebuild path foreach ( $targetPathSplit as $pathPart ) { - if( $pathPart !== $sharedPart ) { + if ( $pathPart !== $sharedPart ) { $path = '/' . $pathPart . $path; @@ -295,15 +296,13 @@ class Hooks { $failed[] = $path; } } - - // If no attempts to set keyfiles failed - if ( empty( $failed ) ) { - return true; + // If some attempts to set keyfiles failed + if ( ! empty( $failed ) ) { - } else { - - return false; + // Set flag var 'run' to notify emitting + // script that hook execution failed + $params['run']->run = false; } } diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 5ab5ea6425..871d3bcfc3 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -146,7 +146,7 @@ class Util { return false; } else { - + return true; } @@ -855,15 +855,14 @@ class Util { * @param string $filePath path of the file to be shared */ public function setSharedFileKeyfiles( Session $session, array $users, $filePath ) { - + // Make sure users are capable of sharing $filteredUids = $this->filterShareReadyUsers( $users ); if ( ! empty( $filteredUids['unready'] ) ) { - // Notify user of unready userDir - // TODO: Move this out of here; it belongs somewhere else - \OCP\JSON::error(); + // TODO: Notify user of unready userDir + \OC_Log::write( 'Encryption library', 'Sharing to these user(s) failed as they are unready for encryption:"'.print_r( $filteredUids['unready'], 1 ), \OC_Log::WARN ); } diff --git a/lib/public/share.php b/lib/public/share.php index fee906d187..cb151b9f4b 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -1223,42 +1223,12 @@ class Share { } else { $groupFileTarget = null; } - $query->execute(array($itemType, $itemSource, $groupItemTarget, $parent, $shareType, - $shareWith['group'], $uidOwner, $permissions, time(), $fileSource, $groupFileTarget, $token)); - // Save this id, any extra rows for this group share will need to reference it - $parent = \OC_DB::insertid('*PREFIX*share'); - // Loop through all users of this group in case we need to add an extra row - foreach ($shareWith['users'] as $uid) { - $itemTarget = self::generateTarget($itemType, $itemSource, self::SHARE_TYPE_USER, $uid, - $uidOwner, $suggestedItemTarget, $parent); - if (isset($fileSource)) { - if ($parentFolder) { - if ($parentFolder === true) { - $fileTarget = self::generateTarget('file', $filePath, self::SHARE_TYPE_USER, $uid, - $uidOwner, $suggestedFileTarget, $parent); - if ($fileTarget != $groupFileTarget) { - $parentFolders[$uid]['folder'] = $fileTarget; - } - } else if (isset($parentFolder[$uid])) { - $fileTarget = $parentFolder[$uid]['folder'].$itemSource; - $parent = $parentFolder[$uid]['id']; - } - } else { - $fileTarget = self::generateTarget('file', $filePath, self::SHARE_TYPE_USER, - $uid, $uidOwner, $suggestedFileTarget, $parent); - } - } else { - $fileTarget = null; - } - // 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, - self::$shareTypeGroupUserUnique, $uid, $uidOwner, $permissions, time(), - $fileSource, $fileTarget, $token)); - $id = \OC_DB::insertid('*PREFIX*share'); - } - } - \OC_Hook::emit('OCP\Share', 'post_shared', array( + // Trigger hooks before the share is added to DB + // Set flag indicating if execution should continue. + // Use an object as workaround for pass by reference issues + $run = new \stdClass(); + $run->run = true; + $params = array( 'itemType' => $itemType, 'itemSource' => $itemSource, 'itemTarget' => $groupItemTarget, @@ -1270,11 +1240,73 @@ class Share { 'fileSource' => $fileSource, 'fileTarget' => $groupFileTarget, 'id' => $parent, - 'token' => $token - )); - if ($parentFolder === true) { - // Return parent folders to preserve file target paths for potential children - return $parentFolders; + 'token' => $token, + 'run' => $run + ); + $run = \OC_Hook::emit( + 'OCP\Share' + , 'pre_shared' + , $params + ); + // If hook execution didn't encounter errors + if ( ! $run->run ) { + $message = 'Sharing '.$itemSource.' failed, because pre share hooks failed'; + \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR); + return false; + } else { + $query->execute(array($itemType, $itemSource, $groupItemTarget, $parent, $shareType, + $shareWith['group'], $uidOwner, $permissions, time(), $fileSource, $groupFileTarget, $token)); + // Save this id, any extra rows for this group share will need to reference it + $parent = \OC_DB::insertid('*PREFIX*share'); + // Loop through all users of this group in case we need to add an extra row + foreach ($shareWith['users'] as $uid) { + $itemTarget = self::generateTarget($itemType, $itemSource, self::SHARE_TYPE_USER, $uid, + $uidOwner, $suggestedItemTarget, $parent); + if (isset($fileSource)) { + if ($parentFolder) { + if ($parentFolder === true) { + $fileTarget = self::generateTarget('file', $filePath, self::SHARE_TYPE_USER, $uid, + $uidOwner, $suggestedFileTarget, $parent); + if ($fileTarget != $groupFileTarget) { + $parentFolders[$uid]['folder'] = $fileTarget; + } + } else if (isset($parentFolder[$uid])) { + $fileTarget = $parentFolder[$uid]['folder'].$itemSource; + $parent = $parentFolder[$uid]['id']; + } + } else { + $fileTarget = self::generateTarget('file', $filePath, self::SHARE_TYPE_USER, + $uid, $uidOwner, $suggestedFileTarget, $parent); + } + } else { + $fileTarget = null; + } + // 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, + self::$shareTypeGroupUserUnique, $uid, $uidOwner, $permissions, time(), + $fileSource, $fileTarget, $token)); + $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' => $shareWith['group'], + '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; + } } } else { $itemTarget = self::generateTarget($itemType, $itemSource, $shareType, $shareWith, $uidOwner, @@ -1296,10 +1328,14 @@ class Share { } else { $fileTarget = null; } - $query->execute(array($itemType, $itemSource, $itemTarget, $parent, $shareType, $shareWith, $uidOwner, - $permissions, time(), $fileSource, $fileTarget, $token)); - $id = \OC_DB::insertid('*PREFIX*share'); - \OC_Hook::emit('OCP\Share', 'post_shared', array( + // Trigger hooks before the share is added to DB + // Set flag indicating if execution should continue. + // Use an object as workaround for pass by reference issues + $run = new \stdClass(); + $run->run = true; + // NOTE: [id] isn't included as it's not yet available + // (hasn't been inserted) + $params = array( 'itemType' => $itemType, 'itemSource' => $itemSource, 'itemTarget' => $itemTarget, @@ -1310,13 +1346,42 @@ class Share { 'permissions' => $permissions, 'fileSource' => $fileSource, 'fileTarget' => $fileTarget, - 'id' => $id, - 'token' => $token - )); - if ($parentFolder === true) { - $parentFolders['id'] = $id; - // Return parent folder to preserve file target paths for potential children - return $parentFolders; + 'token' => $token, + 'run' => $run + ); + \OC_Hook::emit( + 'OCP\Share' + , 'pre_shared' + , $params + ); + // If hook execution didn't encounter errors + if ( ! $run->run ) { + $message = 'Sharing '.$itemSource.' failed, because pre share hooks failed'; + \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR); + return false; + } else { + $query->execute(array($itemType, $itemSource, $itemTarget, $parent, $shareType, $shareWith, $uidOwner, + $permissions, time(), $fileSource, $fileTarget, $token)); + $id = \OC_DB::insertid('*PREFIX*share'); + \OC_Hook::emit('OCP\Share', 'post_shared', array( + 'itemType' => $itemType, + 'itemSource' => $itemSource, + 'itemTarget' => $itemTarget, + 'parent' => $parent, + 'shareType' => $shareType, + 'shareWith' => $shareWith, + 'uidOwner' => $uidOwner, + 'permissions' => $permissions, + 'fileSource' => $fileSource, + 'fileTarget' => $fileTarget, + 'id' => $id, + 'token' => $token + )); + if ($parentFolder === true) { + $parentFolders['id'] = $id; + // Return parent folder to preserve file target paths for potential children + return $parentFolders; + } } } return true;