From d40d6aa3581fdacfc10532cfcfc2dc20835817d1 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Thu, 16 May 2013 22:39:09 +0200 Subject: [PATCH 1/6] fix typo in addRecoveryKeys --- apps/files_encryption/lib/util.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index fab807b014..038ec78bbd 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -1325,7 +1325,7 @@ class Util { foreach ($dirContent as $item) { $filePath = substr($item['path'], 25); if ($item['type'] == 'dir') { - $this->addRecoveryKey($filePath.'/'); + $this->addRecoveryKeys($filePath.'/'); } else { $session = new Session(new \OC_FilesystemView('/')); $sharingEnabled = \OCP\Share::isEnabled(); From 3793e4d2d6729f01a83c56d8f123226134f8c626 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Thu, 16 May 2013 22:57:55 +0200 Subject: [PATCH 2/6] fix for recover files in subfolder --- apps/files_encryption/lib/util.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 038ec78bbd..7acb3ce2dc 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -1406,7 +1406,7 @@ class Util { foreach ($dirContent as $item) { $filePath = substr($item['path'], 25); if ($item['type'] == 'dir') { - $this->addRecoveryKey($filePath . '/', $privateKey); + $this->recoverAllFiles($filePath . '/', $privateKey); } else { $file = substr($filePath, 0, -4); $this->recoverFile($file, $privateKey); From 42b4963dd010830d1a99666052ee2bfc7295249a Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Fri, 17 May 2013 00:58:41 +0200 Subject: [PATCH 3/6] moved enable and disable recovery to Helper class for unit tests --- apps/files_encryption/ajax/adminrecovery.php | 64 +------------- apps/files_encryption/lib/helper.php | 92 ++++++++++++++++++++ 2 files changed, 94 insertions(+), 62 deletions(-) diff --git a/apps/files_encryption/ajax/adminrecovery.php b/apps/files_encryption/ajax/adminrecovery.php index 0ab449709c..dc13bc57c1 100644 --- a/apps/files_encryption/ajax/adminrecovery.php +++ b/apps/files_encryption/ajax/adminrecovery.php @@ -21,74 +21,14 @@ $recoveryKeyId = OC_Appconfig::getValue('files_encryption', 'recoveryKeyId'); if (isset($_POST['adminEnableRecovery']) && $_POST['adminEnableRecovery'] == 1){ - $view = new \OC\Files\View('/'); - - if ($recoveryKeyId === null) { - $recoveryKeyId = 'recovery_' . substr(md5(time()), 0, 8); - \OC_Appconfig::setValue('files_encryption', 'recoveryKeyId', $recoveryKeyId); - } - - if (!$view->is_dir('/owncloud_private_key')) { - $view->mkdir('/owncloud_private_key'); - } - - if ( - (!$view->file_exists("/public-keys/" . $recoveryKeyId . ".public.key") - || !$view->file_exists("/owncloud_private_key/" . $recoveryKeyId . ".private.key")) - ) { - - $keypair = \OCA\Encryption\Crypt::createKeypair(); - - \OC_FileProxy::$enabled = false; - - // Save public key - - if (!$view->is_dir('/public-keys')) { - $view->mkdir('/public-keys'); - } - - $view->file_put_contents('/public-keys/' . $recoveryKeyId . '.public.key', $keypair['publicKey']); - - // Encrypt private key empthy passphrase - $encryptedPrivateKey = \OCA\Encryption\Crypt::symmetricEncryptFileContent($keypair['privateKey'], $_POST['recoveryPassword']); - - // Save private key - $view->file_put_contents('/owncloud_private_key/' . $recoveryKeyId . '.private.key', $encryptedPrivateKey); - - // create control file which let us check later on if the entered password was correct. - $encryptedControlData = \OCA\Encryption\Crypt::keyEncrypt("ownCloud", $keypair['publicKey']); - if (!$view->is_dir('/control-file')) { - $view->mkdir('/control-file'); - } - $view->file_put_contents('/control-file/controlfile.enc', $encryptedControlData); - - \OC_FileProxy::$enabled = true; - - // Set recoveryAdmin as enabled - OC_Appconfig::setValue('files_encryption', 'recoveryAdminEnabled', 1); - - $return = true; - - } else { // get recovery key and check the password - $util = new \OCA\Encryption\Util(new \OC_FilesystemView('/'), \OCP\User::getUser()); - $return = $util->checkRecoveryPassword($_POST['recoveryPassword']); - if ($return) { - OC_Appconfig::setValue('files_encryption', 'recoveryAdminEnabled', 1); - } - } + $return = \Helper::adminEnableRecovery($recoveryKeyId, $_POST['recoveryPassword']); // Disable recoveryAdmin } elseif ( isset($_POST['adminEnableRecovery']) && 0 == $_POST['adminEnableRecovery'] ) { - $util = new \OCA\Encryption\Util(new \OC_FilesystemView('/'), \OCP\User::getUser()); - $return = $util->checkRecoveryPassword($_POST['recoveryPassword']); - - if ($return) { - // Set recoveryAdmin as disabled - OC_Appconfig::setValue('files_encryption', 'recoveryAdminEnabled', 0); - } + $return = \Helper::adminDisableRecovery($_POST['recoveryPassword']); } // Return success or failure diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php index 86d860465e..a04c65e251 100755 --- a/apps/files_encryption/lib/helper.php +++ b/apps/files_encryption/lib/helper.php @@ -26,6 +26,10 @@ namespace OCA\Encryption; /** * @brief Class to manage registration of hooks an various helper methods */ +/** + * Class Helper + * @package OCA\Encryption + */ class Helper { /** @@ -89,4 +93,92 @@ class Helper { return true; } + + /** + * @brief enable recovery + * + * @param $recoveryKeyId + * @param $recoveryPassword + * @internal param \OCA\Encryption\Util $util + * @internal param string $password + * @return bool + */ + public static function adminEnableRecovery($recoveryKeyId, $recoveryPassword) { + $view = new \OC\Files\View('/'); + + if ($recoveryKeyId === null) { + $recoveryKeyId = 'recovery_' . substr(md5(time()), 0, 8); + \OC_Appconfig::setValue('files_encryption', 'recoveryKeyId', $recoveryKeyId); + } + + if (!$view->is_dir('/owncloud_private_key')) { + $view->mkdir('/owncloud_private_key'); + } + + if ( + (!$view->file_exists("/public-keys/" . $recoveryKeyId . ".public.key") + || !$view->file_exists("/owncloud_private_key/" . $recoveryKeyId . ".private.key")) + ) { + + $keypair = \OCA\Encryption\Crypt::createKeypair(); + + \OC_FileProxy::$enabled = false; + + // Save public key + + if (!$view->is_dir('/public-keys')) { + $view->mkdir('/public-keys'); + } + + $view->file_put_contents('/public-keys/' . $recoveryKeyId . '.public.key', $keypair['publicKey']); + + // Encrypt private key empthy passphrase + $encryptedPrivateKey = \OCA\Encryption\Crypt::symmetricEncryptFileContent($keypair['privateKey'], $recoveryPassword); + + // Save private key + $view->file_put_contents('/owncloud_private_key/' . $recoveryKeyId . '.private.key', $encryptedPrivateKey); + + // create control file which let us check later on if the entered password was correct. + $encryptedControlData = \OCA\Encryption\Crypt::keyEncrypt("ownCloud", $keypair['publicKey']); + if (!$view->is_dir('/control-file')) { + $view->mkdir('/control-file'); + } + $view->file_put_contents('/control-file/controlfile.enc', $encryptedControlData); + + \OC_FileProxy::$enabled = true; + + // Set recoveryAdmin as enabled + \OC_Appconfig::setValue('files_encryption', 'recoveryAdminEnabled', 1); + + $return = true; + + } else { // get recovery key and check the password + $util = new \OCA\Encryption\Util(new \OC_FilesystemView('/'), \OCP\User::getUser()); + $return = $util->checkRecoveryPassword($_POST['recoveryPassword']); + if ($return) { + \OC_Appconfig::setValue('files_encryption', 'recoveryAdminEnabled', 1); + } + } + + return $return; + } + + + /** + * @brief disable recovery + * + * @param $recoveryPassword + * @return bool + */ + public static function adminDisableRecovery($recoveryPassword) { + $util = new Util(new \OC_FilesystemView('/'), \OCP\User::getUser()); + $return = $util->checkRecoveryPassword($recoveryPassword); + + if ($return) { + // Set recoveryAdmin as disabled + \OC_Appconfig::setValue('files_encryption', 'recoveryAdminEnabled', 0); + } + + return $return; + } } \ No newline at end of file From a4c0eb17569457784faa06ed0b65a319f7ec2f78 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Fri, 17 May 2013 01:07:26 +0200 Subject: [PATCH 4/6] improved tests --- apps/files_encryption/tests/crypt.php | 17 +++++++++++++++- apps/files_encryption/tests/keymanager.php | 23 ++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/apps/files_encryption/tests/crypt.php b/apps/files_encryption/tests/crypt.php index 1caa9ea7da..bfb5ca0ec8 100755 --- a/apps/files_encryption/tests/crypt.php +++ b/apps/files_encryption/tests/crypt.php @@ -62,8 +62,17 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { // Filesystem related hooks \OCA\Encryption\Helper::registerFilesystemHooks(); + // Filesystem related hooks + \OCA\Encryption\Helper::registerUserHooks(); + \OC_FileProxy::register(new OCA\Encryption\Proxy()); + // remember files_trashbin state + $this->stateFilesTrashbin = OC_App::isEnabled('files_trashbin'); + + // we don't want to tests with app files_trashbin enabled + \OC_App::disable('files_trashbin'); + \OC_Util::tearDownFS(); \OC_User::setUserId(''); \OC\Files\Filesystem::tearDown(); @@ -78,6 +87,13 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { function tearDown() { \OC_FileProxy::clearProxies(); + + // reset app files_trashbin + if ($this->stateFilesTrashbin) { + OC_App::enable('files_trashbin'); + } else { + OC_App::disable('files_trashbin'); + } } function testGenerateKey() { @@ -686,7 +702,6 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { $this->assertEquals( $this->dataLong, $newDecrypt ); // tear down - $view->unlink( $newFolder . '/' . $newFilename ); $view->unlink( $newFolder ); } diff --git a/apps/files_encryption/tests/keymanager.php b/apps/files_encryption/tests/keymanager.php index 28452d779c..3f6b936373 100644 --- a/apps/files_encryption/tests/keymanager.php +++ b/apps/files_encryption/tests/keymanager.php @@ -57,6 +57,12 @@ class Test_Keymanager extends \PHPUnit_Framework_TestCase { \OC_FileProxy::register(new OCA\Encryption\Proxy()); + // remember files_trashbin state + $this->stateFilesTrashbin = OC_App::isEnabled('files_trashbin'); + + // we don't want to tests with app files_trashbin enabled + \OC_App::disable('files_trashbin'); + \OC_Util::tearDownFS(); \OC_User::setUserId(''); \OC\Files\Filesystem::tearDown(); @@ -72,6 +78,13 @@ class Test_Keymanager extends \PHPUnit_Framework_TestCase { \OC_FileProxy::$enabled = true; \OC_FileProxy::clearProxies(); + + // reset app files_trashbin + if ($this->stateFilesTrashbin) { + OC_App::enable('files_trashbin'); + } else { + OC_App::disable('files_trashbin'); + } } function testGetPrivateKey() { @@ -116,6 +129,16 @@ class Test_Keymanager extends \PHPUnit_Framework_TestCase { //$view = new \OC_FilesystemView( '/' . $this->userId . '/files_encryption/keyfiles' ); Encryption\Keymanager::setFileKey( $this->view, $file, $this->userId, $key['key'] ); + + // Disable encryption proxy to prevent recursive calls + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = true; + + // cleanup + $this->view->unlink('/'.$this->userId . '/files/' . $file); + + // Re-enable proxy - our work is done + \OC_FileProxy::$enabled = $proxyStatus; } From 2b0bf4dc87a1117de5b2a6c0201f35736b80f0e7 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Fri, 17 May 2013 01:07:50 +0200 Subject: [PATCH 5/6] added tests for recovery --- apps/files_encryption/tests/share.php | 144 +++++++++++++++++++++++++- 1 file changed, 142 insertions(+), 2 deletions(-) diff --git a/apps/files_encryption/tests/share.php b/apps/files_encryption/tests/share.php index e5427fdf50..a40a992b80 100755 --- a/apps/files_encryption/tests/share.php +++ b/apps/files_encryption/tests/share.php @@ -528,12 +528,152 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase } - function loginHelper($user, $create = false) + function testRecoveryFile() + { + // login as admin + $this->loginHelper('admin'); + + \OCA\Encryption\Helper::adminEnableRecovery(null, 'test123'); + $recoveryKeyId = OC_Appconfig::getValue('files_encryption', 'recoveryKeyId'); + + // check if control file created + $this->assertTrue($this->view->file_exists('/control-file/controlfile.enc')); + + $util = new \OCA\Encryption\Util(new \OC_FilesystemView('/'), 'admin'); + + // check if recovery password match + $this->assertTrue($util->checkRecoveryPassword('test123')); + + // enable recovery for admin + $this->assertTrue($util->setRecoveryForUser(true)); + + // create folder structure + $this->view->mkdir('/admin/files' . $this->folder1); + $this->view->mkdir('/admin/files' . $this->folder1 . $this->subfolder); + $this->view->mkdir('/admin/files' . $this->folder1 . $this->subfolder . $this->subsubfolder); + + // save file with content + $cryptedFile1 = file_put_contents('crypt://' . $this->filename, $this->dataShort); + $cryptedFile2 = file_put_contents('crypt://' . $this->folder1 . $this->subfolder . $this->subsubfolder .'/'. $this->filename, $this->dataShort); + + // test that data was successfully written + $this->assertTrue(is_int($cryptedFile1)); + $this->assertTrue(is_int($cryptedFile2)); + + // check if share key for admin and recovery exists + $this->assertTrue($this->view->file_exists('/admin/files_encryption/share-keys/' . $this->filename . '.admin.shareKey')); + $this->assertTrue($this->view->file_exists('/admin/files_encryption/share-keys/' . $this->filename . '.'.$recoveryKeyId.'.shareKey')); + $this->assertTrue($this->view->file_exists('/admin/files_encryption/share-keys/' . $this->folder1 . $this->subfolder . $this->subsubfolder .'/'. $this->filename . '.admin.shareKey')); + $this->assertTrue($this->view->file_exists('/admin/files_encryption/share-keys/' . $this->folder1 . $this->subfolder . $this->subsubfolder .'/'. $this->filename . '.'.$recoveryKeyId.'.shareKey')); + + // disable recovery for admin + $this->assertTrue($util->setRecoveryForUser(false)); + + // remove all recovery keys + $util->removeRecoveryKeys('/'); + + // check if share key for recovery not exists + $this->assertFalse($this->view->file_exists('/admin/files_encryption/share-keys/' . $this->filename . '.'.$recoveryKeyId.'.shareKey')); + $this->assertFalse($this->view->file_exists('/admin/files_encryption/share-keys/' . $this->folder1 . $this->subfolder . $this->subsubfolder .'/'. $this->filename . '.'.$recoveryKeyId.'.shareKey')); + + // enable recovery for admin + $this->assertTrue($util->setRecoveryForUser(true)); + + // remove all recovery keys + $util->addRecoveryKeys('/'); + + // check if share key for admin and recovery exists + $this->assertTrue($this->view->file_exists('/admin/files_encryption/share-keys/' . $this->filename . '.'.$recoveryKeyId.'.shareKey')); + $this->assertTrue($this->view->file_exists('/admin/files_encryption/share-keys/' . $this->folder1 . $this->subfolder . $this->subsubfolder .'/'. $this->filename . '.'.$recoveryKeyId.'.shareKey')); + + // cleanup + $this->view->unlink('/admin/files/' . $this->filename); + $this->view->unlink('/admin/files/' . $this->folder1 . $this->subfolder . $this->subsubfolder .'/'. $this->filename); + + // check if share key for recovery not exists + $this->assertFalse($this->view->file_exists('/admin/files_encryption/share-keys/' . $this->filename . '.'.$recoveryKeyId.'.shareKey')); + $this->assertFalse($this->view->file_exists('/admin/files_encryption/share-keys/' . $this->folder1 . $this->subfolder . $this->subsubfolder .'/'. $this->filename . '.'.$recoveryKeyId.'.shareKey')); + } + + function testRecoveryForUser() + { + // login as admin + $this->loginHelper('admin'); + + \OCA\Encryption\Helper::adminEnableRecovery(null, 'test123'); + $recoveryKeyId = OC_Appconfig::getValue('files_encryption', 'recoveryKeyId'); + + // check if control file created + $this->assertTrue($this->view->file_exists('/control-file/controlfile.enc')); + + // login as user1 + $this->loginHelper('user1'); + + $util = new \OCA\Encryption\Util(new \OC_FilesystemView('/'), 'user1'); + + // enable recovery for admin + $this->assertTrue($util->setRecoveryForUser(true)); + + // create folder structure + $this->view->mkdir('/user1/files' . $this->folder1); + $this->view->mkdir('/user1/files' . $this->folder1 . $this->subfolder); + $this->view->mkdir('/user1/files' . $this->folder1 . $this->subfolder . $this->subsubfolder); + + // save file with content + $cryptedFile1 = file_put_contents('crypt://' . $this->filename, $this->dataShort); + $cryptedFile2 = file_put_contents('crypt://' . $this->folder1 . $this->subfolder . $this->subsubfolder .'/'. $this->filename, $this->dataShort); + + // test that data was successfully written + $this->assertTrue(is_int($cryptedFile1)); + $this->assertTrue(is_int($cryptedFile2)); + + // check if share key for user and recovery exists + $this->assertTrue($this->view->file_exists('/user1/files_encryption/share-keys/' . $this->filename . '.user1.shareKey')); + $this->assertTrue($this->view->file_exists('/user1/files_encryption/share-keys/' . $this->filename . '.'.$recoveryKeyId.'.shareKey')); + $this->assertTrue($this->view->file_exists('/user1/files_encryption/share-keys/' . $this->folder1 . $this->subfolder . $this->subsubfolder .'/'. $this->filename . '.user1.shareKey')); + $this->assertTrue($this->view->file_exists('/user1/files_encryption/share-keys/' . $this->folder1 . $this->subfolder . $this->subsubfolder .'/'. $this->filename . '.'.$recoveryKeyId.'.shareKey')); + + // login as admin + $this->loginHelper('admin'); + + // change password + \OC_User::setPassword('user1', 'test', 'test123'); + + // login as user1 + $this->loginHelper('user1', false, 'test'); + + // get file contents + $retrievedCryptedFile1 = file_get_contents('crypt://' . $this->filename); + $retrievedCryptedFile2 = file_get_contents('crypt://' . $this->folder1 . $this->subfolder . $this->subsubfolder .'/'. $this->filename); + + // check if data is the same as we previously written + $this->assertEquals($this->dataShort, $retrievedCryptedFile1); + $this->assertEquals($this->dataShort, $retrievedCryptedFile2); + + // cleanup + $this->view->unlink('/user1/files' . $this->folder1); + $this->view->unlink('/user1/files' . $this->filename); + + // check if share key for user and recovery exists + $this->assertFalse($this->view->file_exists('/user1/files_encryption/share-keys/' . $this->filename . '.user1.shareKey')); + $this->assertFalse($this->view->file_exists('/user1/files_encryption/share-keys/' . $this->filename . '.'.$recoveryKeyId.'.shareKey')); + $this->assertFalse($this->view->file_exists('/user1/files_encryption/share-keys/' . $this->folder1 . $this->subfolder . $this->subsubfolder .'/'. $this->filename . '.user1.shareKey')); + $this->assertFalse($this->view->file_exists('/user1/files_encryption/share-keys/' . $this->folder1 . $this->subfolder . $this->subsubfolder .'/'. $this->filename . '.'.$recoveryKeyId.'.shareKey')); + + // enable recovery for admin + $this->assertTrue($util->setRecoveryForUser(false)); + } + + function loginHelper($user, $create = false, $password = false) { if ($create) { \OC_User::createUser($user, $user); } + if($password === false) { + $password = $user; + } + \OC_Util::tearDownFS(); \OC_User::setUserId(''); \OC\Files\Filesystem::tearDown(); @@ -541,7 +681,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase \OC_User::setUserId($user); $params['uid'] = $user; - $params['password'] = $user; + $params['password'] = $password; OCA\Encryption\Hooks::login($params); } } From d7dc710c8b1d46947cb2afe13152e0adc9ee5594 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Fri, 17 May 2013 01:17:55 +0200 Subject: [PATCH 6/6] revert changes --- lib/public/share.php | 53 +++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/lib/public/share.php b/lib/public/share.php index e1538152d8..03d662676c 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -1541,34 +1541,31 @@ class Share { } public static function post_addToGroup($arguments) { - - if(\OC_Config::getValue('installed')) { - // Find the group shares and check if the user needs a unique target - $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share` WHERE `share_type` = ? AND `share_with` = ?'); - $result = $query->execute(array(self::SHARE_TYPE_GROUP, $arguments['gid'])); - $query = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`item_type`, `item_source`,' - .' `item_target`, `parent`, `share_type`, `share_with`, `uid_owner`, `permissions`,' - .' `stime`, `file_source`, `file_target`) VALUES (?,?,?,?,?,?,?,?,?,?,?)'); - while ($item = $result->fetchRow()) { - if ($item['item_type'] == 'file' || $item['item_type'] == 'file') { - $itemTarget = null; - } else { - $itemTarget = self::generateTarget($item['item_type'], $item['item_source'], self::SHARE_TYPE_USER, - $arguments['uid'], $item['uid_owner'], $item['item_target'], $item['id']); - } - if (isset($item['file_source'])) { - $fileTarget = self::generateTarget($item['item_type'], $item['item_source'], self::SHARE_TYPE_USER, - $arguments['uid'], $item['uid_owner'], $item['file_target'], $item['id']); - } else { - $fileTarget = null; - } - // Insert an extra row for the group share if the item or file target is unique for this user - if ($itemTarget != $item['item_target'] || $fileTarget != $item['file_target']) { - $query->execute(array($item['item_type'], $item['item_source'], $itemTarget, $item['id'], - self::$shareTypeGroupUserUnique, $arguments['uid'], $item['uid_owner'], $item['permissions'], - $item['stime'], $item['file_source'], $fileTarget)); - \OC_DB::insertid('*PREFIX*share'); - } + // Find the group shares and check if the user needs a unique target + $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share` WHERE `share_type` = ? AND `share_with` = ?'); + $result = $query->execute(array(self::SHARE_TYPE_GROUP, $arguments['gid'])); + $query = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`item_type`, `item_source`,' + .' `item_target`, `parent`, `share_type`, `share_with`, `uid_owner`, `permissions`,' + .' `stime`, `file_source`, `file_target`) VALUES (?,?,?,?,?,?,?,?,?,?,?)'); + while ($item = $result->fetchRow()) { + if ($item['item_type'] == 'file' || $item['item_type'] == 'file') { + $itemTarget = null; + } else { + $itemTarget = self::generateTarget($item['item_type'], $item['item_source'], self::SHARE_TYPE_USER, + $arguments['uid'], $item['uid_owner'], $item['item_target'], $item['id']); + } + if (isset($item['file_source'])) { + $fileTarget = self::generateTarget($item['item_type'], $item['item_source'], self::SHARE_TYPE_USER, + $arguments['uid'], $item['uid_owner'], $item['file_target'], $item['id']); + } else { + $fileTarget = null; + } + // Insert an extra row for the group share if the item or file target is unique for this user + if ($itemTarget != $item['item_target'] || $fileTarget != $item['file_target']) { + $query->execute(array($item['item_type'], $item['item_source'], $itemTarget, $item['id'], + self::$shareTypeGroupUserUnique, $arguments['uid'], $item['uid_owner'], $item['permissions'], + $item['stime'], $item['file_source'], $fileTarget)); + \OC_DB::insertid('*PREFIX*share'); } } }