public function testSinglePropagate() { $this->view->mkdir('/foo'); $this->view->mkdir('/foo/bar'); $this->view->file_put_contents('/foo/bar/sad.txt', 'qwerty'); $oldInfo1 = $this->view->getFileInfo('/'); $oldInfo2 = $this->view->getFileInfo('/foo'); $oldInfo3 = $this->view->getFileInfo('/foo/bar'); $time = time() + 50; $this->propagator->addChange('/foo/bar/sad.txt'); $this->propagator->propagateChanges($time); $newInfo1 = $this->view->getFileInfo('/'); $newInfo2 = $this->view->getFileInfo('/foo'); $newInfo3 = $this->view->getFileInfo('/foo/bar'); $this->assertEquals($newInfo1->getMTime(), $time); $this->assertEquals($newInfo2->getMTime(), $time); $this->assertEquals($newInfo3->getMTime(), $time); $this->assertNotSame($oldInfo1->getEtag(), $newInfo1->getEtag()); $this->assertNotSame($oldInfo2->getEtag(), $newInfo2->getEtag()); $this->assertNotSame($oldInfo3->getEtag(), $newInfo3->getEtag()); }
/** * "user1" is the admin who shares a folder "sub1/sub2/folder" with "user2" and "user3" * "user2" receives the folder and puts it in "sub1/sub2/folder" * "user3" receives the folder and puts it in "sub1/sub2/folder" * "user2" reshares the subdir "sub1/sub2/folder/inside" with "user4" * "user4" puts the received "inside" folder into "sub1/sub2/inside" (this is to check if it propagates across multiple subfolders) */ private function setUpShares() { $this->fileIds[self::TEST_FILES_SHARING_API_USER1] = []; $this->fileIds[self::TEST_FILES_SHARING_API_USER2] = []; $this->fileIds[self::TEST_FILES_SHARING_API_USER3] = []; $this->fileIds[self::TEST_FILES_SHARING_API_USER4] = []; $this->rootView = new View(''); $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); $view1 = new View('/' . self::TEST_FILES_SHARING_API_USER1 . '/files'); $view1->mkdir('/sub1/sub2/folder/inside'); $view1->mkdir('/directReshare'); $view1->mkdir('/sub1/sub2/folder/other'); $view1->mkdir('/sub1/sub2/folder/other'); $view1->file_put_contents('/foo.txt', 'foobar'); $view1->file_put_contents('/sub1/sub2/folder/file.txt', 'foobar'); $view1->file_put_contents('/sub1/sub2/folder/inside/file.txt', 'foobar'); $folderInfo = $view1->getFileInfo('/sub1/sub2/folder'); $fileInfo = $view1->getFileInfo('/foo.txt'); \OCP\Share::shareItem('file', $fileInfo->getId(), \OCP\Share::SHARE_TYPE_USER, self::TEST_FILES_SHARING_API_USER2, 31); \OCP\Share::shareItem('folder', $folderInfo->getId(), \OCP\Share::SHARE_TYPE_USER, self::TEST_FILES_SHARING_API_USER2, 31); \OCP\Share::shareItem('folder', $folderInfo->getId(), \OCP\Share::SHARE_TYPE_USER, self::TEST_FILES_SHARING_API_USER3, 31); $folderInfo = $view1->getFileInfo('/directReshare'); \OCP\Share::shareItem('folder', $folderInfo->getId(), \OCP\Share::SHARE_TYPE_USER, self::TEST_FILES_SHARING_API_USER2, 31); $this->fileIds[self::TEST_FILES_SHARING_API_USER1][''] = $view1->getFileInfo('')->getId(); $this->fileIds[self::TEST_FILES_SHARING_API_USER1]['sub1'] = $view1->getFileInfo('sub1')->getId(); $this->fileIds[self::TEST_FILES_SHARING_API_USER1]['sub1/sub2'] = $view1->getFileInfo('sub1/sub2')->getId(); $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); $view2 = new View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); $view2->mkdir('/sub1/sub2'); $view2->rename('/folder', '/sub1/sub2/folder'); $insideInfo = $view2->getFileInfo('/sub1/sub2/folder/inside'); \OCP\Share::shareItem('folder', $insideInfo->getId(), \OCP\Share::SHARE_TYPE_USER, self::TEST_FILES_SHARING_API_USER4, 31); $folderInfo = $view2->getFileInfo('/directReshare'); \OCP\Share::shareItem('folder', $folderInfo->getId(), \OCP\Share::SHARE_TYPE_USER, self::TEST_FILES_SHARING_API_USER4, 31); $this->fileIds[self::TEST_FILES_SHARING_API_USER2][''] = $view2->getFileInfo('')->getId(); $this->fileIds[self::TEST_FILES_SHARING_API_USER2]['sub1'] = $view2->getFileInfo('sub1')->getId(); $this->fileIds[self::TEST_FILES_SHARING_API_USER2]['sub1/sub2'] = $view2->getFileInfo('sub1/sub2')->getId(); $this->loginAsUser(self::TEST_FILES_SHARING_API_USER3); $view3 = new View('/' . self::TEST_FILES_SHARING_API_USER3 . '/files'); $view3->mkdir('/sub1/sub2'); $view3->rename('/folder', '/sub1/sub2/folder'); $this->fileIds[self::TEST_FILES_SHARING_API_USER3][''] = $view3->getFileInfo('')->getId(); $this->fileIds[self::TEST_FILES_SHARING_API_USER3]['sub1'] = $view3->getFileInfo('sub1')->getId(); $this->fileIds[self::TEST_FILES_SHARING_API_USER3]['sub1/sub2'] = $view3->getFileInfo('sub1/sub2')->getId(); $this->loginAsUser(self::TEST_FILES_SHARING_API_USER4); $view4 = new View('/' . self::TEST_FILES_SHARING_API_USER4 . '/files'); $view4->mkdir('/sub1/sub2'); $view4->rename('/inside', '/sub1/sub2/inside'); $this->fileIds[self::TEST_FILES_SHARING_API_USER4][''] = $view4->getFileInfo('')->getId(); $this->fileIds[self::TEST_FILES_SHARING_API_USER4]['sub1'] = $view4->getFileInfo('sub1')->getId(); $this->fileIds[self::TEST_FILES_SHARING_API_USER4]['sub1/sub2'] = $view4->getFileInfo('sub1/sub2')->getId(); foreach ($this->fileIds as $user => $ids) { $this->loginAsUser($user); foreach ($ids as $id) { $path = $this->rootView->getPath($id); $this->fileEtags[$id] = $this->rootView->getFileInfo($path)->getEtag(); } } }
public function testUpdatedFile() { $this->view->file_put_contents('/foo.txt', 'bar'); $cached = $this->cache->get('foo.txt'); $this->assertEquals(3, $cached['size']); $this->assertEquals('text/plain', $cached['mimetype']); $this->storage->file_put_contents('foo.txt', 'qwerty'); $cached = $this->cache->get('foo.txt'); $this->assertEquals(3, $cached['size']); $this->updater->update('/foo.txt'); $cached = $this->cache->get('foo.txt'); $this->assertEquals(6, $cached['size']); }
private function doTestRestore() { $filePath = self::TEST_VERSIONS_USER . '/files/sub/test.txt'; $this->rootView->file_put_contents($filePath, 'test file'); $t0 = $this->rootView->filemtime($filePath); // not exactly the same timestamp as the file $t1 = time() - 60; // second version is two weeks older $t2 = $t1 - 60 * 60 * 24 * 14; // create some versions $v1 = self::USERS_VERSIONS_ROOT . '/sub/test.txt.v' . $t1; $v2 = self::USERS_VERSIONS_ROOT . '/sub/test.txt.v' . $t2; $this->rootView->mkdir(self::USERS_VERSIONS_ROOT . '/sub'); $this->rootView->file_put_contents($v1, 'version1'); $this->rootView->file_put_contents($v2, 'version2'); $oldVersions = \OCA\Files_Versions\Storage::getVersions(self::TEST_VERSIONS_USER, '/sub/test.txt'); $this->assertCount(2, $oldVersions); $this->assertEquals('test file', $this->rootView->file_get_contents($filePath)); $info1 = $this->rootView->getFileInfo($filePath); \OCA\Files_Versions\Storage::rollback('sub/test.txt', $t2); $this->assertEquals('version2', $this->rootView->file_get_contents($filePath)); $info2 = $this->rootView->getFileInfo($filePath); $this->assertNotEquals($info2['etag'], $info1['etag'], 'Etag must change after rolling back version'); $this->assertEquals($info2['fileid'], $info1['fileid'], 'File id must not change after rolling back version'); $this->assertEquals($info2['mtime'], $t2, 'Restored file has mtime from version'); $newVersions = \OCA\Files_Versions\Storage::getVersions(self::TEST_VERSIONS_USER, '/sub/test.txt'); $this->assertTrue($this->rootView->file_exists(self::USERS_VERSIONS_ROOT . '/sub/test.txt.v' . $t0), 'A version file was created for the file before restoration'); $this->assertTrue($this->rootView->file_exists($v1), 'Untouched version file is still there'); $this->assertFalse($this->rootView->file_exists($v2), 'Restored version file gone from files_version folder'); $this->assertCount(2, $newVersions, 'Additional version created'); $this->assertTrue(isset($newVersions[$t0 . '#' . 'test.txt']), 'A version was created for the file before restoration'); $this->assertTrue(isset($newVersions[$t1 . '#' . 'test.txt']), 'Untouched version is still there'); $this->assertFalse(isset($newVersions[$t2 . '#' . 'test.txt']), 'Restored version is not in the list any more'); }
public function testPropagateCrossStorage() { $storage = new Temporary(); $this->view->mkdir('/foo'); Filesystem::mount($storage, [], $this->view->getAbsolutePath('/foo/submount')); $this->view->mkdir('/foo/submount/bar'); $this->view->file_put_contents('/foo/submount/bar/sad.txt', 'qwerty'); $oldInfo1 = $this->view->getFileInfo('/'); $oldInfo2 = $this->view->getFileInfo('/foo'); $oldInfo3 = $this->view->getFileInfo('/foo/submount'); $oldInfo4 = $this->view->getFileInfo('/foo/submount/bar'); $time = time() + 50; $this->propagator->addChange('/foo/submount/bar/sad.txt'); $this->propagator->propagateChanges($time); $newInfo1 = $this->view->getFileInfo('/'); $newInfo2 = $this->view->getFileInfo('/foo'); $newInfo3 = $this->view->getFileInfo('/foo/submount'); $newInfo4 = $this->view->getFileInfo('/foo/submount/bar'); $this->assertEquals($newInfo1->getMTime(), $time); $this->assertEquals($newInfo2->getMTime(), $time); $this->assertEquals($newInfo3->getMTime(), $time); $this->assertEquals($newInfo4->getMTime(), $time); $this->assertNotSame($oldInfo1->getEtag(), $newInfo1->getEtag()); $this->assertNotSame($oldInfo2->getEtag(), $newInfo2->getEtag()); $this->assertNotSame($oldInfo3->getEtag(), $newInfo3->getEtag()); $this->assertNotSame($oldInfo4->getEtag(), $newInfo3->getEtag()); }
/** * @medium * Test that data that is written by the crypto stream wrapper with AES 128 * @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 */ public function testStreamDecryptLongFileContentWithoutHeader() { // Generate a a random filename $filename = 'tmp-' . $this->getUniqueID() . '.test'; $this->config->setSystemValue('cipher', 'AES-128-CFB'); // Save long data as encrypted file using stream wrapper $cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/' . $filename, $this->dataLong . $this->dataLong); $this->config->deleteSystemValue('cipher'); // 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); // Check that the file was encrypted before being written to disk $this->assertNotEquals($this->dataLong . $this->dataLong, $retreivedCryptedFile); // remove the header to check if we can also decrypt old files without a header, // this files should fall back to AES-128 $cryptedWithoutHeader = substr($retreivedCryptedFile, \OCA\Files_Encryption\Crypt::BLOCKSIZE); $this->view->file_put_contents($this->userId . '/files/' . $filename, $cryptedWithoutHeader); // Re-enable proxy - our work is done \OC_FileProxy::$enabled = $proxyStatus; $decrypted = file_get_contents('crypt:///' . $this->userId . '/files/' . $filename); $this->assertEquals($this->dataLong . $this->dataLong, $decrypted); // Teardown $this->view->unlink($this->userId . '/files/' . $filename); }
/** * @medium * test if stream wrapper can read files outside from the data folder */ function testStreamFromLocalFile() { $filename = '/' . $this->userId . '/files/' . 'tmp-' . $this->getUniqueID() . '.txt'; $tmpFilename = "/tmp/" . $this->getUniqueID() . ".txt"; // write an encrypted file $cryptedFile = $this->view->file_put_contents($filename, $this->dataShort); // Test that data was successfully written $this->assertTrue(is_int($cryptedFile)); // create a copy outside of the data folder in /tmp $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; $encryptedContent = $this->view->file_get_contents($filename); \OC_FileProxy::$enabled = $proxyStatus; file_put_contents($tmpFilename, $encryptedContent); \OCA\Files_Encryption\Helper::addTmpFileToMapper($tmpFilename, $filename); // try to read the file from /tmp $handle = fopen("crypt://" . $tmpFilename, "r"); $contentFromTmpFile = stream_get_contents($handle); // check if it was successful $this->assertEquals($this->dataShort, $contentFromTmpFile); fclose($handle); // clean up unlink($tmpFilename); $this->view->unlink($filename); }
public function testSizePropagationWhenRecipientChangesFile() { $this->loginHelper(self::TEST_FILES_SHARING_API_USER1); $recipientView = new View('/' . self::TEST_FILES_SHARING_API_USER1 . '/files'); $this->loginHelper(self::TEST_FILES_SHARING_API_USER2); $ownerView = new View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); $ownerView->mkdir('/sharedfolder/subfolder'); $ownerView->file_put_contents('/sharedfolder/subfolder/foo.txt', 'bar'); $sharedFolderInfo = $ownerView->getFileInfo('/sharedfolder', false); $this->assertInstanceOf('\\OC\\Files\\FileInfo', $sharedFolderInfo); \OCP\Share::shareItem('folder', $sharedFolderInfo->getId(), \OCP\Share::SHARE_TYPE_USER, self::TEST_FILES_SHARING_API_USER1, 31); $ownerRootInfo = $ownerView->getFileInfo('', false); $this->loginHelper(self::TEST_FILES_SHARING_API_USER1); $this->assertTrue($recipientView->file_exists('/sharedfolder/subfolder/foo.txt')); $recipientRootInfo = $recipientView->getFileInfo('', false); // when file changed as recipient $recipientView->file_put_contents('/sharedfolder/subfolder/foo.txt', 'foobar'); // size of recipient's root stays the same $newRecipientRootInfo = $recipientView->getFileInfo('', false); $this->assertEquals($recipientRootInfo->getSize(), $newRecipientRootInfo->getSize()); // size of owner's root increases $this->loginHelper(self::TEST_FILES_SHARING_API_USER2); $newOwnerRootInfo = $ownerView->getFileInfo('', false); $this->assertEquals($ownerRootInfo->getSize() + 3, $newOwnerRootInfo->getSize()); }
/** * sets the users avatar * @param \OCP\IImage|resource|string $data An image object, imagedata or path to set a new avatar * @throws \Exception if the provided file is not a jpg or png image * @throws \Exception if the provided image is not valid * @throws \OC\NotSquareException if the image is not square * @return void */ public function set($data) { if ($data instanceof \OCP\IImage) { $img = $data; $data = $img->data(); } else { $img = new OC_Image($data); } $type = substr($img->mimeType(), -3); if ($type === 'peg') { $type = 'jpg'; } if ($type !== 'jpg' && $type !== 'png') { $l = \OC::$server->getL10N('lib'); throw new \Exception($l->t("Unknown filetype")); } if (!$img->valid()) { $l = \OC::$server->getL10N('lib'); throw new \Exception($l->t("Invalid image")); } if (!($img->height() === $img->width())) { throw new \OC\NotSquareException(); } $this->view->unlink('avatar.jpg'); $this->view->unlink('avatar.png'); $this->view->file_put_contents('avatar.' . $type, $data); }
protected function setUp() { $app = new Application(); $this->container = $app->getContainer(); $this->container['Config'] = $this->getMockBuilder('\\OCP\\IConfig')->disableOriginalConstructor()->getMock(); $this->container['AppName'] = 'files_sharing'; $this->container['UserSession'] = $this->getMockBuilder('\\OC\\User\\Session')->disableOriginalConstructor()->getMock(); $this->container['URLGenerator'] = $this->getMockBuilder('\\OC\\URLGenerator')->disableOriginalConstructor()->getMock(); $this->urlGenerator = $this->container['URLGenerator']; $this->shareController = $this->container['ShareController']; // Store current user $this->oldUser = \OC_User::getUser(); // Create a dummy user $this->user = \OC::$server->getSecureRandom()->getLowStrengthGenerator()->generate(12, ISecureRandom::CHAR_LOWER); \OC_User::createUser($this->user, $this->user); \OC_Util::tearDownFS(); \OC_User::setUserId(''); Filesystem::tearDown(); \OC_User::setUserId($this->user); \OC_Util::setupFS($this->user); // Create a dummy shared file $view = new View('/' . $this->user . '/files'); $view->file_put_contents('file1.txt', 'I am such an awesome shared file!'); $this->token = \OCP\Share::shareItem(Filesystem::getFileInfo('file1.txt')->getType(), Filesystem::getFileInfo('file1.txt')->getId(), \OCP\Share::SHARE_TYPE_LINK, 'IAmPasswordProtected!', 1); }
/** * @dataProvider isExcludedPathProvider */ function testIsExcludedPath($path, $expected) { $this->view->mkdir(dirname($path)); $this->view->file_put_contents($path, "test"); $result = \Test_Helper::invokePrivate(new \OCA\Files_Encryption\Proxy(), 'isExcludedPath', array($path)); $this->assertSame($expected, $result); $this->view->deleteAll(dirname($path)); }
/** * Stores the sample in the filesystem and stores it in the $samples array * * @param string $fileName * @param int $sampleWidth * @param int $sampleHeight */ private function prepareSample($fileName, $sampleWidth, $sampleHeight) { $imgData = file_get_contents(\OC::$SERVERROOT . '/tests/data/' . $fileName); $imgPath = '/' . self::TEST_PREVIEW_USER1 . '/files/' . $fileName; $this->rootView->file_put_contents($imgPath, $imgData); $fileInfo = $this->rootView->getFileInfo($imgPath); list($maxPreviewWidth, $maxPreviewHeight) = $this->setMaxPreview($sampleWidth, $sampleHeight); $this->samples[] = ['sampleFileId' => $fileInfo['fileid'], 'sampleFileName' => $fileName, 'sampleWidth' => $sampleWidth, 'sampleHeight' => $sampleHeight, 'maxPreviewWidth' => $maxPreviewWidth, 'maxPreviewHeight' => $maxPreviewHeight]; }
/** * @dataProvider isExcludedPathProvider */ function testIsExcludedPath($path, $expected) { $this->view->mkdir(dirname($path)); $this->view->file_put_contents($path, "test"); $testClass = new DummyProxy(); $result = $testClass->isExcludedPathTesting($path, $this->userId); $this->assertSame($expected, $result); $this->view->deleteAll(dirname($path)); }
protected function createDummySystemWideKeys() { $this->view->mkdir('files_encryption'); $this->view->mkdir('files_encryption/public_keys'); $this->view->file_put_contents('files_encryption/systemwide_1.privateKey', 'data'); $this->view->file_put_contents('files_encryption/systemwide_2.privateKey', 'data'); $this->view->file_put_contents('files_encryption/public_keys/systemwide_1.publicKey', 'data'); $this->view->file_put_contents('files_encryption/public_keys/systemwide_2.publicKey', 'data'); }
/** * Adds the test file to the filesystem * * @param string $fileName name of the file to create * @param string $fileContent path to file to use for test * * @return string */ protected function prepareTestFile($fileName, $fileContent) { $imgData = file_get_contents($fileContent); $imgPath = '/' . $this->userId . '/files/' . $fileName; $this->rootView->file_put_contents($imgPath, $imgData); $scanner = $this->storage->getScanner(); $scanner->scan(''); return $imgPath; }
/** * prepare new key storage * * @param string $newRoot * @throws \Exception */ protected function prepareNewRoot($newRoot) { if ($this->rootView->is_dir($newRoot) === false) { throw new \Exception("New root folder doesn't exist. Please create the folder or check the permissions and try again."); } $result = $this->rootView->file_put_contents($newRoot . '/' . Storage::KEY_STORAGE_MARKER, 'ownCloud will detect this folder as key storage root only if this file exists'); if ($result === false) { throw new \Exception("Can't write to new root folder. Please check the permissions and try again"); } }
/** * write key to disk * * * @param string $path path to key directory * @param string $key key * @return bool */ private function setKey($path, $key) { $this->keySetPreparation(dirname($path)); $result = $this->view->file_put_contents($path, $key); if (is_int($result) && $result > 0) { $this->keyCache[$path] = $key; return true; } return false; }
function testPostFileSizeWithDirectory() { $this->view->file_put_contents($this->filename, $this->data); \OC_FileProxy::$enabled = false; // get root size, must match the file's unencrypted size $unencryptedSize = $this->view->filesize(''); \OC_FileProxy::$enabled = true; $encryptedSize = $this->view->filesize(''); $this->assertTrue($encryptedSize !== $unencryptedSize); // cleanup $this->view->unlink($this->filename); }
function testDescryptAllWithBrokenFiles() { $file1 = "/decryptAll1" . $this->getUniqueID() . ".txt"; $file2 = "/decryptAll2" . $this->getUniqueID() . ".txt"; $util = new \OCA\Files_Encryption\Util($this->view, $this->userId); $this->view->file_put_contents($this->userId . '/files/' . $file1, $this->dataShort); $this->view->file_put_contents($this->userId . '/files/' . $file2, $this->dataShort); $fileInfoEncrypted1 = $this->view->getFileInfo($this->userId . '/files/' . $file1); $fileInfoEncrypted2 = $this->view->getFileInfo($this->userId . '/files/' . $file2); $this->assertTrue($fileInfoEncrypted1 instanceof \OC\Files\FileInfo); $this->assertTrue($fileInfoEncrypted2 instanceof \OC\Files\FileInfo); $this->assertEquals($fileInfoEncrypted1['encrypted'], 1); $this->assertEquals($fileInfoEncrypted2['encrypted'], 1); // rename keyfile for file1 so that the decryption for file1 fails // Expected behaviour: decryptAll() returns false, file2 gets decrypted anyway $this->view->rename($this->userId . '/files_encryption/keys/' . $file1 . '/fileKey', $this->userId . '/files_encryption/keys/' . $file1 . '/fileKey.moved'); // need to reset key cache that we don't use the cached key $this->resetKeyCache(); // decrypt all encrypted files $result = $util->decryptAll(); $this->assertFalse($result); $fileInfoUnencrypted1 = $this->view->getFileInfo($this->userId . '/files/' . $file1); $fileInfoUnencrypted2 = $this->view->getFileInfo($this->userId . '/files/' . $file2); $this->assertTrue($fileInfoUnencrypted1 instanceof \OC\Files\FileInfo); $this->assertTrue($fileInfoUnencrypted2 instanceof \OC\Files\FileInfo); // file1 should be still encrypted; file2 should be decrypted $this->assertEquals(1, $fileInfoUnencrypted1['encrypted']); $this->assertEquals(0, $fileInfoUnencrypted2['encrypted']); // keyfiles and share keys should still exist $this->assertTrue($this->view->is_dir($this->userId . '/files_encryption/keys/')); $this->assertTrue($this->view->file_exists($this->userId . '/files_encryption/keys/' . $file1 . '/fileKey.moved')); $this->assertTrue($this->view->file_exists($this->userId . '/files_encryption/keys/' . $file1 . '/' . $this->userId . '.shareKey')); // rename the keyfile for file1 back $this->view->rename($this->userId . '/files_encryption/keys/' . $file1 . '/fileKey.moved', $this->userId . '/files_encryption/keys/' . $file1 . '/fileKey'); // try again to decrypt all encrypted files $result = $util->decryptAll(); $this->assertTrue($result); $fileInfoUnencrypted1 = $this->view->getFileInfo($this->userId . '/files/' . $file1); $fileInfoUnencrypted2 = $this->view->getFileInfo($this->userId . '/files/' . $file2); $this->assertTrue($fileInfoUnencrypted1 instanceof \OC\Files\FileInfo); $this->assertTrue($fileInfoUnencrypted2 instanceof \OC\Files\FileInfo); // now both files should be decrypted $this->assertEquals(0, $fileInfoUnencrypted1['encrypted']); $this->assertEquals(0, $fileInfoUnencrypted2['encrypted']); // keyfiles and share keys should be deleted $this->assertFalse($this->view->is_dir($this->userId . '/files_encryption/keys/')); //cleanup $backupPath = $this->getBackupPath('decryptAll'); $this->view->unlink($this->userId . '/files/' . $file1); $this->view->unlink($this->userId . '/files/' . $file2); $this->view->deleteAll($backupPath); }
/** * save text file * * @NoAdminRequired * * @param string $path * @param string $filecontents * @param integer $mtime * @return DataResponse */ public function save($path, $filecontents, $mtime) { try { if ($path !== '' && (is_integer($mtime) && $mtime > 0)) { // Get file mtime $filemtime = $this->view->filemtime($path); if ($mtime !== $filemtime) { // Then the file has changed since opening $this->logger->error('File: ' . $path . ' modified since opening.', ['app' => 'files_texteditor']); return new DataResponse(['message' => $this->l->t('Cannot save file as it has been modified since opening')], Http::STATUS_BAD_REQUEST); } else { // File same as when opened, save file if ($this->view->isUpdatable($path)) { $filecontents = iconv(mb_detect_encoding($filecontents), "UTF-8", $filecontents); try { $this->view->file_put_contents($path, $filecontents); } catch (LockedException $e) { $message = (string) $this->l->t('The file is locked.'); return new DataResponse(['message' => $message], Http::STATUS_BAD_REQUEST); } catch (ForbiddenException $e) { return new DataResponse(['message' => $e->getMessage()], Http::STATUS_BAD_REQUEST); } // Clear statcache clearstatcache(); // Get new mtime $newmtime = $this->view->filemtime($path); $newsize = $this->view->filesize($path); return new DataResponse(['mtime' => $newmtime, 'size' => $newsize], Http::STATUS_OK); } else { // Not writeable! $this->logger->error('User does not have permission to write to file: ' . $path, ['app' => 'files_texteditor']); return new DataResponse(['message' => $this->l->t('Insufficient permissions')], Http::STATUS_BAD_REQUEST); } } } else { if ($path === '') { $this->logger->error('No file path supplied'); return new DataResponse(['message' => $this->l->t('File path not supplied')], Http::STATUS_BAD_REQUEST); } else { $this->logger->error('No file mtime supplied', ['app' => 'files_texteditor']); return new DataResponse(['message' => $this->l->t('File mtime not supplied')], Http::STATUS_BAD_REQUEST); } } } catch (HintException $e) { $message = (string) $e->getHint(); return new DataResponse(['message' => $message], Http::STATUS_BAD_REQUEST); } catch (\Exception $e) { $message = (string) $this->l->t('An internal server error occurred.'); return new DataResponse(['message' => $message], Http::STATUS_BAD_REQUEST); } }
function testDeleteHooksForSharedFiles() { self::logoutHelper(); self::loginHelper(self::TEST_ENCRYPTION_HOOKS_USER1); \OC_User::setUserId(self::TEST_ENCRYPTION_HOOKS_USER1); // remember files_trashbin state $stateFilesTrashbin = \OC_App::isEnabled('files_trashbin'); // we want to tests with app files_trashbin disabled \OC_App::disable('files_trashbin'); // make sure that the trash bin is disabled $this->assertFalse(\OC_APP::isEnabled('files_trashbin')); $this->user1View->file_put_contents($this->filename, $this->data); // check if all keys are generated $this->assertTrue($this->rootView->file_exists(self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keys/' . $this->filename . '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey')); $this->assertTrue($this->rootView->file_exists(self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keys/' . $this->filename . '/fileKey')); // get the file info from previous created file $fileInfo = $this->user1View->getFileInfo($this->filename); // check if we have a valid file info $this->assertTrue($fileInfo instanceof \OC\Files\FileInfo); // share the file with user2 \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, self::TEST_ENCRYPTION_HOOKS_USER2, \OCP\Constants::PERMISSION_ALL); // check if new share key exists $this->assertTrue($this->rootView->file_exists(self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keys/' . $this->filename . '/' . self::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey')); self::logoutHelper(); self::loginHelper(self::TEST_ENCRYPTION_HOOKS_USER2); \OC_User::setUserId(self::TEST_ENCRYPTION_HOOKS_USER2); // user2 update the shared file $this->user2View->file_put_contents($this->filename, $this->data); // keys should be stored at user1s dir, not in user2s $this->assertFalse($this->rootView->file_exists(self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/keys/' . $this->filename . '/' . self::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey')); $this->assertFalse($this->rootView->file_exists(self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/keys/' . $this->filename . '/fileKey')); // delete the Shared file from user1 in data/user2/files/Shared $result = $this->user2View->unlink($this->filename); $this->assertTrue($result); // share key for user2 from user1s home should be gone, all other keys should still exists $this->assertTrue($this->rootView->file_exists(self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keys/' . $this->filename . '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey')); $this->assertFalse($this->rootView->file_exists(self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keys/' . $this->filename . '/' . self::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey')); $this->assertTrue($this->rootView->file_exists(self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keys/' . $this->filename . '/fileKey')); // cleanup self::logoutHelper(); self::loginHelper(self::TEST_ENCRYPTION_HOOKS_USER1); \OC_User::setUserId(self::TEST_ENCRYPTION_HOOKS_USER1); if ($stateFilesTrashbin) { \OC_App::enable('files_trashbin'); } else { \OC_App::disable('files_trashbin'); } }
public function testCreationFromCached() { $sampleFile = '/' . $this->user . '/files/test.txt'; $this->rootView->file_put_contents($sampleFile, 'dummy file data'); // create base preview $x = 150; $y = 150; $preview = new \OC\Preview($this->user, 'files/', 'test.txt', $x, $y); $preview->getPreview(); $fileInfo = $this->rootView->getFileInfo($sampleFile); $fileId = $fileInfo['fileid']; $thumbCacheFile = '/' . $this->user . '/' . \OC\Preview::THUMBNAILS_FOLDER . '/' . $fileId . '/' . $x . '-' . $y . '.png'; $this->assertEquals($this->rootView->file_exists($thumbCacheFile), true); // create smaller previews $preview = new \OC\Preview($this->user, 'files/', 'test.txt', 50, 50); $isCached = $preview->isCached($fileId); $this->assertEquals($this->user . '/' . \OC\Preview::THUMBNAILS_FOLDER . '/' . $fileId . '/150-150.png', $isCached); }
/** * Delete should fail is the source file cant be deleted */ public function testSingleStorageDeleteFail() { /** * @var \OC\Files\Storage\Temporary | \PHPUnit_Framework_MockObject_MockObject $storage */ $storage = $this->getMockBuilder('\\OC\\Files\\Storage\\Temporary')->setConstructorArgs([[]])->setMethods(['rename', 'unlink'])->getMock(); $storage->expects($this->any())->method('rename')->will($this->returnValue(false)); $storage->expects($this->any())->method('unlink')->will($this->returnValue(false)); $cache = $storage->getCache(); Filesystem::mount($storage, [], '/' . $this->user . '/files'); $this->userView->file_put_contents('test.txt', 'foo'); $this->assertTrue($storage->file_exists('test.txt')); $this->assertFalse($this->userView->unlink('test.txt')); $this->assertTrue($storage->file_exists('test.txt')); $this->assertTrue($cache->inCache('test.txt')); // file should not be in the trashbin $results = $this->rootView->getDirectoryContent($this->user . '/files_trashbin/files/'); $this->assertEquals(0, count($results)); }
/** * Save the certificate and re-generate the certificate bundle * * @param string $certificate the certificate data * @param string $name the filename for the certificate * @return \OCP\ICertificate * @throws \Exception If the certificate could not get added */ public function addCertificate($certificate, $name) { if (!Filesystem::isValidPath($name) or Filesystem::isFileBlacklisted($name)) { throw new \Exception('Filename is not valid'); } $dir = $this->getPathToCertificates() . 'uploads/'; if (!$this->view->file_exists($dir)) { $this->view->mkdir($dir); } try { $file = $dir . $name; $certificateObject = new Certificate($certificate, $name); $this->view->file_put_contents($file, $certificate); $this->createCertificateBundle(); return $certificateObject; } catch (\Exception $e) { throw $e; } }
/** * Sets up user folders and keys for serverside encryption * * @param string $passphrase to encrypt server-stored private key with * @return bool */ public function setupServerSide($passphrase = null) { // Set directories to check / create $setUpDirs = array($this->userDir, $this->publicKeyDir, $this->encryptionDir, $this->keysPath); // Check / create all necessary dirs foreach ($setUpDirs as $dirPath) { if (!$this->view->file_exists($dirPath)) { $this->view->mkdir($dirPath); } } // Create user keypair // we should never override a keyfile if (!$this->view->file_exists($this->publicKeyPath) && !$this->view->file_exists($this->privateKeyPath)) { // Generate keypair $keypair = Crypt::createKeypair(); if ($keypair) { \OC_FileProxy::$enabled = false; // Encrypt private key with user pwd as passphrase $encryptedPrivateKey = Crypt::symmetricEncryptFileContent($keypair['privateKey'], $passphrase, Helper::getCipher()); // Save key-pair if ($encryptedPrivateKey) { $header = crypt::generateHeader(); $this->view->file_put_contents($this->privateKeyPath, $header . $encryptedPrivateKey); $this->view->file_put_contents($this->publicKeyPath, $keypair['publicKey']); } \OC_FileProxy::$enabled = true; } } else { // check if public-key exists but private-key is missing if ($this->view->file_exists($this->publicKeyPath) && !$this->view->file_exists($this->privateKeyPath)) { \OCP\Util::writeLog('Encryption library', 'public key exists but private key is missing for "' . $this->keyId . '"', \OCP\Util::FATAL); return false; } else { if (!$this->view->file_exists($this->publicKeyPath) && $this->view->file_exists($this->privateKeyPath)) { \OCP\Util::writeLog('Encryption library', 'private key exists but public key is missing for "' . $this->keyId . '"', \OCP\Util::FATAL); return false; } } } return true; }
/** * test if we find all versions and if the versions array contain * the correct 'path' and 'name' */ public function testGetVersions() { $t1 = time(); // second version is two weeks older, this way we make sure that no // version will be expired $t2 = $t1 - 60 * 60 * 24 * 14; // create some versions $v1 = self::USERS_VERSIONS_ROOT . '/subfolder/test.txt.v' . $t1; $v2 = self::USERS_VERSIONS_ROOT . '/subfolder/test.txt.v' . $t2; $this->rootView->mkdir(self::USERS_VERSIONS_ROOT . '/subfolder/'); $this->rootView->file_put_contents($v1, 'version1'); $this->rootView->file_put_contents($v2, 'version2'); // execute copy hook of versions app $versions = \OCA\Files_Versions\Storage::getVersions(self::TEST_VERSIONS_USER, '/subfolder/test.txt'); $this->assertSame(2, count($versions)); foreach ($versions as $version) { $this->assertSame('/subfolder/test.txt', $version['path']); $this->assertSame('test.txt', $version['name']); } //cleanup $this->rootView->deleteAll(self::USERS_VERSIONS_ROOT . '/subfolder'); }
public function setUp() { $app = new Application(); $container = $app->getContainer(); // reset backend $um = $container->getServer()->getUserManager(); $this->userSession = $container->getServer()->getUserSession(); $um->clearBackends(); $um->registerBackend(new \OC_User_Database()); // create test user $this->userName = '******'; \OC_User::deleteUser($this->userName); $um->createUser($this->userName, $this->userName); \OC_Util::tearDownFS(); $this->userSession->setUser(null); Filesystem::tearDown(); \OC_Util::setupFS($this->userName); $this->userSession->setUser($um->get($this->userName)); $view = new \OC\Files\View('/' . $this->userName . '/files'); // setup files $filesToCopy = array('documents' => array('document.pdf', 'document.docx', 'document.odt', 'document.txt')); $count = 0; foreach ($filesToCopy as $folder => $files) { foreach ($files as $file) { $imgData = file_get_contents(__DIR__ . '/data/' . $file); $view->mkdir($folder); $path = $folder . '/' . $file; $view->file_put_contents($path, $imgData); // set mtime to get fixed sorting with respect to recentFiles $count++; $view->touch($path, 1000 + $count); } } list($storage, ) = $view->resolvePath(''); /** @var $storage Storage */ $this->storage = $storage; $this->scanner = $storage->getScanner(); $this->scanner->scan(''); }
/** * @medium */ function testRecursiveDelShareKeysFile() { $this->view->mkdir('/' . self::TEST_USER . '/files/folder1'); $this->view->file_put_contents('/' . self::TEST_USER . '/files/folder1/existingFile.txt', 'data'); // create folder structure for some dummy share key files $this->view->mkdir('/' . self::TEST_USER . '/files_encryption/keys/folder1'); $this->view->mkdir('/' . self::TEST_USER . '/files_encryption/keys/folder1/existingFile.txt'); // create some dummy share keys $this->view->file_put_contents('/' . self::TEST_USER . '/files_encryption/keys/folder1/existingFile.txt/user1.shareKey', 'data'); $this->view->file_put_contents('/' . self::TEST_USER . '/files_encryption/keys/folder1/existingFile.txt/user2.shareKey', 'data'); $this->view->file_put_contents('/' . self::TEST_USER . '/files_encryption/keys/folder1/existingFile.txt/user3.shareKey', 'data'); $this->view->file_put_contents('/' . self::TEST_USER . '/files_encryption/keys/folder1/existingFile.txt/' . self::TEST_USER . '.shareKey', 'data'); // recursive delete share keys from user1 and user2 \OCA\Files_Encryption\Keymanager::delShareKey($this->view, array('user1', 'user2', self::TEST_USER), \OCA\Files_Encryption\Keymanager::getKeyPath($this->view, new \OCA\Files_Encryption\Util($this->view, self::TEST_USER), '/folder1/existingFile.txt'), self::TEST_USER, '/folder1/existingFile.txt'); // check if share keys from user1 and user2 are deleted $this->assertFalse($this->view->file_exists('/' . self::TEST_USER . '/files_encryption/keys/folder1/existingFile/user1.shareKey')); $this->assertFalse($this->view->file_exists('/' . self::TEST_USER . '/files_encryption/keys/folder1/existingFile/user2.shareKey')); // check if share keys for user3 and owner $this->assertTrue($this->view->file_exists('/' . self::TEST_USER . '/files_encryption/keys/folder1/existingFile.txt/' . self::TEST_USER . '.shareKey')); $this->assertTrue($this->view->file_exists('/' . self::TEST_USER . '/files_encryption/keys/folder1/existingFile.txt/user3.shareKey')); // cleanup $this->view->deleteAll('/' . self::TEST_USER . '/files/folder1'); }
protected function createDummySystemWideKeys() { $this->view->mkdir('owncloud_private_key'); $this->view->file_put_contents('owncloud_private_key/systemwide_1.private.key', 'data'); $this->view->file_put_contents('owncloud_private_key/systemwide_2.private.key', 'data'); }
/** * @param \OC\Files\View $view * @param string $path */ private function createAndCheckVersions(\OC\Files\View $view, $path) { $view->file_put_contents($path, 'test file'); $view->file_put_contents($path, 'version 1'); $view->file_put_contents($path, 'version 2'); $this->loginAsUser(self::TEST_VERSIONS_USER); // need to scan for the versions list($rootStorage, ) = $this->rootView->resolvePath(self::TEST_VERSIONS_USER . '/files_versions'); $rootStorage->getScanner()->scan('files_versions'); $versions = \OCA\Files_Versions\Storage::getVersions(self::TEST_VERSIONS_USER, '/' . $path); // note: we cannot predict how many versions are created due to // test run timing $this->assertGreaterThan(0, count($versions)); }