summaryrefslogtreecommitdiffstats
path: root/apps/files_encryption/tests
diff options
context:
space:
mode:
Diffstat (limited to 'apps/files_encryption/tests')
-rw-r--r--apps/files_encryption/tests/binarybin0 -> 9734 bytes
-rwxr-xr-xapps/files_encryption/tests/crypt.php809
-rw-r--r--apps/files_encryption/tests/encryption.keybin0 -> 24 bytes
-rw-r--r--apps/files_encryption/tests/keymanager.php245
-rw-r--r--apps/files_encryption/tests/legacy-encrypted-text.txt1
-rw-r--r--apps/files_encryption/tests/proxy.php220
-rwxr-xr-xapps/files_encryption/tests/share.php911
-rw-r--r--apps/files_encryption/tests/stream.php180
-rwxr-xr-xapps/files_encryption/tests/trashbin.php300
-rwxr-xr-xapps/files_encryption/tests/util.php317
-rwxr-xr-xapps/files_encryption/tests/webdav.php262
-rw-r--r--apps/files_encryption/tests/zerosbin0 -> 10238 bytes
12 files changed, 3245 insertions, 0 deletions
diff --git a/apps/files_encryption/tests/binary b/apps/files_encryption/tests/binary
new file mode 100644
index 00000000000..79bc99479da
--- /dev/null
+++ b/apps/files_encryption/tests/binary
Binary files differ
diff --git a/apps/files_encryption/tests/crypt.php b/apps/files_encryption/tests/crypt.php
new file mode 100755
index 00000000000..32156eea272
--- /dev/null
+++ b/apps/files_encryption/tests/crypt.php
@@ -0,0 +1,809 @@
+<?php
+/**
+ * Copyright (c) 2012 Sam Tuke <samtuke@owncloud.com>, and
+ * Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+require_once realpath(dirname(__FILE__) . '/../3rdparty/Crypt_Blowfish/Blowfish.php');
+require_once realpath(dirname(__FILE__) . '/../../../lib/base.php');
+require_once realpath(dirname(__FILE__) . '/../lib/crypt.php');
+require_once realpath(dirname(__FILE__) . '/../lib/keymanager.php');
+require_once realpath(dirname(__FILE__) . '/../lib/proxy.php');
+require_once realpath(dirname(__FILE__) . '/../lib/stream.php');
+require_once realpath(dirname(__FILE__) . '/../lib/util.php');
+require_once realpath(dirname(__FILE__) . '/../lib/helper.php');
+require_once realpath(dirname(__FILE__) . '/../appinfo/app.php');
+require_once realpath(dirname(__FILE__) . '/util.php');
+
+use OCA\Encryption;
+
+/**
+ * Class Test_Encryption_Crypt
+ */
+class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
+
+ const TEST_ENCRYPTION_CRYPT_USER1 = "test-crypt-user1";
+
+ public $userId;
+ public $pass;
+ public $stateFilesTrashbin;
+ public $dataLong;
+ public $dataUrl;
+ public $dataShort;
+ /**
+ * @var OC_FilesystemView
+ */
+ public $view;
+ public $legacyEncryptedData;
+ public $genPrivateKey;
+ public $genPublicKey;
+
+ public static function setUpBeforeClass() {
+ // reset backend
+ \OC_User::clearBackends();
+ \OC_User::useBackend('database');
+
+ // Filesystem related hooks
+ \OCA\Encryption\Helper::registerFilesystemHooks();
+
+ // Filesystem related hooks
+ \OCA\Encryption\Helper::registerUserHooks();
+
+ // clear and register hooks
+ \OC_FileProxy::clearProxies();
+ \OC_FileProxy::register(new OCA\Encryption\Proxy());
+
+ // create test user
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Crypt::TEST_ENCRYPTION_CRYPT_USER1, true);
+ }
+
+ function setUp() {
+ // set user id
+ \OC_User::setUserId(\Test_Encryption_Crypt::TEST_ENCRYPTION_CRYPT_USER1);
+ $this->userId = \Test_Encryption_Crypt::TEST_ENCRYPTION_CRYPT_USER1;
+ $this->pass = \Test_Encryption_Crypt::TEST_ENCRYPTION_CRYPT_USER1;
+
+ // set content for encrypting / decrypting in tests
+ $this->dataLong = file_get_contents(realpath(dirname(__FILE__) . '/../lib/crypt.php'));
+ $this->dataShort = 'hats';
+ $this->dataUrl = realpath(dirname(__FILE__) . '/../lib/crypt.php');
+ $this->legacyData = realpath(dirname(__FILE__) . '/legacy-text.txt');
+ $this->legacyEncryptedData = realpath(dirname(__FILE__) . '/legacy-encrypted-text.txt');
+ $this->legacyEncryptedDataKey = realpath(dirname(__FILE__) . '/encryption.key');
+ $this->randomKey = Encryption\Crypt::generateKey();
+
+ $keypair = Encryption\Crypt::createKeypair();
+ $this->genPublicKey = $keypair['publicKey'];
+ $this->genPrivateKey = $keypair['privateKey'];
+
+ $this->view = new \OC_FilesystemView('/');
+
+ // 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');
+ }
+
+ function tearDown() {
+ // reset app files_trashbin
+ if ($this->stateFilesTrashbin) {
+ OC_App::enable('files_trashbin');
+ }
+ else {
+ OC_App::disable('files_trashbin');
+ }
+ }
+
+ public static function tearDownAfterClass() {
+ // cleanup test user
+ \OC_User::deleteUser(\Test_Encryption_Crypt::TEST_ENCRYPTION_CRYPT_USER1);
+ }
+
+ function testGenerateKey() {
+
+ # TODO: use more accurate (larger) string length for test confirmation
+
+ $key = Encryption\Crypt::generateKey();
+
+ $this->assertTrue(strlen($key) > 16);
+
+ }
+
+ /**
+ * @return String
+ */
+ function testGenerateIv() {
+
+ $iv = Encryption\Crypt::generateIv();
+
+ $this->assertEquals(16, strlen($iv));
+
+ return $iv;
+
+ }
+
+ /**
+ * @depends testGenerateIv
+ */
+ function testConcatIv($iv) {
+
+ $catFile = Encryption\Crypt::concatIv($this->dataLong, $iv);
+
+ // Fetch encryption metadata from end of file
+ $meta = substr($catFile, -22);
+
+ $identifier = substr($meta, 0, 6);
+
+ // Fetch IV from end of file
+ $foundIv = substr($meta, 6);
+
+ $this->assertEquals('00iv00', $identifier);
+
+ $this->assertEquals($iv, $foundIv);
+
+ // Remove IV and IV identifier text to expose encrypted content
+ $data = substr($catFile, 0, -22);
+
+ $this->assertEquals($this->dataLong, $data);
+
+ return array(
+ 'iv' => $iv
+ ,
+ 'catfile' => $catFile
+ );
+
+ }
+
+ /**
+ * @depends testConcatIv
+ */
+ function testSplitIv($testConcatIv) {
+
+ // Split catfile into components
+ $splitCatfile = Encryption\Crypt::splitIv($testConcatIv['catfile']);
+
+ // Check that original IV and split IV match
+ $this->assertEquals($testConcatIv['iv'], $splitCatfile['iv']);
+
+ // Check that original data and split data match
+ $this->assertEquals($this->dataLong, $splitCatfile['encrypted']);
+
+ }
+
+ /**
+ * @return string padded
+ */
+ function testAddPadding() {
+
+ $padded = Encryption\Crypt::addPadding($this->dataLong);
+
+ $padding = substr($padded, -2);
+
+ $this->assertEquals('xx', $padding);
+
+ return $padded;
+
+ }
+
+ /**
+ * @depends testAddPadding
+ */
+ function testRemovePadding($padded) {
+
+ $noPadding = Encryption\Crypt::RemovePadding($padded);
+
+ $this->assertEquals($this->dataLong, $noPadding);
+
+ }
+
+ function testEncrypt() {
+
+ $random = openssl_random_pseudo_bytes(13);
+
+ $iv = substr(base64_encode($random), 0, -4); // i.e. E5IG033j+mRNKrht
+
+ $crypted = Encryption\Crypt::encrypt($this->dataUrl, $iv, 'hat');
+
+ $this->assertNotEquals($this->dataUrl, $crypted);
+
+ }
+
+ function testDecrypt() {
+
+ $random = openssl_random_pseudo_bytes(13);
+
+ $iv = substr(base64_encode($random), 0, -4); // i.e. E5IG033j+mRNKrht
+
+ $crypted = Encryption\Crypt::encrypt($this->dataUrl, $iv, 'hat');
+
+ $decrypt = Encryption\Crypt::decrypt($crypted, $iv, 'hat');
+
+ $this->assertEquals($this->dataUrl, $decrypt);
+
+ }
+
+ function testSymmetricEncryptFileContent() {
+
+ # TODO: search in keyfile for actual content as IV will ensure this test always passes
+
+ $crypted = Encryption\Crypt::symmetricEncryptFileContent($this->dataShort, 'hat');
+
+ $this->assertNotEquals($this->dataShort, $crypted);
+
+
+ $decrypt = Encryption\Crypt::symmetricDecryptFileContent($crypted, 'hat');
+
+ $this->assertEquals($this->dataShort, $decrypt);
+
+ }
+
+ function testSymmetricStreamEncryptShortFileContent() {
+
+ $filename = 'tmp-' . time() . '.test';
+
+ $cryptedFile = file_put_contents('crypt://' . $filename, $this->dataShort);
+
+ // Test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ // Disable encryption proxy to prevent recursive calls
+ $proxyStatus = \OC_FileProxy::$enabled;
+ \OC_FileProxy::$enabled = false;
+
+ // Get file contents without using any wrapper to get it's actual contents on disk
+ $retreivedCryptedFile = $this->view->file_get_contents($this->userId . '/files/' . $filename);
+
+ // Re-enable proxy - our work is done
+ \OC_FileProxy::$enabled = $proxyStatus;
+
+ // Check that the file was encrypted before being written to disk
+ $this->assertNotEquals($this->dataShort, $retreivedCryptedFile);
+
+ // Get the encrypted keyfile
+ $encKeyfile = Encryption\Keymanager::getFileKey($this->view, $this->userId, $filename);
+
+ // Attempt to fetch the user's shareKey
+ $shareKey = Encryption\Keymanager::getShareKey($this->view, $this->userId, $filename);
+
+ // get session
+ $session = new \OCA\Encryption\Session($this->view);
+
+ // get private key
+ $privateKey = $session->getPrivateKey($this->userId);
+
+ // Decrypt keyfile with shareKey
+ $plainKeyfile = Encryption\Crypt::multiKeyDecrypt($encKeyfile, $shareKey, $privateKey);
+
+ // Manually decrypt
+ $manualDecrypt = Encryption\Crypt::symmetricDecryptFileContent($retreivedCryptedFile, $plainKeyfile);
+
+ // Check that decrypted data matches
+ $this->assertEquals($this->dataShort, $manualDecrypt);
+
+ // Teardown
+ $this->view->unlink($this->userId . '/files/' . $filename);
+
+ Encryption\Keymanager::deleteFileKey($this->view, $this->userId, $filename);
+ }
+
+ /**
+ * @brief Test that data that is written by the crypto stream wrapper
+ * @note Encrypted data is manually prepared and decrypted here to avoid dependency on success of stream_read
+ * @note If this test fails with truncate content, check that enough array slices are being rejoined to form $e, as the crypt.php file may have gotten longer and broken the manual
+ * reassembly of its data
+ */
+ function testSymmetricStreamEncryptLongFileContent() {
+
+ // Generate a a random filename
+ $filename = 'tmp-' . time() . '.test';
+
+ // Save long data as encrypted file using stream wrapper
+ $cryptedFile = file_put_contents('crypt://' . $filename, $this->dataLong . $this->dataLong);
+
+ // Test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ // Disable encryption proxy to prevent recursive calls
+ $proxyStatus = \OC_FileProxy::$enabled;
+ \OC_FileProxy::$enabled = false;
+
+ // Get file contents without using any wrapper to get it's actual contents on disk
+ $retreivedCryptedFile = $this->view->file_get_contents($this->userId . '/files/' . $filename);
+
+ // Re-enable proxy - our work is done
+ \OC_FileProxy::$enabled = $proxyStatus;
+
+
+ // Check that the file was encrypted before being written to disk
+ $this->assertNotEquals($this->dataLong . $this->dataLong, $retreivedCryptedFile);
+
+ // Manuallly split saved file into separate IVs and encrypted chunks
+ $r = preg_split('/(00iv00.{16,18})/', $retreivedCryptedFile, NULL, PREG_SPLIT_DELIM_CAPTURE);
+
+ //print_r($r);
+
+ // Join IVs and their respective data chunks
+ $e = array(
+ $r[0] . $r[1],
+ $r[2] . $r[3],
+ $r[4] . $r[5],
+ $r[6] . $r[7],
+ $r[8] . $r[9],
+ $r[10] . $r[11]
+ ); //.$r[11], $r[12].$r[13], $r[14] );
+
+ //print_r($e);
+
+ // Get the encrypted keyfile
+ $encKeyfile = Encryption\Keymanager::getFileKey($this->view, $this->userId, $filename);
+
+ // Attempt to fetch the user's shareKey
+ $shareKey = Encryption\Keymanager::getShareKey($this->view, $this->userId, $filename);
+
+ // get session
+ $session = new \OCA\Encryption\Session($this->view);
+
+ // get private key
+ $privateKey = $session->getPrivateKey($this->userId);
+
+ // Decrypt keyfile with shareKey
+ $plainKeyfile = Encryption\Crypt::multiKeyDecrypt($encKeyfile, $shareKey, $privateKey);
+
+ // Set var for reassembling decrypted content
+ $decrypt = '';
+
+ // Manually decrypt chunk
+ foreach ($e as $chunk) {
+
+ $chunkDecrypt = Encryption\Crypt::symmetricDecryptFileContent($chunk, $plainKeyfile);
+
+ // Assemble decrypted chunks
+ $decrypt .= $chunkDecrypt;
+
+ }
+
+ $this->assertEquals($this->dataLong . $this->dataLong, $decrypt);
+
+ // Teardown
+
+ $this->view->unlink($this->userId . '/files/' . $filename);
+
+ Encryption\Keymanager::deleteFileKey($this->view, $this->userId, $filename);
+
+ }
+
+ /**
+ * @brief Test that data that is read by the crypto stream wrapper
+ */
+ function testSymmetricStreamDecryptShortFileContent() {
+
+ $filename = 'tmp-' . time();
+
+ // Save long data as encrypted file using stream wrapper
+ $cryptedFile = file_put_contents('crypt://' . $filename, $this->dataShort);
+
+ // Test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ // Disable encryption proxy to prevent recursive calls
+ $proxyStatus = \OC_FileProxy::$enabled;
+ \OC_FileProxy::$enabled = false;
+
+ $this->assertTrue(Encryption\Crypt::isEncryptedMeta($filename));
+
+ \OC_FileProxy::$enabled = $proxyStatus;
+
+ // Get file decrypted contents
+ $decrypt = file_get_contents('crypt://' . $filename);
+
+ $this->assertEquals($this->dataShort, $decrypt);
+
+ // tear down
+ $this->view->unlink($this->userId . '/files/' . $filename);
+ }
+
+ function testSymmetricStreamDecryptLongFileContent() {
+
+ $filename = 'tmp-' . time();
+
+ // Save long data as encrypted file using stream wrapper
+ $cryptedFile = file_put_contents('crypt://' . $filename, $this->dataLong);
+
+ // Test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ // Get file decrypted contents
+ $decrypt = file_get_contents('crypt://' . $filename);
+
+ $this->assertEquals($this->dataLong, $decrypt);
+
+ // tear down
+ $this->view->unlink($this->userId . '/files/' . $filename);
+ }
+
+ function testSymmetricEncryptFileContentKeyfile() {
+
+ # TODO: search in keyfile for actual content as IV will ensure this test always passes
+
+ $crypted = Encryption\Crypt::symmetricEncryptFileContentKeyfile($this->dataUrl);
+
+ $this->assertNotEquals($this->dataUrl, $crypted['encrypted']);
+
+
+ $decrypt = Encryption\Crypt::symmetricDecryptFileContent($crypted['encrypted'], $crypted['key']);
+
+ $this->assertEquals($this->dataUrl, $decrypt);
+
+ }
+
+ function testIsEncryptedContent() {
+
+ $this->assertFalse(Encryption\Crypt::isCatfileContent($this->dataUrl));
+
+ $this->assertFalse(Encryption\Crypt::isCatfileContent($this->legacyEncryptedData));
+
+ $keyfileContent = Encryption\Crypt::symmetricEncryptFileContent($this->dataUrl, 'hat');
+
+ $this->assertTrue(Encryption\Crypt::isCatfileContent($keyfileContent));
+
+ }
+
+ function testMultiKeyEncrypt() {
+
+ # TODO: search in keyfile for actual content as IV will ensure this test always passes
+
+ $pair1 = Encryption\Crypt::createKeypair();
+
+ $this->assertEquals(2, count($pair1));
+
+ $this->assertTrue(strlen($pair1['publicKey']) > 1);
+
+ $this->assertTrue(strlen($pair1['privateKey']) > 1);
+
+
+ $crypted = Encryption\Crypt::multiKeyEncrypt($this->dataShort, array($pair1['publicKey']));
+
+ $this->assertNotEquals($this->dataShort, $crypted['data']);
+
+
+ $decrypt = Encryption\Crypt::multiKeyDecrypt($crypted['data'], $crypted['keys'][0], $pair1['privateKey']);
+
+ $this->assertEquals($this->dataShort, $decrypt);
+
+ }
+
+ function testKeyEncrypt() {
+
+ // Generate keypair
+ $pair1 = Encryption\Crypt::createKeypair();
+
+ // Encrypt data
+ $crypted = Encryption\Crypt::keyEncrypt($this->dataUrl, $pair1['publicKey']);
+
+ $this->assertNotEquals($this->dataUrl, $crypted);
+
+ // Decrypt data
+ $decrypt = Encryption\Crypt::keyDecrypt($crypted, $pair1['privateKey']);
+
+ $this->assertEquals($this->dataUrl, $decrypt);
+
+ }
+
+ /**
+ * @brief test encryption using legacy blowfish method
+ */
+ function testLegacyEncryptShort() {
+
+ $crypted = Encryption\Crypt::legacyEncrypt($this->dataShort, $this->pass);
+
+ $this->assertNotEquals($this->dataShort, $crypted);
+
+ # TODO: search inencrypted text for actual content to ensure it
+ # genuine transformation
+
+ return $crypted;
+
+ }
+
+ /**
+ * @brief test decryption using legacy blowfish method
+ * @depends testLegacyEncryptShort
+ */
+ function testLegacyDecryptShort($crypted) {
+
+ $decrypted = Encryption\Crypt::legacyBlockDecrypt($crypted, $this->pass);
+
+ $this->assertEquals($this->dataShort, $decrypted);
+
+ }
+
+ /**
+ * @brief test encryption using legacy blowfish method
+ */
+ function testLegacyEncryptLong() {
+
+ $crypted = Encryption\Crypt::legacyEncrypt($this->dataLong, $this->pass);
+
+ $this->assertNotEquals($this->dataLong, $crypted);
+
+ # TODO: search inencrypted text for actual content to ensure it
+ # genuine transformation
+
+ return $crypted;
+
+ }
+
+ /**
+ * @brief test decryption using legacy blowfish method
+ * @depends testLegacyEncryptLong
+ */
+ function testLegacyDecryptLong($crypted) {
+
+ $decrypted = Encryption\Crypt::legacyBlockDecrypt($crypted, $this->pass);
+
+ $this->assertEquals($this->dataLong, $decrypted);
+
+ $this->assertFalse(Encryption\Crypt::getBlowfish(''));
+ }
+
+ /**
+ * @brief test generation of legacy encryption key
+ * @depends testLegacyDecryptShort
+ */
+ function testLegacyCreateKey() {
+
+ // Create encrypted key
+ $encKey = Encryption\Crypt::legacyCreateKey($this->pass);
+
+ // Decrypt key
+ $key = Encryption\Crypt::legacyBlockDecrypt($encKey, $this->pass);
+
+ $this->assertTrue(is_numeric($key));
+
+ // Check that key is correct length
+ $this->assertEquals(20, strlen($key));
+
+ }
+
+ /**
+ * @brief test decryption using legacy blowfish method
+ * @depends testLegacyEncryptLong
+ */
+ function testLegacyKeyRecryptKeyfileEncrypt($crypted) {
+
+ $recrypted = Encryption\Crypt::LegacyKeyRecryptKeyfile($crypted, $this->pass, array($this->genPublicKey));
+
+ $this->assertNotEquals($this->dataLong, $recrypted['data']);
+
+ return $recrypted;
+
+ # TODO: search inencrypted text for actual content to ensure it
+ # genuine transformation
+
+ }
+
+ function testRenameFile() {
+
+ $filename = 'tmp-' . time();
+
+ // Save long data as encrypted file using stream wrapper
+ $cryptedFile = file_put_contents('crypt://' . $filename, $this->dataLong);
+
+ // Test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ // Get file decrypted contents
+ $decrypt = file_get_contents('crypt://' . $filename);
+
+ $this->assertEquals($this->dataLong, $decrypt);
+
+ $newFilename = 'tmp-new-' . time();
+ $view = new \OC\Files\View('/' . $this->userId . '/files');
+ $view->rename($filename, $newFilename);
+
+ // Get file decrypted contents
+ $newDecrypt = file_get_contents('crypt://' . $newFilename);
+
+ $this->assertEquals($this->dataLong, $newDecrypt);
+
+ // tear down
+ $view->unlink($newFilename);
+ }
+
+ function testMoveFileIntoFolder() {
+
+ $filename = 'tmp-' . time();
+
+ // Save long data as encrypted file using stream wrapper
+ $cryptedFile = file_put_contents('crypt://' . $filename, $this->dataLong);
+
+ // Test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ // Get file decrypted contents
+ $decrypt = file_get_contents('crypt://' . $filename);
+
+ $this->assertEquals($this->dataLong, $decrypt);
+
+ $newFolder = '/newfolder' . time();
+ $newFilename = 'tmp-new-' . time();
+ $view = new \OC\Files\View('/' . $this->userId . '/files');
+ $view->mkdir($newFolder);
+ $view->rename($filename, $newFolder . '/' . $newFilename);
+
+ // Get file decrypted contents
+ $newDecrypt = file_get_contents('crypt://' . $newFolder . '/' . $newFilename);
+
+ $this->assertEquals($this->dataLong, $newDecrypt);
+
+ // tear down
+ $view->unlink($newFolder);
+ }
+
+ function testMoveFolder() {
+
+ $view = new \OC\Files\View('/' . $this->userId . '/files');
+
+ $filename = '/tmp-' . time();
+ $folder = '/folder' . time();
+
+ $view->mkdir($folder);
+
+ // Save long data as encrypted file using stream wrapper
+ $cryptedFile = file_put_contents('crypt://' . $folder . $filename, $this->dataLong);
+
+ // Test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ // Get file decrypted contents
+ $decrypt = file_get_contents('crypt://' . $folder . $filename);
+
+ $this->assertEquals($this->dataLong, $decrypt);
+
+ $newFolder = '/newfolder/subfolder' . time();
+ $view->mkdir('/newfolder');
+
+ $view->rename($folder, $newFolder);
+
+ // Get file decrypted contents
+ $newDecrypt = file_get_contents('crypt://' . $newFolder . $filename);
+
+ $this->assertEquals($this->dataLong, $newDecrypt);
+
+ // tear down
+ $view->unlink($newFolder);
+ $view->unlink('/newfolder');
+ }
+
+ function testChangePassphrase() {
+ $filename = 'tmp-' . time();
+
+ // Save long data as encrypted file using stream wrapper
+ $cryptedFile = file_put_contents('crypt://' . $filename, $this->dataLong);
+
+ // Test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ // Get file decrypted contents
+ $decrypt = file_get_contents('crypt://' . $filename);
+
+ $this->assertEquals($this->dataLong, $decrypt);
+
+ // change password
+ \OC_User::setPassword($this->userId, 'test', null);
+
+ // relogin
+ $params['uid'] = $this->userId;
+ $params['password'] = 'test';
+ OCA\Encryption\Hooks::login($params);
+
+ // Get file decrypted contents
+ $newDecrypt = file_get_contents('crypt://' . $filename);
+
+ $this->assertEquals($this->dataLong, $newDecrypt);
+
+ // tear down
+ // change password back
+ \OC_User::setPassword($this->userId, $this->pass);
+ $view = new \OC\Files\View('/' . $this->userId . '/files');
+ $view->unlink($filename);
+ }
+
+ function testViewFilePutAndGetContents() {
+
+ $filename = '/tmp-' . time();
+ $view = new \OC\Files\View('/' . $this->userId . '/files');
+
+ // Save short data as encrypted file using stream wrapper
+ $cryptedFile = $view->file_put_contents($filename, $this->dataShort);
+
+ // Test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ // Get file decrypted contents
+ $decrypt = $view->file_get_contents($filename);
+
+ $this->assertEquals($this->dataShort, $decrypt);
+
+ // Save long data as encrypted file using stream wrapper
+ $cryptedFileLong = $view->file_put_contents($filename, $this->dataLong);
+
+ // Test that data was successfully written
+ $this->assertTrue(is_int($cryptedFileLong));
+
+ // Get file decrypted contents
+ $decryptLong = $view->file_get_contents($filename);
+
+ $this->assertEquals($this->dataLong, $decryptLong);
+
+ // tear down
+ $view->unlink($filename);
+ }
+
+ function testTouchExistingFile() {
+ $filename = '/tmp-' . time();
+ $view = new \OC\Files\View('/' . $this->userId . '/files');
+
+ // Save short data as encrypted file using stream wrapper
+ $cryptedFile = $view->file_put_contents($filename, $this->dataShort);
+
+ // Test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ $view->touch($filename);
+
+ // Get file decrypted contents
+ $decrypt = $view->file_get_contents($filename);
+
+ $this->assertEquals($this->dataShort, $decrypt);
+
+ // tear down
+ $view->unlink($filename);
+ }
+
+ function testTouchFile() {
+ $filename = '/tmp-' . time();
+ $view = new \OC\Files\View('/' . $this->userId . '/files');
+
+ $view->touch($filename);
+
+ // Save short data as encrypted file using stream wrapper
+ $cryptedFile = $view->file_put_contents($filename, $this->dataShort);
+
+ // Test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ // Get file decrypted contents
+ $decrypt = $view->file_get_contents($filename);
+
+ $this->assertEquals($this->dataShort, $decrypt);
+
+ // tear down
+ $view->unlink($filename);
+ }
+
+ function testFopenFile() {
+ $filename = '/tmp-' . time();
+ $view = new \OC\Files\View('/' . $this->userId . '/files');
+
+ // Save short data as encrypted file using stream wrapper
+ $cryptedFile = $view->file_put_contents($filename, $this->dataShort);
+
+ // Test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ $handle = $view->fopen($filename, 'r');
+
+ // Get file decrypted contents
+ $decrypt = fgets($handle);
+
+ $this->assertEquals($this->dataShort, $decrypt);
+
+ // tear down
+ $view->unlink($filename);
+ }
+}
diff --git a/apps/files_encryption/tests/encryption.key b/apps/files_encryption/tests/encryption.key
new file mode 100644
index 00000000000..4ee962145c2
--- /dev/null
+++ b/apps/files_encryption/tests/encryption.key
Binary files differ
diff --git a/apps/files_encryption/tests/keymanager.php b/apps/files_encryption/tests/keymanager.php
new file mode 100644
index 00000000000..40ae1659a55
--- /dev/null
+++ b/apps/files_encryption/tests/keymanager.php
@@ -0,0 +1,245 @@
+<?php
+/**
+ * Copyright (c) 2012 Sam Tuke <samtuke@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+require_once realpath(dirname(__FILE__) . '/../../../lib/base.php');
+require_once realpath(dirname(__FILE__) . '/../lib/crypt.php');
+require_once realpath(dirname(__FILE__) . '/../lib/keymanager.php');
+require_once realpath(dirname(__FILE__) . '/../lib/proxy.php');
+require_once realpath(dirname(__FILE__) . '/../lib/stream.php');
+require_once realpath(dirname(__FILE__) . '/../lib/util.php');
+require_once realpath(dirname(__FILE__) . '/../lib/helper.php');
+require_once realpath(dirname(__FILE__) . '/../appinfo/app.php');
+
+use OCA\Encryption;
+
+/**
+ * Class Test_Encryption_Keymanager
+ */
+class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
+
+ public $userId;
+ public $pass;
+ public $stateFilesTrashbin;
+ /**
+ * @var OC_FilesystemView
+ */
+ public $view;
+ public $randomKey;
+ public $dataShort;
+
+ public static function setUpBeforeClass() {
+ // reset backend
+ \OC_User::clearBackends();
+ \OC_User::useBackend('database');
+
+ // Filesystem related hooks
+ \OCA\Encryption\Helper::registerFilesystemHooks();
+
+ // clear and register hooks
+ \OC_FileProxy::clearProxies();
+ \OC_FileProxy::register(new OCA\Encryption\Proxy());
+
+ // disable file proxy by default
+ \OC_FileProxy::$enabled = false;
+
+ // setup filesystem
+ \OC_Util::tearDownFS();
+ \OC_User::setUserId('');
+ \OC\Files\Filesystem::tearDown();
+ \OC_Util::setupFS('admin');
+ \OC_User::setUserId('admin');
+
+ // login admin
+ $params['uid'] = 'admin';
+ $params['password'] = 'admin';
+ OCA\Encryption\Hooks::login($params);
+ }
+
+ function setUp() {
+ // set content for encrypting / decrypting in tests
+ $this->dataLong = file_get_contents(realpath(dirname(__FILE__) . '/../lib/crypt.php'));
+ $this->dataShort = 'hats';
+ $this->dataUrl = realpath(dirname(__FILE__) . '/../lib/crypt.php');
+ $this->legacyData = realpath(dirname(__FILE__) . '/legacy-text.txt');
+ $this->legacyEncryptedData = realpath(dirname(__FILE__) . '/legacy-encrypted-text.txt');
+ $this->randomKey = Encryption\Crypt::generateKey();
+
+ $keypair = Encryption\Crypt::createKeypair();
+ $this->genPublicKey = $keypair['publicKey'];
+ $this->genPrivateKey = $keypair['privateKey'];
+
+ $this->view = new \OC_FilesystemView('/');
+
+ \OC_User::setUserId('admin');
+ $this->userId = 'admin';
+ $this->pass = 'admin';
+
+ $userHome = \OC_User::getHome($this->userId);
+ $this->dataDir = str_replace('/' . $this->userId, '', $userHome);
+
+ // 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');
+ }
+
+ function tearDown() {
+ // reset app files_trashbin
+ if ($this->stateFilesTrashbin) {
+ OC_App::enable('files_trashbin');
+ }
+ else {
+ OC_App::disable('files_trashbin');
+ }
+ }
+
+ public static function tearDownAfterClass() {
+ \OC_FileProxy::$enabled = true;
+ }
+
+ function testGetPrivateKey() {
+
+ $key = Encryption\Keymanager::getPrivateKey($this->view, $this->userId);
+
+ $privateKey = Encryption\Crypt::symmetricDecryptFileContent($key, $this->pass);
+
+ $res = openssl_pkey_get_private($privateKey);
+
+ $this->assertTrue(is_resource($res));
+
+ $sslInfo = openssl_pkey_get_details($res);
+
+ $this->assertArrayHasKey('key', $sslInfo);
+
+ }
+
+ function testGetPublicKey() {
+
+ $publiceKey = Encryption\Keymanager::getPublicKey($this->view, $this->userId);
+
+ $res = openssl_pkey_get_public($publiceKey);
+
+ $this->assertTrue(is_resource($res));
+
+ $sslInfo = openssl_pkey_get_details($res);
+
+ $this->assertArrayHasKey('key', $sslInfo);
+ }
+
+ function testSetFileKey() {
+
+ # NOTE: This cannot be tested until we are able to break out
+ # of the FileSystemView data directory root
+
+ $key = Encryption\Crypt::symmetricEncryptFileContentKeyfile($this->randomKey, 'hat');
+
+ $file = 'unittest-' . time() . '.txt';
+
+ // Disable encryption proxy to prevent recursive calls
+ $proxyStatus = \OC_FileProxy::$enabled;
+ \OC_FileProxy::$enabled = false;
+
+ $this->view->file_put_contents($this->userId . '/files/' . $file, $key['encrypted']);
+
+ // Re-enable proxy - our work is done
+ \OC_FileProxy::$enabled = $proxyStatus;
+
+ //$view = new \OC_FilesystemView( '/' . $this->userId . '/files_encryption/keyfiles' );
+ Encryption\Keymanager::setFileKey($this->view, $file, $this->userId, $key['key']);
+
+ // enable encryption proxy
+ $proxyStatus = \OC_FileProxy::$enabled;
+ \OC_FileProxy::$enabled = true;
+
+ // cleanup
+ $this->view->unlink('/' . $this->userId . '/files/' . $file);
+
+ // change encryption proxy to previous state
+ \OC_FileProxy::$enabled = $proxyStatus;
+
+ }
+
+ function testGetUserKeys() {
+
+ $keys = Encryption\Keymanager::getUserKeys($this->view, $this->userId);
+
+ $resPublic = openssl_pkey_get_public($keys['publicKey']);
+
+ $this->assertTrue(is_resource($resPublic));
+
+ $sslInfoPublic = openssl_pkey_get_details($resPublic);
+
+ $this->assertArrayHasKey('key', $sslInfoPublic);
+
+ $privateKey = Encryption\Crypt::symmetricDecryptFileContent($keys['privateKey'], $this->pass);
+
+ $resPrivate = openssl_pkey_get_private($privateKey);
+
+ $this->assertTrue(is_resource($resPrivate));
+
+ $sslInfoPrivate = openssl_pkey_get_details($resPrivate);
+
+ $this->assertArrayHasKey('key', $sslInfoPrivate);
+ }
+
+ function testFixPartialFilePath() {
+
+ $partFilename = 'testfile.txt.part';
+ $filename = 'testfile.txt';
+
+ $this->assertTrue(Encryption\Keymanager::isPartialFilePath($partFilename));
+
+ $this->assertEquals('testfile.txt', Encryption\Keymanager::fixPartialFilePath($partFilename));
+
+ $this->assertFalse(Encryption\Keymanager::isPartialFilePath($filename));
+
+ $this->assertEquals('testfile.txt', Encryption\Keymanager::fixPartialFilePath($filename));
+ }
+
+ function testRecursiveDelShareKeys() {
+
+ // generate filename
+ $filename = '/tmp-' . time() . '.txt';
+
+ // create folder structure
+ $this->view->mkdir('/admin/files/folder1');
+ $this->view->mkdir('/admin/files/folder1/subfolder');
+ $this->view->mkdir('/admin/files/folder1/subfolder/subsubfolder');
+
+ // enable encryption proxy
+ $proxyStatus = \OC_FileProxy::$enabled;
+ \OC_FileProxy::$enabled = true;
+
+ // save file with content
+ $cryptedFile = file_put_contents('crypt:///folder1/subfolder/subsubfolder/' . $filename, $this->dataShort);
+
+ // test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ // change encryption proxy to previous state
+ \OC_FileProxy::$enabled = $proxyStatus;
+
+ // recursive delete keys
+ Encryption\Keymanager::delShareKey($this->view, array('admin'), '/folder1/');
+
+ // check if share key not exists
+ $this->assertFalse($this->view->file_exists(
+ '/admin/files_encryption/share-keys/folder1/subfolder/subsubfolder/' . $filename . '.admin.shareKey'));
+
+ // enable encryption proxy
+ $proxyStatus = \OC_FileProxy::$enabled;
+ \OC_FileProxy::$enabled = true;
+
+ // cleanup
+ $this->view->unlink('/admin/files/folder1');
+
+ // change encryption proxy to previous state
+ \OC_FileProxy::$enabled = $proxyStatus;
+ }
+}
diff --git a/apps/files_encryption/tests/legacy-encrypted-text.txt b/apps/files_encryption/tests/legacy-encrypted-text.txt
new file mode 100644
index 00000000000..1f5087178cd
--- /dev/null
+++ b/apps/files_encryption/tests/legacy-encrypted-text.txt
@@ -0,0 +1 @@
+ð˜¯5–¡‹Ç¡i›òë³Zg§ESlÁF=Àªð \ No newline at end of file
diff --git a/apps/files_encryption/tests/proxy.php b/apps/files_encryption/tests/proxy.php
new file mode 100644
index 00000000000..5a2d851ff7c
--- /dev/null
+++ b/apps/files_encryption/tests/proxy.php
@@ -0,0 +1,220 @@
+<?php
+/**
+ * Copyright (c) 2012 Sam Tuke <samtuke@owncloud.com>,
+ * and Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+// require_once "PHPUnit/Framework/TestCase.php";
+// require_once realpath( dirname(__FILE__).'/../../../lib/base.php' );
+// require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery.php' );
+// require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/Generator.php' );
+// require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/MockInterface.php' );
+// require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/Mock.php' );
+// require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/Container.php' );
+// require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/Configuration.php' );
+// require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/CompositeExpectation.php' );
+// require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/ExpectationDirector.php' );
+// require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/Expectation.php' );
+// require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/Exception.php' );
+// require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/CountValidator/CountValidatorAbstract.php' );
+// require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/CountValidator/Exception.php' );
+// require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/CountValidator/Exact.php' );
+//
+// use \Mockery as m;
+// use OCA\Encryption;
+
+// class Test_Util extends \PHPUnit_Framework_TestCase {
+//
+// public function setUp() {
+//
+// $this->proxy = new Encryption\Proxy();
+//
+// $this->tmpFileName = "tmpFile-".time();
+//
+// $this->privateKey = file_get_contents( realpath( dirname(__FILE__).'/data/admin.public.key' ) );
+// $this->publicKey = file_get_contents( realpath( dirname(__FILE__).'/data/admin.private.key' ) );
+// $this->encDataShort = file_get_contents( realpath( dirname(__FILE__).'/data/yoga-manchester-enc' ) );
+// $this->encDataShortKey = file_get_contents( realpath( dirname(__FILE__).'/data/yoga-manchester.key' ) );
+//
+// $this->dataShort = file_get_contents( realpath( dirname(__FILE__).'/data/yoga-manchester' ) );
+// $this->dataLong = file_get_contents( realpath( dirname(__FILE__).'/../lib/crypt.php' ) );
+// $this->longDataPath = realpath( dirname(__FILE__).'/../lib/crypt.php' );
+//
+// $this->data1 = file_get_contents( realpath( dirname(__FILE__).'/../../../data/admin/files/enc-test.txt' ) );
+//
+// \OC_FileProxy::$enabled = false;
+// $this->Encdata1 = file_get_contents( realpath( dirname(__FILE__).'/../../../data/admin/files/enc-test.txt' ) );
+// \OC_FileProxy::$enabled = true;
+//
+// $this->userId = 'admin';
+// $this->pass = 'admin';
+//
+// $this->session = new Encryption\Session( $view ); // FIXME: Provide a $view object for use here
+//
+// $this->session->setPrivateKey(
+// '-----BEGIN PRIVATE KEY-----
+// MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDiH3EA4EpFA7Fx
+// s2dyyfL5jwXeYXrTqQJ6DqKgGn8VsbT3eu8R9KzM2XitVwZe8c8L52DvJ06o5vg0
+// GqPYxilFdOFJe/ggac5Tq8UmJiZS4EqYEMwxBIfIyWTxeGV06/0HOwnVAkqHMcBz
+// 64qldtgi5O8kZMEM2/gKBgU0kMLJzM+8oEWhL1+gsUWQhxd8cKLXypS6iWgqFJrz
+// f/X0hJsJR+gyYxNpahtnjzd/LxLAETrOMsl2tue+BAxmjbAM0aG0NEM0div+b59s
+// 2uz/iWbxImp5pOdYVKcVW89D4XBMyGegR40trV2VwiuX1blKCfdjMsJhiaL9pymp
+// ug1wzyQFAgMBAAECggEAK6c+PZkPPXuVCgpEcliiW6NM0r2m5K3AGKgypQ34csu3
+// z/8foCvIIFPrhCtEw5eTDQ1CHWlNOjY8vHJYJ0U6Onpx86nHIRrMBkMm8FJ1G5LJ
+// U8oKYXwqaozWu/cuPwA//OFc6I5krOzh5n8WaRMkbrgbor8AtebRX74By0AXGrXe
+// cswJI7zR96oFn4Dm7Pgvpg5Zhk1vFJ+w6QtH+4DDJ6PBvlZsRkGxYBLGVd/3qhAI
+// sBAyjFlSzuP4eCRhHOhHC/e4gmAH9evFVXB88jFyRZm3K+jQ5W5CwrVRBCV2lph6
+// 2B6P7CBJN+IjGKMhy+75y13UvvKPv9IwH8Fzl2x1gQKBgQD8qQOr7a6KhSj16wQE
+// jim2xqt9gQ2jH5No405NrKs/PFQQZnzD4YseQsiK//NUjOJiUhaT+L5jhIpzINHt
+// RJpt3bGkEZmLyjdjgTpB3GwZdXa28DNK9VdXZ19qIl/ZH0qAjKmJCRahUDASMnVi
+// M4Pkk9yx9ZIKkri4TcuMWqc0DQKBgQDlHKBTITZq/arYPD6Nl3NsoOdqVRqJrGay
+// 0TjXAVbBXe46+z5lnMsqwXb79nx14hdmSEsZULrw/3f+MnQbdjMTYLFP24visZg9
+// MN8vAiALiiiR1a+Crz+DTA1Q8sGOMVCMqMDmD7QBys3ZuWxuapm0txAiIYUtsjJZ
+// XN76T4nZ2QKBgQCHaT3igzwsWTmesxowJtEMeGWomeXpKx8h89EfqA8PkRGsyIDN
+// qq+YxEoe1RZgljEuaLhZDdNcGsjo8woPk9kAUPTH7fbRCMuutK+4ZJ469s1tNkcH
+// QX5SBcEJbOrZvv967ehe3VQXmJZq6kgnHVzuwKBjcC2ZJRGDFY6l5l/+cQKBgCqh
+// +Adf/8NK7paMJ0urqfPFwSodKfICXZ3apswDWMRkmSbqh4La+Uc8dsqN5Dz/VEFZ
+// JHhSeGbN8uMfOlG93eU2MehdPxtw1pZUWMNjjtj23XO9ooob2CKzbSrp8TBnZsi1
+// widNNr66oTFpeo7VUUK6acsgF6sYJJxSVr+XO1yJAoGAEhvitq8shNKcEY0xCipS
+// k1kbgyS7KKB7opVxI5+ChEqyUDijS3Y9FZixrRIWE6i2uGu86UG+v2lbKvSbM4Qm
+// xvbOcX9OVMnlRb7n8woOP10UMY+ZE2x+YEUXQTLtPYq7F66e1OfxltstMxLQA+3d
+// Y1d5piFV8PXK3Fg2F+Cj5qg=
+// -----END PRIVATE KEY-----
+// '
+// , $this->userId
+// );
+//
+// \OC_User::setUserId( $this->userId );
+//
+// }
+//
+// public function testpreFile_get_contents() {
+//
+// // This won't work for now because mocking of the static keymanager class isn't working :(
+//
+// // $mock = m::mock( 'alias:OCA\Encryption\Keymanager' );
+// //
+// // $mock->shouldReceive( 'getFileKey' )->times(2)->andReturn( $this->encDataShort );
+// //
+// // $encrypted = $this->proxy->postFile_get_contents( 'data/'.$this->tmpFileName, $this->encDataShortKey );
+// //
+// // $this->assertNotEquals( $this->dataShort, $encrypted );
+//
+// $decrypted = $this->proxy->postFile_get_contents( 'data/admin/files/enc-test.txt', $this->data1 );
+//
+// }
+//
+// }
+
+// class Test_CryptProxy extends PHPUnit_Framework_TestCase {
+// private $oldConfig;
+// private $oldKey;
+//
+// public function setUp(){
+// $user=OC_User::getUser();
+//
+// $this->oldConfig=OCP\Config::getAppValue('files_encryption','enable_encryption','true');
+// OCP\Config::setAppValue('files_encryption','enable_encryption','true');
+// $this->oldKey=isset($_SESSION['privateKey'])?$_SESSION['privateKey']:null;
+//
+//
+// //set testing key
+// $_SESSION['privateKey']=md5(time());
+//
+// //clear all proxies and hooks so we can do clean testing
+// OC_FileProxy::clearProxies();
+// OC_Hook::clear('OC_Filesystem');
+//
+// //enable only the encryption hook
+// OC_FileProxy::register(new OC_FileProxy_Encryption());
+//
+// //set up temporary storage
+// OC_Filesystem::clearMounts();
+// OC_Filesystem::mount('OC_Filestorage_Temporary',array(),'/');
+//
+// OC_Filesystem::init('/'.$user.'/files');
+//
+// //set up the users home folder in the temp storage
+// $rootView=new OC_FilesystemView('');
+// $rootView->mkdir('/'.$user);
+// $rootView->mkdir('/'.$user.'/files');
+// }
+//
+// public function tearDown(){
+// OCP\Config::setAppValue('files_encryption','enable_encryption',$this->oldConfig);
+// if(!is_null($this->oldKey)){
+// $_SESSION['privateKey']=$this->oldKey;
+// }
+// }
+//
+// public function testSimple(){
+// $file=OC::$SERVERROOT.'/3rdparty/MDB2.php';
+// $original=file_get_contents($file);
+//
+// OC_Filesystem::file_put_contents('/file',$original);
+//
+// OC_FileProxy::$enabled=false;
+// $stored=OC_Filesystem::file_get_contents('/file');
+// OC_FileProxy::$enabled=true;
+//
+// $fromFile=OC_Filesystem::file_get_contents('/file');
+// $this->assertNotEquals($original,$stored);
+// $this->assertEquals(strlen($original),strlen($fromFile));
+// $this->assertEquals($original,$fromFile);
+//
+// }
+//
+// public function testView(){
+// $file=OC::$SERVERROOT.'/3rdparty/MDB2.php';
+// $original=file_get_contents($file);
+//
+// $rootView=new OC_FilesystemView('');
+// $view=new OC_FilesystemView('/'.OC_User::getUser());
+// $userDir='/'.OC_User::getUser().'/files';
+//
+// $rootView->file_put_contents($userDir.'/file',$original);
+//
+// OC_FileProxy::$enabled=false;
+// $stored=$rootView->file_get_contents($userDir.'/file');
+// OC_FileProxy::$enabled=true;
+//
+// $this->assertNotEquals($original,$stored);
+// $fromFile=$rootView->file_get_contents($userDir.'/file');
+// $this->assertEquals($original,$fromFile);
+//
+// $fromFile=$view->file_get_contents('files/file');
+// $this->assertEquals($original,$fromFile);
+// }
+//
+// public function testBinary(){
+// $file=__DIR__.'/binary';
+// $original=file_get_contents($file);
+//
+// OC_Filesystem::file_put_contents('/file',$original);
+//
+// OC_FileProxy::$enabled=false;
+// $stored=OC_Filesystem::file_get_contents('/file');
+// OC_FileProxy::$enabled=true;
+//
+// $fromFile=OC_Filesystem::file_get_contents('/file');
+// $this->assertNotEquals($original,$stored);
+// $this->assertEquals(strlen($original),strlen($fromFile));
+// $this->assertEquals($original,$fromFile);
+//
+// $file=__DIR__.'/zeros';
+// $original=file_get_contents($file);
+//
+// OC_Filesystem::file_put_contents('/file',$original);
+//
+// OC_FileProxy::$enabled=false;
+// $stored=OC_Filesystem::file_get_contents('/file');
+// OC_FileProxy::$enabled=true;
+//
+// $fromFile=OC_Filesystem::file_get_contents('/file');
+// $this->assertNotEquals($original,$stored);
+// $this->assertEquals(strlen($original),strlen($fromFile));
+// }
+// }
diff --git a/apps/files_encryption/tests/share.php b/apps/files_encryption/tests/share.php
new file mode 100755
index 00000000000..6d92881ceb0
--- /dev/null
+++ b/apps/files_encryption/tests/share.php
@@ -0,0 +1,911 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Florin Peter
+ * @copyright 2013 Florin Peter <owncloud@florin-peter.de>
+ *
+ * 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/>.
+ *
+ */
+
+require_once realpath(dirname(__FILE__) . '/../3rdparty/Crypt_Blowfish/Blowfish.php');
+require_once realpath(dirname(__FILE__) . '/../../../lib/base.php');
+require_once realpath(dirname(__FILE__) . '/../lib/crypt.php');
+require_once realpath(dirname(__FILE__) . '/../lib/keymanager.php');
+require_once realpath(dirname(__FILE__) . '/../lib/proxy.php');
+require_once realpath(dirname(__FILE__) . '/../lib/stream.php');
+require_once realpath(dirname(__FILE__) . '/../lib/util.php');
+require_once realpath(dirname(__FILE__) . '/../lib/helper.php');
+require_once realpath(dirname(__FILE__) . '/../appinfo/app.php');
+require_once realpath(dirname(__FILE__) . '/util.php');
+
+use OCA\Encryption;
+
+/**
+ * Class Test_Encryption_Share
+ */
+class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
+
+ const TEST_ENCRYPTION_SHARE_USER1 = "test-share-user1";
+ const TEST_ENCRYPTION_SHARE_USER2 = "test-share-user2";
+ const TEST_ENCRYPTION_SHARE_USER3 = "test-share-user3";
+ const TEST_ENCRYPTION_SHARE_USER4 = "test-share-user4";
+ const TEST_ENCRYPTION_SHARE_GROUP1 = "test-share-group1";
+
+ public $stateFilesTrashbin;
+ public $filename;
+ public $dataShort;
+ /**
+ * @var OC_FilesystemView
+ */
+ public $view;
+ public $folder1;
+ public $subfolder;
+ public $subsubfolder;
+
+ public static function setUpBeforeClass() {
+ // reset backend
+ \OC_User::clearBackends();
+ \OC_User::useBackend('database');
+
+ // enable resharing
+ \OC_Appconfig::setValue('core', 'shareapi_allow_resharing', 'yes');
+
+ // clear share hooks
+ \OC_Hook::clear('OCP\\Share');
+ \OC::registerShareHooks();
+ \OCP\Util::connectHook('OC_Filesystem', 'setup', '\OC\Files\Storage\Shared', 'setup');
+
+ // Sharing related hooks
+ \OCA\Encryption\Helper::registerShareHooks();
+
+ // Filesystem related hooks
+ \OCA\Encryption\Helper::registerFilesystemHooks();
+
+ // clear and register hooks
+ \OC_FileProxy::clearProxies();
+ \OC_FileProxy::register(new OCA\Encryption\Proxy());
+
+ // create users
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1, true);
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, true);
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3, true);
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4, true);
+
+ // create group and assign users
+ \OC_Group::createGroup(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_GROUP1);
+ \OC_Group::addToGroup(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_GROUP1);
+ \OC_Group::addToGroup(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_GROUP1);
+ }
+
+ function setUp() {
+ $this->dataShort = 'hats';
+ $this->view = new \OC_FilesystemView('/');
+
+ $this->folder1 = '/folder1';
+ $this->subfolder = '/subfolder1';
+ $this->subsubfolder = '/subsubfolder1';
+
+ $this->filename = 'share-tmp.test';
+
+ // we don't want to tests with app files_trashbin enabled
+ \OC_App::disable('files_trashbin');
+
+ // remember files_trashbin state
+ $this->stateFilesTrashbin = OC_App::isEnabled('files_trashbin');
+ }
+
+ function tearDown() {
+ // reset app files_trashbin
+ if ($this->stateFilesTrashbin) {
+ OC_App::enable('files_trashbin');
+ }
+ else {
+ OC_App::disable('files_trashbin');
+ }
+ }
+
+ public static function tearDownAfterClass() {
+ // clean group
+ \OC_Group::deleteGroup(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_GROUP1);
+
+ // cleanup users
+ \OC_User::deleteUser(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+ \OC_User::deleteUser(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
+ \OC_User::deleteUser(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3);
+ \OC_User::deleteUser(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4);
+ }
+
+ /**
+ * @param bool $withTeardown
+ */
+ function testShareFile($withTeardown = true) {
+ // login as admin
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ // save file with content
+ $cryptedFile = file_put_contents('crypt://' . $this->filename, $this->dataShort);
+
+ // test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ // disable encryption proxy to prevent recursive calls
+ $proxyStatus = \OC_FileProxy::$enabled;
+ \OC_FileProxy::$enabled = false;
+
+ // get the file info from previous created file
+ $fileInfo = $this->view->getFileInfo(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
+
+ // check if we have a valid file info
+ $this->assertTrue(is_array($fileInfo));
+
+ // check if the unencrypted file size is stored
+ $this->assertGreaterThan(0, $fileInfo['unencrypted_size']);
+
+ // re-enable the file proxy
+ \OC_FileProxy::$enabled = $proxyStatus;
+
+ // share the file
+ \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, OCP\PERMISSION_ALL);
+
+ // login as admin
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ // check if share key for user1 exists
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
+
+ // login as user1
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
+
+ // get file contents
+ $retrievedCryptedFile = $this->view->file_get_contents(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/Shared/' . $this->filename);
+
+ // check if data is the same as we previously written
+ $this->assertEquals($this->dataShort, $retrievedCryptedFile);
+
+ // cleanup
+ if ($withTeardown) {
+
+ // login as admin
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ // unshare the file
+ \OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
+
+ // check if share key not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
+
+ // cleanup
+ $this->view->unlink(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
+
+ // check if share key not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '.shareKey'));
+ }
+ }
+
+ /**
+ * @param bool $withTeardown
+ */
+ function testReShareFile($withTeardown = true) {
+ $this->testShareFile(false);
+
+ // login as user1
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
+
+ // get the file info
+ $fileInfo = $this->view->getFileInfo(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/Shared/' . $this->filename);
+
+ // share the file with user2
+ \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3, OCP\PERMISSION_ALL);
+
+ // login as admin
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ // check if share key for user2 exists
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '.shareKey'));
+
+ // login as user2
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3);
+
+ // get file contents
+ $retrievedCryptedFile = $this->view->file_get_contents(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '/files/Shared/' . $this->filename);
+
+ // check if data is the same as previously written
+ $this->assertEquals($this->dataShort, $retrievedCryptedFile);
+
+ // cleanup
+ if ($withTeardown) {
+
+ // login as user1
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
+
+ // unshare the file with user2
+ \OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3);
+
+ // login as admin
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ // check if share key not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '.shareKey'));
+
+ // unshare the file with user1
+ \OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
+
+ // check if share key not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
+
+ // cleanup
+ $this->view->unlink(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
+
+ // check if share key not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '.shareKey'));
+ }
+ }
+
+ /**
+ * @param bool $withTeardown
+ * @return array
+ */
+ function testShareFolder($withTeardown = true) {
+ // login as admin
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ // create folder structure
+ $this->view->mkdir('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files' . $this->folder1);
+ $this->view->mkdir(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files' . $this->folder1 . $this->subfolder);
+ $this->view->mkdir(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files' . $this->folder1 . $this->subfolder
+ . $this->subsubfolder);
+
+ // save file with content
+ $cryptedFile = file_put_contents('crypt://' . $this->folder1 . $this->subfolder . $this->subsubfolder . '/'
+ . $this->filename, $this->dataShort);
+
+ // test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ // disable encryption proxy to prevent recursive calls
+ $proxyStatus = \OC_FileProxy::$enabled;
+ \OC_FileProxy::$enabled = false;
+
+ // get the file info from previous created folder
+ $fileInfo = $this->view->getFileInfo(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files' . $this->folder1);
+
+ // check if we have a valid file info
+ $this->assertTrue(is_array($fileInfo));
+
+ // re-enable the file proxy
+ \OC_FileProxy::$enabled = $proxyStatus;
+
+ // share the folder with user1
+ \OCP\Share::shareItem('folder', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, OCP\PERMISSION_ALL);
+
+ // login as admin
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ // check if share key for user1 exists
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys' . $this->folder1
+ . $this->subfolder . $this->subsubfolder . '/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
+
+ // login as user1
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
+
+ // get file contents
+ $retrievedCryptedFile = $this->view->file_get_contents(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/Shared' . $this->folder1
+ . $this->subfolder . $this->subsubfolder . '/' . $this->filename);
+
+ // check if data is the same
+ $this->assertEquals($this->dataShort, $retrievedCryptedFile);
+
+ // cleanup
+ if ($withTeardown) {
+
+ // login as admin
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ // unshare the folder with user1
+ \OCP\Share::unshare('folder', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
+
+ // check if share key not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys'
+ . $this->folder1 . $this->subfolder . $this->subsubfolder . '/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
+
+ // cleanup
+ $this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files' . $this->folder1);
+
+ // check if share key not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys'
+ . $this->folder1 . $this->subfolder . $this->subsubfolder . '/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '.shareKey'));
+ }
+
+ return $fileInfo;
+ }
+
+ /**
+ * @param bool $withTeardown
+ */
+ function testReShareFolder($withTeardown = true) {
+ $fileInfoFolder1 = $this->testShareFolder(false);
+
+ // login as user1
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
+
+ // disable encryption proxy to prevent recursive calls
+ $proxyStatus = \OC_FileProxy::$enabled;
+ \OC_FileProxy::$enabled = false;
+
+ // get the file info from previous created folder
+ $fileInfoSubFolder = $this->view->getFileInfo(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/Shared' . $this->folder1
+ . $this->subfolder);
+
+ // check if we have a valid file info
+ $this->assertTrue(is_array($fileInfoSubFolder));
+
+ // re-enable the file proxy
+ \OC_FileProxy::$enabled = $proxyStatus;
+
+ // share the file with user2
+ \OCP\Share::shareItem('folder', $fileInfoSubFolder['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3, OCP\PERMISSION_ALL);
+
+ // login as admin
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ // check if share key for user2 exists
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys' . $this->folder1
+ . $this->subfolder . $this->subsubfolder . '/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '.shareKey'));
+
+ // login as user2
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3);
+
+ // get file contents
+ $retrievedCryptedFile = $this->view->file_get_contents(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '/files/Shared' . $this->subfolder
+ . $this->subsubfolder . '/' . $this->filename);
+
+ // check if data is the same
+ $this->assertEquals($this->dataShort, $retrievedCryptedFile);
+
+ // get the file info
+ $fileInfo = $this->view->getFileInfo(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '/files/Shared' . $this->subfolder
+ . $this->subsubfolder . '/' . $this->filename);
+
+ // check if we have fileInfos
+ $this->assertTrue(is_array($fileInfo));
+
+ // share the file with user3
+ \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4, OCP\PERMISSION_ALL);
+
+ // login as admin
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ // check if share key for user3 exists
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys' . $this->folder1
+ . $this->subfolder . $this->subsubfolder . '/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4 . '.shareKey'));
+
+ // login as user3
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4);
+
+ // get file contents
+ $retrievedCryptedFile = $this->view->file_get_contents(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4 . '/files/Shared/' . $this->filename);
+
+ // check if data is the same
+ $this->assertEquals($this->dataShort, $retrievedCryptedFile);
+
+ // cleanup
+ if ($withTeardown) {
+
+ // login as user2
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3);
+
+ // unshare the file with user3
+ \OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4);
+
+ // check if share key not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys'
+ . $this->folder1 . $this->subfolder . $this->subsubfolder . '/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4 . '.shareKey'));
+
+ // login as user1
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
+
+ // unshare the folder with user2
+ \OCP\Share::unshare('folder', $fileInfoSubFolder['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3);
+
+ // check if share key not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys'
+ . $this->folder1 . $this->subfolder . $this->subsubfolder . '/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '.shareKey'));
+
+ // login as admin
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ // unshare the folder1 with user1
+ \OCP\Share::unshare('folder', $fileInfoFolder1['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
+
+ // check if share key not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys'
+ . $this->folder1 . $this->subfolder . $this->subsubfolder . '/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
+
+ // cleanup
+ $this->view->unlink(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files' . $this->folder1 . $this->subfolder
+ . $this->subsubfolder . '/' . $this->filename);
+
+ // check if share key not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys'
+ . $this->folder1 . $this->subfolder . $this->subsubfolder . '/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '.shareKey'));
+ }
+ }
+
+ function testPublicShareFile() {
+ // login as admin
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ // save file with content
+ $cryptedFile = file_put_contents('crypt://' . $this->filename, $this->dataShort);
+
+ // test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ // disable encryption proxy to prevent recursive calls
+ $proxyStatus = \OC_FileProxy::$enabled;
+ \OC_FileProxy::$enabled = false;
+
+ // get the file info from previous created file
+ $fileInfo = $this->view->getFileInfo(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
+
+ // check if we have a valid file info
+ $this->assertTrue(is_array($fileInfo));
+
+ // check if the unencrypted file size is stored
+ $this->assertGreaterThan(0, $fileInfo['unencrypted_size']);
+
+ // re-enable the file proxy
+ \OC_FileProxy::$enabled = $proxyStatus;
+
+ // share the file
+ \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_LINK, false, OCP\PERMISSION_ALL);
+
+ // login as admin
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ $publicShareKeyId = \OC_Appconfig::getValue('files_encryption', 'publicShareKeyId');
+
+ // check if share key for public exists
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . $publicShareKeyId . '.shareKey'));
+
+ // some hacking to simulate public link
+ $GLOBALS['app'] = 'files_sharing';
+ $GLOBALS['fileOwner'] = \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1;
+ \OC_User::setUserId('');
+
+ // get file contents
+ $retrievedCryptedFile = file_get_contents('crypt://' . $this->filename);
+
+ // check if data is the same as we previously written
+ $this->assertEquals($this->dataShort, $retrievedCryptedFile);
+
+ // tear down
+
+ // login as admin
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ // unshare the file
+ \OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_LINK, null);
+
+ // check if share key not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . $publicShareKeyId . '.shareKey'));
+
+ // cleanup
+ $this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
+
+ // check if share key not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '.shareKey'));
+ }
+
+ function testShareFileWithGroup() {
+ // login as admin
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ // save file with content
+ $cryptedFile = file_put_contents('crypt://' . $this->filename, $this->dataShort);
+
+ // test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ // disable encryption proxy to prevent recursive calls
+ $proxyStatus = \OC_FileProxy::$enabled;
+ \OC_FileProxy::$enabled = false;
+
+ // get the file info from previous created file
+ $fileInfo = $this->view->getFileInfo(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
+
+ // check if we have a valid file info
+ $this->assertTrue(is_array($fileInfo));
+
+ // check if the unencrypted file size is stored
+ $this->assertGreaterThan(0, $fileInfo['unencrypted_size']);
+
+ // re-enable the file proxy
+ \OC_FileProxy::$enabled = $proxyStatus;
+
+ // share the file
+ \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_GROUP, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_GROUP1, OCP\PERMISSION_ALL);
+
+ // login as admin
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ // check if share key for user2 and user3 exists
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '.shareKey'));
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4 . '.shareKey'));
+
+ // login as user1
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3);
+
+ // get file contents
+ $retrievedCryptedFile = $this->view->file_get_contents(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '/files/Shared/' . $this->filename);
+
+ // check if data is the same as we previously written
+ $this->assertEquals($this->dataShort, $retrievedCryptedFile);
+
+ // login as admin
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ // unshare the file
+ \OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_GROUP, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_GROUP1);
+
+ // check if share key not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '.shareKey'));
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4 . '.shareKey'));
+
+ // cleanup
+ $this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
+
+ // check if share key not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '.shareKey'));
+
+ }
+
+ function testRecoveryFile() {
+ // login as admin
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ \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 admin
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ $util = new \OCA\Encryption\Util(new \OC_FilesystemView('/'), \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ // check if recovery password match
+ $this->assertTrue($util->checkRecoveryPassword('test123'));
+
+ // enable recovery for admin
+ $this->assertTrue($util->setRecoveryForUser(1));
+
+ // create folder structure
+ $this->view->mkdir('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files' . $this->folder1);
+ $this->view->mkdir(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files' . $this->folder1 . $this->subfolder);
+ $this->view->mkdir(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_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 admin and recovery exists
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '.shareKey'));
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . $recoveryKeyId . '.shareKey'));
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/' . $this->folder1
+ . $this->subfolder . $this->subsubfolder . '/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '.shareKey'));
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/' . $this->folder1
+ . $this->subfolder . $this->subsubfolder . '/'
+ . $this->filename . '.' . $recoveryKeyId . '.shareKey'));
+
+ // disable recovery for admin
+ $this->assertTrue($util->setRecoveryForUser(0));
+
+ // remove all recovery keys
+ $util->removeRecoveryKeys('/');
+
+ // check if share key for recovery not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . $recoveryKeyId . '.shareKey'));
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/' . $this->folder1
+ . $this->subfolder . $this->subsubfolder . '/'
+ . $this->filename . '.' . $recoveryKeyId . '.shareKey'));
+
+ // enable recovery for admin
+ $this->assertTrue($util->setRecoveryForUser(1));
+
+ // remove all recovery keys
+ $util->addRecoveryKeys('/');
+
+ // check if share key for admin and recovery exists
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . $recoveryKeyId . '.shareKey'));
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/' . $this->folder1
+ . $this->subfolder . $this->subsubfolder . '/'
+ . $this->filename . '.' . $recoveryKeyId . '.shareKey'));
+
+ // cleanup
+ $this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
+ $this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->folder1);
+
+ // check if share key for recovery not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . $recoveryKeyId . '.shareKey'));
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/' . $this->folder1
+ . $this->subfolder . $this->subsubfolder . '/'
+ . $this->filename . '.' . $recoveryKeyId . '.shareKey'));
+
+ $this->assertTrue(\OCA\Encryption\Helper::adminEnableRecovery(null, 'test123'));
+ $this->assertTrue(\OCA\Encryption\Helper::adminDisableRecovery('test123'));
+ $this->assertEquals(0, \OC_Appconfig::getValue('files_encryption', 'recoveryAdminEnabled'));
+ }
+
+ function testRecoveryForUser() {
+ // login as admin
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ \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
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
+
+ $util = new \OCA\Encryption\Util(new \OC_FilesystemView('/'), \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
+
+ // enable recovery for admin
+ $this->assertTrue($util->setRecoveryForUser(1));
+
+ // create folder structure
+ $this->view->mkdir('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files' . $this->folder1);
+ $this->view->mkdir(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files' . $this->folder1 . $this->subfolder);
+ $this->view->mkdir(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/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(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . $recoveryKeyId . '.shareKey'));
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files_encryption/share-keys/' . $this->folder1
+ . $this->subfolder . $this->subsubfolder . '/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files_encryption/share-keys/' . $this->folder1
+ . $this->subfolder . $this->subsubfolder . '/'
+ . $this->filename . '.' . $recoveryKeyId . '.shareKey'));
+
+ // login as admin
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ // change password
+ \OC_User::setPassword(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, 'test', 'test123');
+
+ // login as user1
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, 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('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files' . $this->folder1);
+ $this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files' . $this->filename);
+
+ // check if share key for user and recovery exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . $recoveryKeyId . '.shareKey'));
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files_encryption/share-keys/' . $this->folder1
+ . $this->subfolder . $this->subsubfolder . '/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files_encryption/share-keys/' . $this->folder1
+ . $this->subfolder . $this->subsubfolder . '/'
+ . $this->filename . '.' . $recoveryKeyId . '.shareKey'));
+
+ // enable recovery for admin
+ $this->assertTrue($util->setRecoveryForUser(0));
+
+ \OCA\Encryption\Helper::adminDisableRecovery('test123');
+ $this->assertEquals(0, \OC_Appconfig::getValue('files_encryption', 'recoveryAdminEnabled'));
+ }
+
+ function testFailShareFile() {
+ // login as admin
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ // save file with content
+ $cryptedFile = file_put_contents('crypt://' . $this->filename, $this->dataShort);
+
+ // test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ // disable encryption proxy to prevent recursive calls
+ $proxyStatus = \OC_FileProxy::$enabled;
+ \OC_FileProxy::$enabled = false;
+
+ // get the file info from previous created file
+ $fileInfo = $this->view->getFileInfo(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
+
+ // check if we have a valid file info
+ $this->assertTrue(is_array($fileInfo));
+
+ // check if the unencrypted file size is stored
+ $this->assertGreaterThan(0, $fileInfo['unencrypted_size']);
+
+ // break users public key
+ $this->view->rename('/public-keys/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '.public.key',
+ '/public-keys/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '.public.key_backup');
+
+ // re-enable the file proxy
+ \OC_FileProxy::$enabled = $proxyStatus;
+
+ // share the file
+ \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_GROUP, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_GROUP1, OCP\PERMISSION_ALL);
+
+ // login as admin
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
+
+ // check if share key for user1 not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '.shareKey'));
+
+ // disable encryption proxy to prevent recursive calls
+ $proxyStatus = \OC_FileProxy::$enabled;
+ \OC_FileProxy::$enabled = false;
+
+ // break user1 public key
+ $this->view->rename(
+ '/public-keys/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '.public.key_backup',
+ '/public-keys/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '.public.key');
+
+ // remove share file
+ $this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3
+ . '.shareKey');
+
+ // re-enable the file proxy
+ \OC_FileProxy::$enabled = $proxyStatus;
+
+ // unshare the file with user1
+ \OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_GROUP, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_GROUP1);
+
+ // check if share key not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '.shareKey'));
+
+ // cleanup
+ $this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
+ }
+
+}
diff --git a/apps/files_encryption/tests/stream.php b/apps/files_encryption/tests/stream.php
new file mode 100644
index 00000000000..3d978767542
--- /dev/null
+++ b/apps/files_encryption/tests/stream.php
@@ -0,0 +1,180 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Florin Peter
+ * @copyright 2013 Florin Peter <owncloud@florin-peter.de>
+ *
+ * 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/>.
+ *
+ */
+
+require_once realpath(dirname(__FILE__) . '/../../../lib/base.php');
+require_once realpath(dirname(__FILE__) . '/../lib/crypt.php');
+require_once realpath(dirname(__FILE__) . '/../lib/keymanager.php');
+require_once realpath(dirname(__FILE__) . '/../lib/proxy.php');
+require_once realpath(dirname(__FILE__) . '/../lib/stream.php');
+require_once realpath(dirname(__FILE__) . '/../lib/util.php');
+require_once realpath(dirname(__FILE__) . '/../appinfo/app.php');
+require_once realpath(dirname(__FILE__) . '/util.php');
+
+use OCA\Encryption;
+
+/**
+ * Class Test_Encryption_Stream
+ * @brief this class provide basic stream tests
+ */
+class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase {
+
+ const TEST_ENCRYPTION_STREAM_USER1 = "test-stream-user1";
+
+ public $userId;
+ public $pass;
+ /**
+ * @var \OC_FilesystemView
+ */
+ public $view;
+ public $dataShort;
+ public $stateFilesTrashbin;
+
+ public static function setUpBeforeClass() {
+ // reset backend
+ \OC_User::clearBackends();
+ \OC_User::useBackend('database');
+
+ // Filesystem related hooks
+ \OCA\Encryption\Helper::registerFilesystemHooks();
+
+ // clear and register hooks
+ \OC_FileProxy::clearProxies();
+ \OC_FileProxy::register(new OCA\Encryption\Proxy());
+
+ // create test user
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Stream::TEST_ENCRYPTION_STREAM_USER1, true);
+ }
+
+ function setUp() {
+ // set user id
+ \OC_User::setUserId(\Test_Encryption_Stream::TEST_ENCRYPTION_STREAM_USER1);
+ $this->userId = \Test_Encryption_Stream::TEST_ENCRYPTION_STREAM_USER1;
+ $this->pass = \Test_Encryption_Stream::TEST_ENCRYPTION_STREAM_USER1;
+
+ // init filesystem view
+ $this->view = new \OC_FilesystemView('/');
+
+ // init short data
+ $this->dataShort = 'hats';
+
+ // 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');
+ }
+
+ function tearDown() {
+ // reset app files_trashbin
+ if ($this->stateFilesTrashbin) {
+ OC_App::enable('files_trashbin');
+ }
+ else {
+ OC_App::disable('files_trashbin');
+ }
+ }
+
+ public static function tearDownAfterClass() {
+ // cleanup test user
+ \OC_User::deleteUser(\Test_Encryption_Stream::TEST_ENCRYPTION_STREAM_USER1);
+ }
+
+ function testStreamOptions() {
+ $filename = '/tmp-' . time();
+ $view = new \OC\Files\View('/' . $this->userId . '/files');
+
+ // Save short data as encrypted file using stream wrapper
+ $cryptedFile = $view->file_put_contents($filename, $this->dataShort);
+
+ // Test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ $handle = $view->fopen($filename, 'r');
+
+ // check if stream is at position zero
+ $this->assertEquals(0, ftell($handle));
+
+ // set stream options
+ $this->assertTrue(flock($handle, LOCK_SH));
+ $this->assertTrue(flock($handle, LOCK_UN));
+
+ // tear down
+ $view->unlink($filename);
+ }
+
+ function testStreamSetBlocking() {
+ $filename = '/tmp-' . time();
+ $view = new \OC\Files\View('/' . $this->userId . '/files');
+
+ // Save short data as encrypted file using stream wrapper
+ $cryptedFile = $view->file_put_contents($filename, $this->dataShort);
+
+ // Test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ $handle = $view->fopen($filename, 'r');
+
+ // set stream options
+ $this->assertTrue(stream_set_blocking($handle, 1));
+
+ // tear down
+ $view->unlink($filename);
+ }
+
+ function testStreamSetTimeout() {
+ $filename = '/tmp-' . time();
+ $view = new \OC\Files\View('/' . $this->userId . '/files');
+
+ // Save short data as encrypted file using stream wrapper
+ $cryptedFile = $view->file_put_contents($filename, $this->dataShort);
+
+ // Test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ $handle = $view->fopen($filename, 'r');
+
+ // set stream options
+ $this->assertFalse(stream_set_timeout($handle, 1));
+
+ // tear down
+ $view->unlink($filename);
+ }
+
+ function testStreamSetWriteBuffer() {
+ $filename = '/tmp-' . time();
+ $view = new \OC\Files\View('/' . $this->userId . '/files');
+
+ // Save short data as encrypted file using stream wrapper
+ $cryptedFile = $view->file_put_contents($filename, $this->dataShort);
+
+ // Test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ $handle = $view->fopen($filename, 'r');
+
+ // set stream options
+ $this->assertEquals(0, stream_set_write_buffer($handle, 1024));
+
+ // tear down
+ $view->unlink($filename);
+ }
+} \ No newline at end of file
diff --git a/apps/files_encryption/tests/trashbin.php b/apps/files_encryption/tests/trashbin.php
new file mode 100755
index 00000000000..29f8fb5a396
--- /dev/null
+++ b/apps/files_encryption/tests/trashbin.php
@@ -0,0 +1,300 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Florin Peter
+ * @copyright 2013 Florin Peter <owncloud@florin-peter.de>
+ *
+ * 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/>.
+ *
+ */
+
+require_once realpath(dirname(__FILE__) . '/../../../lib/base.php');
+require_once realpath(dirname(__FILE__) . '/../lib/crypt.php');
+require_once realpath(dirname(__FILE__) . '/../lib/keymanager.php');
+require_once realpath(dirname(__FILE__) . '/../lib/proxy.php');
+require_once realpath(dirname(__FILE__) . '/../lib/stream.php');
+require_once realpath(dirname(__FILE__) . '/../lib/util.php');
+require_once realpath(dirname(__FILE__) . '/../appinfo/app.php');
+require_once realpath(dirname(__FILE__) . '/../../files_trashbin/appinfo/app.php');
+require_once realpath(dirname(__FILE__) . '/util.php');
+
+use OCA\Encryption;
+
+/**
+ * Class Test_Encryption_Trashbin
+ * @brief this class provide basic trashbin app tests
+ */
+class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase {
+
+ const TEST_ENCRYPTION_TRASHBIN_USER1 = "test-trashbin-user1";
+
+ public $userId;
+ public $pass;
+ /**
+ * @var \OC_FilesystemView
+ */
+ public $view;
+ public $dataShort;
+ public $stateFilesTrashbin;
+ public $folder1;
+ public $subfolder;
+ public $subsubfolder;
+
+ public static function setUpBeforeClass() {
+ // reset backend
+ \OC_User::clearBackends();
+ \OC_User::useBackend('database');
+
+ \OC_Hook::clear('OC_Filesystem');
+ \OC_Hook::clear('OC_User');
+
+ // trashbin hooks
+ \OCA\Files_Trashbin\Trashbin::registerHooks();
+
+ // Filesystem related hooks
+ \OCA\Encryption\Helper::registerFilesystemHooks();
+
+ // clear and register hooks
+ \OC_FileProxy::clearProxies();
+ \OC_FileProxy::register(new OCA\Encryption\Proxy());
+
+ // create test user
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1, true);
+ }
+
+ function setUp() {
+ // set user id
+ \OC_User::setUserId(\Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1);
+ $this->userId = \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1;
+ $this->pass = \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1;
+
+ // init filesystem view
+ $this->view = new \OC_FilesystemView('/');
+
+ // init short data
+ $this->dataShort = 'hats';
+
+ $this->folder1 = '/folder1';
+ $this->subfolder = '/subfolder1';
+ $this->subsubfolder = '/subsubfolder1';
+
+ // remember files_trashbin state
+ $this->stateFilesTrashbin = OC_App::isEnabled('files_trashbin');
+
+ // we want to tests with app files_trashbin enabled
+ \OC_App::enable('files_trashbin');
+ }
+
+ function tearDown() {
+ // reset app files_trashbin
+ if ($this->stateFilesTrashbin) {
+ OC_App::enable('files_trashbin');
+ }
+ else {
+ OC_App::disable('files_trashbin');
+ }
+ }
+
+ public static function tearDownAfterClass() {
+ // cleanup test user
+ \OC_User::deleteUser(\Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1);
+ }
+
+ /**
+ * @brief test delete file
+ */
+ function testDeleteFile() {
+
+ // generate filename
+ $filename = 'tmp-' . time() . '.txt';
+
+ // save file with content
+ $cryptedFile = file_put_contents('crypt:///' . $filename, $this->dataShort);
+
+ // test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ // check if key for admin exists
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/' . $filename
+ . '.key'));
+
+ // check if share key for admin exists
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/'
+ . $filename . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey'));
+
+ // delete file
+ \OC\FIles\Filesystem::unlink($filename);
+
+ // check if file not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files/' . $filename));
+
+ // check if key for admin not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/' . $filename
+ . '.key'));
+
+ // check if share key for admin not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/'
+ . $filename . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey'));
+
+ // get files
+ $trashFiles = $this->view->getDirectoryContent(
+ '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/files/');
+
+ $trashFileSuffix = null;
+ // find created file with timestamp
+ foreach ($trashFiles as $file) {
+ if (strncmp($file['path'], $filename, strlen($filename))) {
+ $path_parts = pathinfo($file['name']);
+ $trashFileSuffix = $path_parts['extension'];
+ }
+ }
+
+ // check if we found the file we created
+ $this->assertNotNull($trashFileSuffix);
+
+ // check if key for admin not exists
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/keyfiles/' . $filename
+ . '.key.' . $trashFileSuffix));
+
+ // check if share key for admin not exists
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/share-keys/' . $filename
+ . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey.' . $trashFileSuffix));
+
+ // return filename for next test
+ return $filename . '.' . $trashFileSuffix;
+ }
+
+ /**
+ * @brief test restore file
+ *
+ * @depends testDeleteFile
+ */
+ function testRestoreFile($filename) {
+
+ // prepare file information
+ $path_parts = pathinfo($filename);
+ $trashFileSuffix = $path_parts['extension'];
+ $timestamp = str_replace('d', '', $trashFileSuffix);
+ $fileNameWithoutSuffix = str_replace('.' . $trashFileSuffix, '', $filename);
+
+ // restore file
+ $this->assertTrue(\OCA\Files_Trashbin\Trashbin::restore($filename, $fileNameWithoutSuffix, $timestamp));
+
+ // check if file exists
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files/' . $fileNameWithoutSuffix));
+
+ // check if key for admin exists
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/'
+ . $fileNameWithoutSuffix . '.key'));
+
+ // check if share key for admin exists
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/'
+ . $fileNameWithoutSuffix . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey'));
+ }
+
+ /**
+ * @brief test delete file forever
+ */
+ function testPermanentDeleteFile() {
+
+ // generate filename
+ $filename = 'tmp-' . time() . '.txt';
+
+ // save file with content
+ $cryptedFile = file_put_contents('crypt:///' . $filename, $this->dataShort);
+
+ // test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ // check if key for admin exists
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/' . $filename
+ . '.key'));
+
+ // check if share key for admin exists
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/'
+ . $filename . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey'));
+
+ // delete file
+ \OC\FIles\Filesystem::unlink($filename);
+
+ // check if file not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files/' . $filename));
+
+ // check if key for admin not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/' . $filename
+ . '.key'));
+
+ // check if share key for admin not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/'
+ . $filename . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey'));
+
+ // find created file with timestamp
+ $query = \OC_DB::prepare('SELECT `timestamp`,`type` FROM `*PREFIX*files_trash`'
+ . ' WHERE `id`=?');
+ $result = $query->execute(array($filename))->fetchRow();
+
+ $this->assertTrue(is_array($result));
+
+ // build suffix
+ $trashFileSuffix = 'd' . $result['timestamp'];
+
+ // check if key for admin exists
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/keyfiles/' . $filename
+ . '.key.' . $trashFileSuffix));
+
+ // check if share key for admin exists
+ $this->assertTrue($this->view->file_exists(
+ '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/share-keys/' . $filename
+ . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey.' . $trashFileSuffix));
+
+ // get timestamp from file
+ $timestamp = str_replace('d', '', $trashFileSuffix);
+
+ // delete file forever
+ $this->assertGreaterThan(0, \OCA\Files_Trashbin\Trashbin::delete($filename, $timestamp));
+
+ // check if key for admin not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/files/' . $filename . '.'
+ . $trashFileSuffix));
+
+ // check if key for admin not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/keyfiles/' . $filename
+ . '.key.' . $trashFileSuffix));
+
+ // check if share key for admin not exists
+ $this->assertFalse($this->view->file_exists(
+ '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/share-keys/' . $filename
+ . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey.' . $trashFileSuffix));
+ }
+
+} \ No newline at end of file
diff --git a/apps/files_encryption/tests/util.php b/apps/files_encryption/tests/util.php
new file mode 100755
index 00000000000..0dc452a41c8
--- /dev/null
+++ b/apps/files_encryption/tests/util.php
@@ -0,0 +1,317 @@
+<?php
+/**
+ * Copyright (c) 2012 Sam Tuke <samtuke@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+require_once realpath(dirname(__FILE__) . '/../../../lib/base.php');
+require_once realpath(dirname(__FILE__) . '/../lib/crypt.php');
+require_once realpath(dirname(__FILE__) . '/../lib/keymanager.php');
+require_once realpath(dirname(__FILE__) . '/../lib/proxy.php');
+require_once realpath(dirname(__FILE__) . '/../lib/stream.php');
+require_once realpath(dirname(__FILE__) . '/../lib/util.php');
+require_once realpath(dirname(__FILE__) . '/../appinfo/app.php');
+
+use OCA\Encryption;
+
+/**
+ * Class Test_Encryption_Util
+ */
+class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
+
+ const TEST_ENCRYPTION_UTIL_USER1 = "test-util-user1";
+ const TEST_ENCRYPTION_UTIL_LEGACY_USER = "test-legacy-user";
+
+ public $userId;
+ public $encryptionDir;
+ public $publicKeyDir;
+ public $pass;
+ /**
+ * @var OC_FilesystemView
+ */
+ public $view;
+ public $keyfilesPath;
+ public $publicKeyPath;
+ public $privateKeyPath;
+ /**
+ * @var \OCA\Encryption\Util
+ */
+ public $util;
+ public $dataShort;
+ public $legacyEncryptedData;
+ public $legacyEncryptedDataKey;
+ public $legacyKey;
+ public $stateFilesTrashbin;
+
+ public static function setUpBeforeClass() {
+ // reset backend
+ \OC_User::clearBackends();
+ \OC_User::useBackend('database');
+
+ // Filesystem related hooks
+ \OCA\Encryption\Helper::registerFilesystemHooks();
+
+ // clear and register hooks
+ \OC_FileProxy::clearProxies();
+ \OC_FileProxy::register(new OCA\Encryption\Proxy());
+
+ // create test user
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1, true);
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER, true);
+ }
+
+
+ function setUp() {
+ \OC_User::setUserId(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1);
+ $this->userId = \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1;
+ $this->pass = \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1;
+
+ // set content for encrypting / decrypting in tests
+ $this->dataUrl = realpath(dirname(__FILE__) . '/../lib/crypt.php');
+ $this->dataShort = 'hats';
+ $this->dataLong = file_get_contents(realpath(dirname(__FILE__) . '/../lib/crypt.php'));
+ $this->legacyData = realpath(dirname(__FILE__) . '/legacy-text.txt');
+ $this->legacyEncryptedData = realpath(dirname(__FILE__) . '/legacy-encrypted-text.txt');
+ $this->legacyEncryptedDataKey = realpath(dirname(__FILE__) . '/encryption.key');
+ $this->legacyKey = '30943623843030686906';
+
+ $keypair = Encryption\Crypt::createKeypair();
+
+ $this->genPublicKey = $keypair['publicKey'];
+ $this->genPrivateKey = $keypair['privateKey'];
+
+ $this->publicKeyDir = '/' . 'public-keys';
+ $this->encryptionDir = '/' . $this->userId . '/' . 'files_encryption';
+ $this->keyfilesPath = $this->encryptionDir . '/' . 'keyfiles';
+ $this->publicKeyPath =
+ $this->publicKeyDir . '/' . $this->userId . '.public.key'; // e.g. data/public-keys/admin.public.key
+ $this->privateKeyPath =
+ $this->encryptionDir . '/' . $this->userId . '.private.key'; // e.g. data/admin/admin.private.key
+
+ $this->view = new \OC_FilesystemView('/');
+
+ $this->util = new Encryption\Util($this->view, $this->userId);
+
+ // 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');
+ }
+
+ function tearDown() {
+ // reset app files_trashbin
+ if ($this->stateFilesTrashbin) {
+ OC_App::enable('files_trashbin');
+ }
+ else {
+ OC_App::disable('files_trashbin');
+ }
+ }
+
+ public static function tearDownAfterClass() {
+ // cleanup test user
+ \OC_User::deleteUser(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1);
+ \OC_User::deleteUser(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER);
+ }
+
+ /**
+ * @brief test that paths set during User construction are correct
+ */
+ function testKeyPaths() {
+ $util = new Encryption\Util($this->view, $this->userId);
+
+ $this->assertEquals($this->publicKeyDir, $util->getPath('publicKeyDir'));
+ $this->assertEquals($this->encryptionDir, $util->getPath('encryptionDir'));
+ $this->assertEquals($this->keyfilesPath, $util->getPath('keyfilesPath'));
+ $this->assertEquals($this->publicKeyPath, $util->getPath('publicKeyPath'));
+ $this->assertEquals($this->privateKeyPath, $util->getPath('privateKeyPath'));
+
+ }
+
+ /**
+ * @brief test setup of encryption directories
+ */
+ function testSetupServerSide() {
+ $this->assertEquals(true, $this->util->setupServerSide($this->pass));
+ }
+
+ /**
+ * @brief test checking whether account is ready for encryption,
+ */
+ function testUserIsReady() {
+ $this->assertEquals(true, $this->util->ready());
+ }
+
+ /**
+ * @brief test checking whether account is not ready for encryption,
+ */
+// function testUserIsNotReady() {
+// $this->view->unlink($this->publicKeyDir);
+//
+// $params['uid'] = $this->userId;
+// $params['password'] = $this->pass;
+// $this->assertFalse(OCA\Encryption\Hooks::login($params));
+//
+// $this->view->unlink($this->privateKeyPath);
+// }
+
+ /**
+ * @brief test checking whether account is not ready for encryption,
+ */
+ function testIsLegacyUser() {
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER);
+
+ $userView = new \OC_FilesystemView('/' . \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER);
+
+ // Disable encryption proxy to prevent recursive calls
+ $proxyStatus = \OC_FileProxy::$enabled;
+ \OC_FileProxy::$enabled = false;
+
+ $encryptionKeyContent = file_get_contents($this->legacyEncryptedDataKey);
+ $userView->file_put_contents('/encryption.key', $encryptionKeyContent);
+
+ \OC_FileProxy::$enabled = $proxyStatus;
+
+ $params['uid'] = \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER;
+ $params['password'] = \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER;
+
+ $util = new Encryption\Util($this->view, \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER);
+ $util->setMigrationStatus(0);
+
+ $this->assertTrue(OCA\Encryption\Hooks::login($params));
+
+ $this->assertEquals($this->legacyKey, \OC::$session->get('legacyKey'));
+ }
+
+ function testRecoveryEnabledForUser() {
+
+ $util = new Encryption\Util($this->view, $this->userId);
+
+ // Record the value so we can return it to it's original state later
+ $enabled = $util->recoveryEnabledForUser();
+
+ $this->assertTrue($util->setRecoveryForUser(1));
+
+ $this->assertEquals(1, $util->recoveryEnabledForUser());
+
+ $this->assertTrue($util->setRecoveryForUser(0));
+
+ $this->assertEquals(0, $util->recoveryEnabledForUser());
+
+ // Return the setting to it's previous state
+ $this->assertTrue($util->setRecoveryForUser($enabled));
+
+ }
+
+ function testGetUidAndFilename() {
+
+ \OC_User::setUserId(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1);
+
+ $filename = 'tmp-' . time() . '.test';
+
+ // Disable encryption proxy to prevent recursive calls
+ $proxyStatus = \OC_FileProxy::$enabled;
+ \OC_FileProxy::$enabled = false;
+
+ $this->view->file_put_contents($this->userId . '/files/' . $filename, $this->dataShort);
+
+ // Re-enable proxy - our work is done
+ \OC_FileProxy::$enabled = $proxyStatus;
+
+ $util = new Encryption\Util($this->view, $this->userId);
+
+ list($fileOwnerUid, $file) = $util->getUidAndFilename($filename);
+
+ $this->assertEquals(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1, $fileOwnerUid);
+
+ $this->assertEquals($file, $filename);
+
+ $this->view->unlink($this->userId . '/files/' . $filename);
+ }
+
+ function testIsSharedPath() {
+ $sharedPath = '/user1/files/Shared/test';
+ $path = '/user1/files/test';
+
+ $this->assertTrue($this->util->isSharedPath($sharedPath));
+
+ $this->assertFalse($this->util->isSharedPath($path));
+ }
+
+ function testEncryptLegacyFiles() {
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER);
+
+ $userView = new \OC_FilesystemView('/' . \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER);
+ $view = new \OC_FilesystemView('/' . \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER . '/files');
+
+ // Disable encryption proxy to prevent recursive calls
+ $proxyStatus = \OC_FileProxy::$enabled;
+ \OC_FileProxy::$enabled = false;
+
+ $encryptionKeyContent = file_get_contents($this->legacyEncryptedDataKey);
+ $userView->file_put_contents('/encryption.key', $encryptionKeyContent);
+
+ $legacyEncryptedData = file_get_contents($this->legacyEncryptedData);
+ $view->mkdir('/test/');
+ $view->mkdir('/test/subtest/');
+ $view->file_put_contents('/test/subtest/legacy-encrypted-text.txt', $legacyEncryptedData);
+
+ $fileInfo = $view->getFileInfo('/test/subtest/legacy-encrypted-text.txt');
+ $fileInfo['encrypted'] = true;
+ $view->putFileInfo('/test/subtest/legacy-encrypted-text.txt', $fileInfo);
+
+ \OC_FileProxy::$enabled = $proxyStatus;
+
+ $params['uid'] = \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER;
+ $params['password'] = \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER;
+
+ $util = new Encryption\Util($this->view, \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER);
+ $util->setMigrationStatus(0);
+
+ $this->assertTrue(OCA\Encryption\Hooks::login($params));
+
+ $this->assertEquals($this->legacyKey, \OC::$session->get('legacyKey'));
+
+ $files = $util->findEncFiles('/' . \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER . '/files/');
+
+ $this->assertTrue(is_array($files));
+
+ $found = false;
+ foreach ($files['encrypted'] as $encryptedFile) {
+ if ($encryptedFile['name'] === 'legacy-encrypted-text.txt') {
+ $found = true;
+ break;
+ }
+ }
+
+ $this->assertTrue($found);
+ }
+
+ /**
+ * @param $user
+ * @param bool $create
+ * @param bool $password
+ */
+ public static 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();
+ \OC_Util::setupFS($user);
+ \OC_User::setUserId($user);
+
+ $params['uid'] = $user;
+ $params['password'] = $password;
+ OCA\Encryption\Hooks::login($params);
+ }
+}
diff --git a/apps/files_encryption/tests/webdav.php b/apps/files_encryption/tests/webdav.php
new file mode 100755
index 00000000000..1d406789f0c
--- /dev/null
+++ b/apps/files_encryption/tests/webdav.php
@@ -0,0 +1,262 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Florin Peter
+ * @copyright 2013 Florin Peter <owncloud@florin-peter.de>
+ *
+ * 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/>.
+ *
+ */
+
+require_once realpath(dirname(__FILE__) . '/../../../lib/base.php');
+require_once realpath(dirname(__FILE__) . '/../lib/crypt.php');
+require_once realpath(dirname(__FILE__) . '/../lib/keymanager.php');
+require_once realpath(dirname(__FILE__) . '/../lib/proxy.php');
+require_once realpath(dirname(__FILE__) . '/../lib/stream.php');
+require_once realpath(dirname(__FILE__) . '/../lib/util.php');
+require_once realpath(dirname(__FILE__) . '/../appinfo/app.php');
+require_once realpath(dirname(__FILE__) . '/util.php');
+
+use OCA\Encryption;
+
+/**
+ * Class Test_Encryption_Webdav
+ * @brief this class provide basic webdav tests for PUT,GET and DELETE
+ */
+class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase {
+
+ const TEST_ENCRYPTION_WEBDAV_USER1 = "test-webdav-user1";
+
+ public $userId;
+ public $pass;
+ /**
+ * @var \OC_FilesystemView
+ */
+ public $view;
+ public $dataShort;
+ public $stateFilesTrashbin;
+
+ public static function setUpBeforeClass() {
+ // reset backend
+ \OC_User::clearBackends();
+ \OC_User::useBackend('database');
+
+ // Filesystem related hooks
+ \OCA\Encryption\Helper::registerFilesystemHooks();
+
+ // Filesystem related hooks
+ \OCA\Encryption\Helper::registerUserHooks();
+
+ // clear and register hooks
+ \OC_FileProxy::clearProxies();
+ \OC_FileProxy::register(new OCA\Encryption\Proxy());
+
+ // create test user
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Webdav::TEST_ENCRYPTION_WEBDAV_USER1, true);
+ }
+
+ function setUp() {
+ // reset backend
+ \OC_User::useBackend('database');
+
+ // set user id
+ \OC_User::setUserId(\Test_Encryption_Webdav::TEST_ENCRYPTION_WEBDAV_USER1);
+ $this->userId = \Test_Encryption_Webdav::TEST_ENCRYPTION_WEBDAV_USER1;
+ $this->pass = \Test_Encryption_Webdav::TEST_ENCRYPTION_WEBDAV_USER1;
+
+ // init filesystem view
+ $this->view = new \OC_FilesystemView('/');
+
+ // init short data
+ $this->dataShort = 'hats';
+
+ // 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');
+
+ // create test user
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Webdav::TEST_ENCRYPTION_WEBDAV_USER1);
+ }
+
+ function tearDown() {
+ // reset app files_trashbin
+ if ($this->stateFilesTrashbin) {
+ OC_App::enable('files_trashbin');
+ }
+ else {
+ OC_App::disable('files_trashbin');
+ }
+ }
+
+ public static function tearDownAfterClass() {
+ // cleanup test user
+ \OC_User::deleteUser(\Test_Encryption_Webdav::TEST_ENCRYPTION_WEBDAV_USER1);
+ }
+
+ /**
+ * @brief test webdav put random file
+ */
+ function testWebdavPUT() {
+
+ // generate filename
+ $filename = '/tmp-' . time() . '.txt';
+
+ // set server vars
+ $_SERVER['REQUEST_METHOD'] = 'OPTIONS';
+
+ $_SERVER['REQUEST_METHOD'] = 'PUT';
+ $_SERVER['REQUEST_URI'] = '/remote.php/webdav' . $filename;
+ $_SERVER['HTTP_AUTHORIZATION'] = 'Basic dGVzdC13ZWJkYXYtdXNlcjE6dGVzdC13ZWJkYXYtdXNlcjE=';
+ $_SERVER['CONTENT_TYPE'] = 'application/octet-stream';
+ $_SERVER['PATH_INFO'] = '/webdav' . $filename;
+ $_SERVER['CONTENT_LENGTH'] = strlen($this->dataShort);
+
+ // handle webdav request
+ $this->handleWebdavRequest($this->dataShort);
+
+ // check if file was created
+ $this->assertTrue($this->view->file_exists('/' . $this->userId . '/files' . $filename));
+
+ // check if key-file was created
+ $this->assertTrue($this->view->file_exists(
+ '/' . $this->userId . '/files_encryption/keyfiles/' . $filename . '.key'));
+
+ // check if shareKey-file was created
+ $this->assertTrue($this->view->file_exists(
+ '/' . $this->userId . '/files_encryption/share-keys/' . $filename . '.' . $this->userId . '.shareKey'));
+
+ // disable encryption proxy to prevent recursive calls
+ $proxyStatus = \OC_FileProxy::$enabled;
+ \OC_FileProxy::$enabled = false;
+
+ // get encrypted file content
+ $encryptedContent = $this->view->file_get_contents('/' . $this->userId . '/files' . $filename);
+
+ // restore proxy state
+ \OC_FileProxy::$enabled = $proxyStatus;
+
+ // check if encrypted content is valid
+ $this->assertTrue(Encryption\Crypt::isCatfileContent($encryptedContent));
+
+ // get decrypted file contents
+ $decrypt = file_get_contents('crypt://' . $filename);
+
+ // check if file content match with the written content
+ $this->assertEquals($this->dataShort, $decrypt);
+
+ // return filename for next test
+ return $filename;
+ }
+
+ /**
+ * @brief test webdav get random file
+ *
+ * @depends testWebdavPUT
+ */
+ function testWebdavGET($filename) {
+
+ // set server vars
+ $_SERVER['REQUEST_METHOD'] = 'GET';
+ $_SERVER['REQUEST_URI'] = '/remote.php/webdav' . $filename;
+ $_SERVER['HTTP_AUTHORIZATION'] = 'Basic dGVzdC13ZWJkYXYtdXNlcjE6dGVzdC13ZWJkYXYtdXNlcjE=';
+ $_SERVER['PATH_INFO'] = '/webdav' . $filename;
+
+ // handle webdav request
+ $content = $this->handleWebdavRequest();
+
+ // check if file content match with the written content
+ $this->assertEquals($this->dataShort, $content);
+
+ // return filename for next test
+ return $filename;
+ }
+
+ /**
+ * @brief test webdav delete random file
+ * @depends testWebdavGET
+ */
+ function testWebdavDELETE($filename) {
+ // set server vars
+ $_SERVER['REQUEST_METHOD'] = 'DELETE';
+ $_SERVER['REQUEST_URI'] = '/remote.php/webdav' . $filename;
+ $_SERVER['HTTP_AUTHORIZATION'] = 'Basic dGVzdC13ZWJkYXYtdXNlcjE6dGVzdC13ZWJkYXYtdXNlcjE=';
+ $_SERVER['PATH_INFO'] = '/webdav' . $filename;
+
+ // handle webdav request
+ $content = $this->handleWebdavRequest();
+
+ // check if file was removed
+ $this->assertFalse($this->view->file_exists('/' . $this->userId . '/files' . $filename));
+
+ // check if key-file was removed
+ $this->assertFalse($this->view->file_exists(
+ '/' . $this->userId . '/files_encryption/keyfiles' . $filename . '.key'));
+
+ // check if shareKey-file was removed
+ $this->assertFalse($this->view->file_exists(
+ '/' . $this->userId . '/files_encryption/share-keys' . $filename . '.' . $this->userId . '.shareKey'));
+ }
+
+ /**
+ * @brief handle webdav request
+ *
+ * @param bool $body
+ *
+ * @note this init procedure is copied from /apps/files/appinfo/remote.php
+ */
+ function handleWebdavRequest($body = false) {
+ // Backends
+ $authBackend = new OC_Connector_Sabre_Auth();
+ $lockBackend = new OC_Connector_Sabre_Locks();
+ $requestBackend = new OC_Connector_Sabre_Request();
+
+ // Create ownCloud Dir
+ $publicDir = new OC_Connector_Sabre_Directory('');
+
+ // Fire up server
+ $server = new Sabre_DAV_Server($publicDir);
+ $server->httpRequest = $requestBackend;
+ $server->setBaseUri('/remote.php/webdav/');
+
+ // Load plugins
+ $server->addPlugin(new Sabre_DAV_Auth_Plugin($authBackend, 'ownCloud'));
+ $server->addPlugin(new Sabre_DAV_Locks_Plugin($lockBackend));
+ $server->addPlugin(new Sabre_DAV_Browser_Plugin(false)); // Show something in the Browser, but no upload
+ $server->addPlugin(new OC_Connector_Sabre_QuotaPlugin());
+ $server->addPlugin(new OC_Connector_Sabre_MaintenancePlugin());
+
+ // And off we go!
+ if ($body) {
+ $server->httpRequest->setBody($body);
+ }
+
+ // turn on output buffering
+ ob_start();
+
+ // handle request
+ $server->exec();
+
+ // file content is written in the output buffer
+ $content = ob_get_contents();
+
+ // flush the output buffer and turn off output buffering
+ ob_end_clean();
+
+ // return captured content
+ return $content;
+ }
+} \ No newline at end of file
diff --git a/apps/files_encryption/tests/zeros b/apps/files_encryption/tests/zeros
new file mode 100644
index 00000000000..ff982acf423
--- /dev/null
+++ b/apps/files_encryption/tests/zeros
Binary files differ