/** * @medium * @brief test if postFileSize returns the unencrypted file size */ function testPostFileSize() { // generate filename $filename = 'tmp-' . time() . '.txt'; $this->view->file_put_contents($filename, $this->data); \OC_FileProxy::$enabled = false; $unencryptedSize = $this->view->filesize($filename); \OC_FileProxy::$enabled = true; $encryptedSize = $this->view->filesize($filename); $this->assertTrue($encryptedSize !== $unencryptedSize); }
/** * @medium */ function testRecursiveDelShareKeys() { // generate filename $filename = '/tmp-' . time() . '.txt'; // create folder structure $this->view->mkdir('/' . Test_Encryption_Keymanager::TEST_USER . '/files/folder1'); $this->view->mkdir('/' . Test_Encryption_Keymanager::TEST_USER . '/files/folder1/subfolder'); $this->view->mkdir('/' . Test_Encryption_Keymanager::TEST_USER . '/files/folder1/subfolder/subsubfolder'); // enable encryption proxy $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = true; // save file with content $cryptedFile = file_put_contents('crypt:///' . Test_Encryption_Keymanager::TEST_USER . '/files/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; }
/** * @brief test moving a shared file out of the Shared folder */ function testRename() { // login as admin \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1); // save file with content $cryptedFile = file_put_contents('crypt:///' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename, $this->dataShort); // test that data was successfully written $this->assertTrue(is_int($cryptedFile)); // 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)); // share the file \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, OCP\PERMISSION_ALL); // check if share key for user2exists $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 user2 \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2); $this->assertTrue($this->view->file_exists('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/Shared/' . $this->filename)); // 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); // move the file out of the shared folder $this->view->rename('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/Shared/' . $this->filename, '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->filename); // check if we can read the moved file $retrievedRenamedFile = $this->view->file_get_contents('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->filename); // check if data is the same as we previously written $this->assertEquals($this->dataShort, $retrievedRenamedFile); // the owners file should be deleted $this->assertFalse($this->view->file_exists('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename)); // cleanup $this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->filename); }
function testDeleteHooksForSharedFiles() { \Test_Encryption_Util::logoutHelper(); \Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1); \OC_User::setUserId(\Test_Encryption_Hooks::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/share-keys/' . $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey')); $this->assertTrue($this->rootView->file_exists(self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->filename . '.key')); // get the file info from previous created file $fileInfo = $this->user1View->getFileInfo($this->filename); // check if we have a valid file info $this->assertTrue(is_array($fileInfo)); // share the file with user2 \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, self::TEST_ENCRYPTION_HOOKS_USER2, OCP\PERMISSION_ALL); // check if new share key exists $this->assertTrue($this->rootView->file_exists(self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/' . $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey')); \Test_Encryption_Util::logoutHelper(); \Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2); \OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2); // user2 has a local file with the same name $this->user2View->file_put_contents($this->filename, $this->data); // check if all keys are generated $this->assertTrue($this->rootView->file_exists(self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/share-keys/' . $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey')); $this->assertTrue($this->rootView->file_exists(self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/keyfiles/' . $this->filename . '.key')); // delete the Shared file from user1 in data/user2/files/Shared $this->user2View->unlink('/Shared/' . $this->filename); // now keys from user1s home should be gone $this->assertFalse($this->rootView->file_exists(self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/' . $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey')); // FIXME: key is not properly removed /* $this->assertFalse($this->rootView->file_exists( self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/' . $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey')); */ $this->assertFalse($this->rootView->file_exists(self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->filename . '.key')); // but user2 keys should still exist $this->assertTrue($this->rootView->file_exists(self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/share-keys/' . $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey')); $this->assertTrue($this->rootView->file_exists(self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/keyfiles/' . $this->filename . '.key')); // cleanup $this->user2View->unlink($this->filename); \Test_Encryption_Util::logoutHelper(); \Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1); \OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1); // unshare the file \OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, self::TEST_ENCRYPTION_HOOKS_USER2); $this->user1View->unlink($this->filename); if ($stateFilesTrashbin) { OC_App::enable('files_trashbin'); } else { OC_App::disable('files_trashbin'); } }
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->assertNotEqual($original, $stored); $fromFile = $rootView->file_get_contents($userDir . '/file'); $this->assertEqual($original, $fromFile); $fromFile = $view->file_get_contents('files/file'); $this->assertEqual($original, $fromFile); }
public function setUp() { //set testing key $_SESSION['enckey'] = 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(), '/'); //set up the users home folder in the temp storage $rootView = new OC_FilesystemView(''); $rootView->mkdir('/' . OC_User::getUser()); $rootView->mkdir('/' . OC_User::getUser() . '/files'); }
protected function getStorage() { if (isset($this->storage)) { return $this->storage; } if (OC_User::isLoggedIn()) { $subdir = 'cache'; $view = new OC_FilesystemView('/' . OC_User::getUser()); if (!$view->file_exists($subdir)) { $view->mkdir($subdir); } $this->storage = new OC_FilesystemView('/' . OC_User::getUser() . '/' . $subdir); return $this->storage; } else { OC_Log::write('core', 'Can\'t get cache storage, user not logged in', OC_Log::ERROR); 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); }
/** * @medium */ function testSymmetricStreamDecryptLongFileContent() { $filename = 'tmp-' . uniqid(); // Save long data as encrypted file using stream wrapper $cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/' . $filename, $this->dataLong); // Test that data was successfully written $this->assertTrue(is_int($cryptedFile)); // Get file decrypted contents $decrypt = file_get_contents('crypt:///' . $this->userId . '/files/' . $filename); $this->assertEquals($this->dataLong, $decrypt); // tear down $this->view->unlink($this->userId . '/files/' . $filename); }
public function setUp() { //clear all proxies and hooks so we can do clean testing OC_FileProxy::clearProxies(); OC_Hook::clear('OC_Filesystem'); //enable only the encryption hook if needed if (OC_App::isEnabled('files_encryption')) { OC_FileProxy::register(new OC_FileProxy_Encryption()); } //set up temporary storage OC_Filesystem::clearMounts(); OC_Filesystem::mount('OC_Filestorage_Temporary', array(), '/'); OC_User::clearBackends(); OC_User::useBackend(new OC_User_Dummy()); //login OC_User::createUser('test', 'test'); $this->user = OC_User::getUser(); OC_User::setUserId('test'); //set up the users dir $rootView = new OC_FilesystemView(''); $rootView->mkdir('/test'); $this->instance = new OC_Cache_File(); }
/** * @brief if session is started, check if ownCloud key pair is set up, if not create it * @param \OC_FilesystemView $view * * @note The ownCloud key pair is used to allow public link sharing even if encryption is enabled */ public function __construct($view) { $this->view = $view; if (!$this->view->is_dir('owncloud_private_key')) { $this->view->mkdir('owncloud_private_key'); } $publicShareKeyId = \OC_Appconfig::getValue('files_encryption', 'publicShareKeyId'); if ($publicShareKeyId === null) { $publicShareKeyId = 'pubShare_' . substr(md5(time()), 0, 8); \OC_Appconfig::setValue('files_encryption', 'publicShareKeyId', $publicShareKeyId); } if (!$this->view->file_exists("/public-keys/" . $publicShareKeyId . ".public.key") || !$this->view->file_exists("/owncloud_private_key/" . $publicShareKeyId . ".private.key")) { $keypair = Crypt::createKeypair(); // Disable encryption proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; // Save public key if (!$view->is_dir('/public-keys')) { $view->mkdir('/public-keys'); } $this->view->file_put_contents('/public-keys/' . $publicShareKeyId . '.public.key', $keypair['publicKey']); // Encrypt private key empty passphrase $encryptedPrivateKey = Crypt::symmetricEncryptFileContent($keypair['privateKey'], ''); // Save private key $this->view->file_put_contents('/owncloud_private_key/' . $publicShareKeyId . '.private.key', $encryptedPrivateKey); \OC_FileProxy::$enabled = $proxyStatus; } if (\OCA\Encryption\Helper::isPublicAccess()) { // Disable encryption proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; $encryptedKey = $this->view->file_get_contents('/owncloud_private_key/' . $publicShareKeyId . '.private.key'); $privateKey = Crypt::decryptPrivateKey($encryptedKey, ''); $this->setPublicSharePrivateKey($privateKey); \OC_FileProxy::$enabled = $proxyStatus; } }
/** * @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')); }
/** * @medium */ 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:///' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $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 try { \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_GROUP, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_GROUP1, OCP\PERMISSION_ALL); } catch (Exception $e) { $this->assertEquals(0, strpos($e->getMessage(), "Following users are not set up for encryption")); } // 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); }
/** * @medium * @brief test delete file forever */ function testPermanentDeleteFile() { // generate filename $filename = 'tmp-' . time() . '.txt'; // save file with content $cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/' . $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)); }
function testDelAllShareKeysFile() { $this->view->mkdir('/' . Test_Encryption_Keymanager::TEST_USER . '/files/folder1'); $this->view->file_put_contents('/' . Test_Encryption_Keymanager::TEST_USER . '/files/folder1/existingFile.txt', 'data'); // create folder structure for some dummy share key files $this->view->mkdir('/' . Test_Encryption_Keymanager::TEST_USER . '/files_encryption/share-keys/folder1'); // create some dummy share keys for the existing file $this->view->file_put_contents('/' . Test_Encryption_Keymanager::TEST_USER . '/files_encryption/share-keys/folder1/existingFile.txt.user1.shareKey', 'data'); $this->view->file_put_contents('/' . Test_Encryption_Keymanager::TEST_USER . '/files_encryption/share-keys/folder1/existingFile.txt.user2.shareKey', 'data'); $this->view->file_put_contents('/' . Test_Encryption_Keymanager::TEST_USER . '/files_encryption/share-keys/folder1/existingFile.txt.user3.shareKey', 'data'); $this->view->file_put_contents('/' . Test_Encryption_Keymanager::TEST_USER . '/files_encryption/share-keys/folder1/existingFile.txt.' . Test_Encryption_Keymanager::TEST_USER . '.shareKey', 'data'); // create some dummy share keys for a non-existing file $this->view->file_put_contents('/' . Test_Encryption_Keymanager::TEST_USER . '/files_encryption/share-keys/folder1/nonexistingFile.txt.user1.shareKey', 'data'); $this->view->file_put_contents('/' . Test_Encryption_Keymanager::TEST_USER . '/files_encryption/share-keys/folder1/nonexistingFile.txt.user2.shareKey', 'data'); $this->view->file_put_contents('/' . Test_Encryption_Keymanager::TEST_USER . '/files_encryption/share-keys/folder1/nonexistingFile.txt.user3.shareKey', 'data'); $this->view->file_put_contents('/' . Test_Encryption_Keymanager::TEST_USER . '/files_encryption/share-keys/folder1/nonexistingFile.txt.' . Test_Encryption_Keymanager::TEST_USER . '.shareKey', 'data'); // try to del all share keys from a existing file, should fail because the file still exists $result = Encryption\Keymanager::delAllShareKeys($this->view, Test_Encryption_Keymanager::TEST_USER, 'folder1/existingFile.txt'); $this->assertFalse($result); // check if share keys still exists $this->assertTrue($this->view->file_exists('/' . Test_Encryption_Keymanager::TEST_USER . '/files_encryption/share-keys/folder1/existingFile.txt.' . Test_Encryption_Keymanager::TEST_USER . '.shareKey')); $this->assertTrue($this->view->file_exists('/' . Test_Encryption_Keymanager::TEST_USER . '/files_encryption/share-keys/folder1/existingFile.txt.user1.shareKey')); $this->assertTrue($this->view->file_exists('/' . Test_Encryption_Keymanager::TEST_USER . '/files_encryption/share-keys/folder1/existingFile.txt.user2.shareKey')); $this->assertTrue($this->view->file_exists('/' . Test_Encryption_Keymanager::TEST_USER . '/files_encryption/share-keys/folder1/existingFile.txt.user3.shareKey')); // try to del all share keys from file, should succeed because the does not exist any more $result2 = Encryption\Keymanager::delAllShareKeys($this->view, Test_Encryption_Keymanager::TEST_USER, 'folder1/nonexistingFile.txt'); $this->assertTrue($result2); // check if share keys are really gone $this->assertFalse($this->view->file_exists('/' . Test_Encryption_Keymanager::TEST_USER . '/files_encryption/share-keys/folder1/nonexistingFile.txt.' . Test_Encryption_Keymanager::TEST_USER . '.shareKey')); // check that it only deleted keys or users who had access, others remain $this->assertTrue($this->view->file_exists('/' . Test_Encryption_Keymanager::TEST_USER . '/files_encryption/share-keys/folder1/nonexistingFile.txt.user1.shareKey')); $this->assertTrue($this->view->file_exists('/' . Test_Encryption_Keymanager::TEST_USER . '/files_encryption/share-keys/folder1/nonexistingFile.txt.user2.shareKey')); $this->assertTrue($this->view->file_exists('/' . Test_Encryption_Keymanager::TEST_USER . '/files_encryption/share-keys/folder1/nonexistingFile.txt.user3.shareKey')); // cleanup $this->view->deleteAll('/' . Test_Encryption_Keymanager::TEST_USER . '/files/folder1'); }
/** * @medium * @brief test if stream wrapper can read files outside from the data folder */ function testStreamFromLocalFile() { $filename = '/' . $this->userId . '/files/' . 'tmp-' . time() . '.txt'; $tmpFilename = "/tmp/" . time() . ".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\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); // clean up unlink($tmpFilename); $this->view->unlink($filename); }
/** * delete non existing files from the cache */ private static function cleanFolder($path, $root = '') { if (!$root) { $view = OC_Filesystem::getView(); } else { $view = new OC_FilesystemView($root == '/' ? '' : $root); } //check for removed files, not using getFolderContent to prevent loops $parent = self::getFileId($view->getRoot() . $path); $query = OC_DB::prepare('SELECT name FROM *PREFIX*fscache WHERE parent=?'); $result = $query->execute(array($parent)); while ($row = $result->fetchRow()) { $file = $path . '/' . $row['name']; if (!$view->file_exists($file)) { if (!$root) { //filesystem hooks are only valid for the default root OC_Hook::emit('OC_Filesystem', 'post_delete', array('path' => $file)); } else { self::fileSystemWatcherDelete(array('path' => $file), $root); } } } }
/** * after a file is renamed/copied, rename/copy its keyfile and share-keys also fix the file size and fix also the sharing * * @param array $params array with oldpath and newpath */ public static function postRenameOrCopy($params) { if (\OCP\App::isEnabled('files_encryption') === false) { return true; } // Disable encryption proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; $view = new \OC_FilesystemView('/'); $userId = \OCP\User::getUser(); $util = new Util($view, $userId); if (isset(self::$renamedFiles[$params['oldpath']]['uid']) && isset(self::$renamedFiles[$params['oldpath']]['path'])) { $ownerOld = self::$renamedFiles[$params['oldpath']]['uid']; $pathOld = self::$renamedFiles[$params['oldpath']]['path']; $type = self::$renamedFiles[$params['oldpath']]['type']; $operation = self::$renamedFiles[$params['oldpath']]['operation']; unset(self::$renamedFiles[$params['oldpath']]); } else { \OCP\Util::writeLog('Encryption library', "can't get path and owner from the file before it was renamed", \OCP\Util::DEBUG); \OC_FileProxy::$enabled = $proxyStatus; return false; } list($ownerNew, $pathNew) = $util->getUidAndFilename($params['newpath']); // Format paths to be relative to user files dir if ($util->isSystemWideMountPoint($pathOld)) { $oldKeyfilePath = 'files_encryption/keyfiles/' . $pathOld; $oldShareKeyPath = 'files_encryption/share-keys/' . $pathOld; } else { $oldKeyfilePath = $ownerOld . '/' . 'files_encryption/keyfiles/' . $pathOld; $oldShareKeyPath = $ownerOld . '/' . 'files_encryption/share-keys/' . $pathOld; } if ($util->isSystemWideMountPoint($pathNew)) { $newKeyfilePath = 'files_encryption/keyfiles/' . $pathNew; $newShareKeyPath = 'files_encryption/share-keys/' . $pathNew; } else { $newKeyfilePath = $ownerNew . '/files_encryption/keyfiles/' . $pathNew; $newShareKeyPath = $ownerNew . '/files_encryption/share-keys/' . $pathNew; } // add key ext if this is not an folder if ($type === 'file') { $oldKeyfilePath .= '.key'; $newKeyfilePath .= '.key'; // create destination folder if not exists $localKeyPath = $view->getLocalFile($oldShareKeyPath); $newLocalKeyPath = \OC\Files\Filesystem::normalizePath(str_replace($pathOld, $pathNew, $localKeyPath)); if (!file_exists(dirname($newLocalKeyPath))) { mkdir(dirname($newLocalKeyPath), 0750, true); } // handle share-keys $matches = Helper::findShareKeys($pathOld, $oldShareKeyPath, $view); if (count($matches) === 0) { \OC_Log::write('Encryption library', 'No share keys found for "' . $pathOld . '"', \OC_Log::WARN); } foreach ($matches as $src) { $dst = \OC\Files\Filesystem::normalizePath(str_replace($pathOld, $pathNew, $src)); $view->{$operation}($src, $dst); } } else { // handle share-keys folders // create destination folder if not exists if (!$view->file_exists(dirname($newShareKeyPath))) { mkdir($view->getLocalFile($newShareKeyPath), 0750, true); } $view->{$operation}($oldShareKeyPath, $newShareKeyPath); } // Rename keyfile so it isn't orphaned if ($view->file_exists($oldKeyfilePath)) { // create destination folder if not exists if (!$view->file_exists(dirname($newKeyfilePath))) { mkdir(dirname($view->getLocalFile($newKeyfilePath)), 0750, true); } $view->{$operation}($oldKeyfilePath, $newKeyfilePath); } // build the path to the file $newPath = '/' . $ownerNew . '/files' . $pathNew; // update sharing-keys self::updateKeyfiles($params['newpath'], $type); \OC_FileProxy::$enabled = $proxyStatus; }
/** * @param $path * @param $size * @return bool */ public function postFileSize($path, $size, $fileInfo = null) { $view = new \OC_FilesystemView('/'); $userId = Helper::getUser($path); $util = new Util($view, $userId); // if encryption is no longer enabled or if the files aren't migrated yet // we return the default file size if (!\OCP\App::isEnabled('files_encryption') || $util->getMigrationStatus() !== Util::MIGRATION_COMPLETED) { return $size; } // if path is a folder do nothing if ($view->is_dir($path)) { $proxyState = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; $fileInfo = $view->getFileInfo($path); \OC_FileProxy::$enabled = $proxyState; if (isset($fileInfo['unencrypted_size']) && $fileInfo['unencrypted_size'] > 0) { return $fileInfo['unencrypted_size']; } return $size; } // get relative path $relativePath = \OCA\Encryption\Helper::stripUserFilesPath($path); // if path is empty we cannot resolve anything if (empty($relativePath)) { return $size; } // get file info from database/cache if not .part file if (empty($fileInfo) && !Helper::isPartialFilePath($path)) { $proxyState = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; $fileInfo = $view->getFileInfo($path); \OC_FileProxy::$enabled = $proxyState; } // if file is encrypted return real file size if (isset($fileInfo['encrypted']) && $fileInfo['encrypted'] === true) { // try to fix unencrypted file size if it doesn't look plausible if ((int) $fileInfo['size'] > 0 && (int) $fileInfo['unencrypted_size'] === 0) { $fixSize = $util->getFileSize($path); $fileInfo['unencrypted_size'] = $fixSize; // put file info if not .part file if (!Helper::isPartialFilePath($relativePath)) { $view->putFileInfo($path, $fileInfo); } } $size = $fileInfo['unencrypted_size']; } else { // self healing if file was removed from file cache if (!is_array($fileInfo)) { $fileInfo = array(); } $fixSize = $util->getFileSize($path); if ($fixSize > 0) { $size = $fixSize; $fileInfo['encrypted'] = true; $fileInfo['unencrypted_size'] = $size; // put file info if not .part file if (!Helper::isPartialFilePath($relativePath)) { $view->putFileInfo($path, $fileInfo); } } } return $size; }
* 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/>. * */ // Check if we are a user OCP\User::checkLoggedIn(); $filename = $_GET["file"]; $view = new OC_FilesystemView('/' . \OCP\User::getUser() . '/files_trashbin/files'); if (!$view->file_exists($filename)) { header("HTTP/1.0 404 Not Found"); $tmpl = new OCP\Template('', '404', 'guest'); $tmpl->assign('file', $filename); $tmpl->printPage(); exit; } $ftype = $view->getMimeType($filename); header('Content-Type:' . $ftype); if (preg_match("/MSIE/", $_SERVER["HTTP_USER_AGENT"])) { header('Content-Disposition: attachment; filename="' . rawurlencode(basename($filename)) . '"'); } else { header('Content-Disposition: attachment; filename*=UTF-8\'\'' . rawurlencode(basename($filename)) . '; filename="' . rawurlencode(basename($filename)) . '"'); } OCP\Response::disableCaching();
private static function updateFolder($uid_shared_with) { if ($uid_shared_with != self::PUBLICLINK) { if (OC_Group::groupExists($uid_shared_with)) { $uid_shared_with = OC_Group::usersInGroup($uid_shared_with); // Remove the owner from the list of users in the group $uid_shared_with = array_diff($uid_shared_with, array(OCP\USER::getUser())); } else { if ($uid = strstr($uid_shared_with, '@', true)) { $uid_shared_with = array($uid); } else { $uid_shared_with = array($uid_shared_with); } } foreach ($uid_shared_with as $uid) { $sharedFolder = $uid . '/files/Shared'; // Update mtime of shared folder to invoke a file cache rescan $rootView = new OC_FilesystemView('/'); $rootView->touch($sharedFolder); } } }
/** * @brief after a file is renamed, rename its keyfile and share-keys also fix the file size and fix also the sharing * @param array with oldpath and newpath * * This function is connected to the rename signal of OC_Filesystem and adjust the name and location * of the stored versions along the actual file */ public static function postRename($params) { if (\OCP\App::isEnabled('files_encryption') === false) { return true; } // Disable encryption proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; $view = new \OC_FilesystemView('/'); $session = new \OCA\Encryption\Session($view); $userId = \OCP\User::getUser(); $util = new Util($view, $userId); // Format paths to be relative to user files dir if ($util->isSystemWideMountPoint($params['oldpath'])) { $baseDir = 'files_encryption/'; $oldKeyfilePath = $baseDir . 'keyfiles/' . $params['oldpath']; } else { $baseDir = $userId . '/' . 'files_encryption/'; $oldKeyfilePath = $baseDir . 'keyfiles/' . $params['oldpath']; } if ($util->isSystemWideMountPoint($params['newpath'])) { $newKeyfilePath = $baseDir . 'keyfiles/' . $params['newpath']; } else { $newKeyfilePath = $baseDir . 'keyfiles/' . $params['newpath']; } // add key ext if this is not an folder if (!$view->is_dir($oldKeyfilePath)) { $oldKeyfilePath .= '.key'; $newKeyfilePath .= '.key'; // handle share-keys $localKeyPath = $view->getLocalFile($baseDir . 'share-keys/' . $params['oldpath']); $escapedPath = Helper::escapeGlobPattern($localKeyPath); $matches = glob($escapedPath . '*.shareKey'); foreach ($matches as $src) { $dst = \OC\Files\Filesystem::normalizePath(str_replace($params['oldpath'], $params['newpath'], $src)); // create destination folder if not exists if (!file_exists(dirname($dst))) { mkdir(dirname($dst), 0750, true); } rename($src, $dst); } } else { // handle share-keys folders $oldShareKeyfilePath = $baseDir . 'share-keys/' . $params['oldpath']; $newShareKeyfilePath = $baseDir . 'share-keys/' . $params['newpath']; // create destination folder if not exists if (!$view->file_exists(dirname($newShareKeyfilePath))) { $view->mkdir(dirname($newShareKeyfilePath), 0750, true); } $view->rename($oldShareKeyfilePath, $newShareKeyfilePath); } // Rename keyfile so it isn't orphaned if ($view->file_exists($oldKeyfilePath)) { // create destination folder if not exists if (!$view->file_exists(dirname($newKeyfilePath))) { $view->mkdir(dirname($newKeyfilePath), 0750, true); } $view->rename($oldKeyfilePath, $newKeyfilePath); } // build the path to the file $newPath = '/' . $userId . '/files' . $params['newpath']; $newPathRelative = $params['newpath']; if ($util->fixFileSize($newPath)) { // get sharing app state $sharingEnabled = \OCP\Share::isEnabled(); // get users $usersSharing = $util->getSharingUsersArray($sharingEnabled, $newPathRelative); // update sharing-keys $util->setSharedFileKeyfiles($session, $usersSharing, $newPathRelative); } \OC_FileProxy::$enabled = $proxyStatus; }
function testGetFolderContentsInSubdir() { $results = $this->user2View->getDirectoryContent('/Shared/shareddir'); $this->verifyFiles(array(array('name' => 'bar.txt', 'path' => 'files/container/shareddir/bar.txt', 'mimetype' => 'text/plain', 'usersPath' => 'files/Shared/shareddir/bar.txt'), array('name' => 'emptydir', 'path' => 'files/container/shareddir/emptydir', 'mimetype' => 'httpd/unix-directory', 'usersPath' => 'files/Shared/shareddir/emptydir'), array('name' => 'subdir', 'path' => 'files/container/shareddir/subdir', 'mimetype' => 'httpd/unix-directory', 'usersPath' => 'files/Shared/shareddir/subdir')), $results); }
/** * update the filecache according to changes to the filesystem * @param string path * @param string root (optional) */ public static function update($path, $root = false) { if ($root === false) { $view = OC_Filesystem::getView(); } else { $view = new OC_FilesystemView($root); } $mimetype = $view->getMimeType($path); $size = 0; $cached = OC_FileCache_Cached::get($path, $root); $cachedSize = isset($cached['size']) ? $cached['size'] : 0; if ($view->is_dir($path . '/')) { if (OC_FileCache::inCache($path, $root)) { $cachedContent = OC_FileCache_Cached::getFolderContent($path, $root); foreach ($cachedContent as $file) { $size += $file['size']; } $mtime = $view->filemtime($path . '/'); $ctime = $view->filectime($path . '/'); $writable = $view->is_writable($path . '/'); OC_FileCache::put($path, array('size' => $size, 'mtime' => $mtime, 'ctime' => $ctime, 'mimetype' => $mimetype, 'writable' => $writable)); } else { $count = 0; OC_FileCache::scan($path, null, $count, $root); return; //increaseSize is already called inside scan } } else { $size = OC_FileCache::scanFile($path, $root); } OC_FileCache::increaseSize(dirname($path), $size - $cachedSize, $root); }
// User related hooks OCA\Encryption\Helper::registerUserHooks(); // Sharing related hooks OCA\Encryption\Helper::registerShareHooks(); // Filesystem related hooks OCA\Encryption\Helper::registerFilesystemHooks(); // App manager related hooks OCA\Encryption\Helper::registerAppHooks(); stream_wrapper_register('crypt', 'OCA\\Encryption\\Stream'); // check if we are logged in if (OCP\User::isLoggedIn()) { // ensure filesystem is loaded if (!\OC\Files\Filesystem::$loaded) { \OC_Util::setupFS(); } $view = new OC_FilesystemView('/'); $sessionReady = OCA\Encryption\Helper::checkRequirements(); if ($sessionReady) { $session = new \OCA\Encryption\Session($view); } $user = \OCP\USER::getUser(); // check if user has a private key if ($sessionReady === false || !$view->file_exists('/' . $user . '/files_encryption/' . $user . '.private.key') && OCA\Encryption\Crypt::mode() === 'server') { // Force the user to log-in again if the encryption key isn't unlocked // (happens when a user is logged in before the encryption app is // enabled) OCP\User::logout(); header("Location: " . OC::$WEBROOT . '/'); exit; } }
public static function changekeypasscode($oldPassword, $newPassword) { if (OCP\User::isLoggedIn()) { $username = OCP\USER::getUser(); $view = new OC_FilesystemView('/' . $username); // read old key $key = $view->file_get_contents('/encryption.key'); // decrypt key with old passcode $key = OC_Crypt::decrypt($key, $oldPassword); // encrypt again with new passcode $key = OC_Crypt::encrypt($key, $newPassword); // store the new key $view->file_put_contents('/encryption.key', $key); } }
/** * @param $path * @param $size * @return bool */ public function postFileSize($path, $size) { $view = new \OC_FilesystemView('/'); // if path is a folder do nothing if ($view->is_dir($path)) { return $size; } // get relative path $relativePath = \OCA\Encryption\Helper::stripUserFilesPath($path); // if path is empty we cannot resolve anything if (empty($relativePath)) { return $size; } $fileInfo = false; // get file info from database/cache if not .part file if (!Keymanager::isPartialFilePath($path)) { $fileInfo = $view->getFileInfo($path); } // if file is encrypted return real file size if (is_array($fileInfo) && $fileInfo['encrypted'] === true) { $size = $fileInfo['unencrypted_size']; } else { // self healing if file was removed from file cache if (!is_array($fileInfo)) { $fileInfo = array(); } $userId = \OCP\User::getUser(); $util = new Util($view, $userId); $fixSize = $util->getFileSize($path); if ($fixSize > 0) { $size = $fixSize; $fileInfo['encrypted'] = true; $fileInfo['unencrypted_size'] = $size; // put file info if not .part file if (!Keymanager::isPartialFilePath($relativePath)) { $view->putFileInfo($path, $fileInfo); } } } return $size; }
/** * @large */ 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); $this->setMigrationStatus(0, \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER); $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 string $appid * @return OC_FilesystemView */ public static function getStorage($appid) { if (OC_App::isEnabled($appid)) { //sanity check if (OC_User::isLoggedIn()) { $view = new OC_FilesystemView('/' . OC_User::getUser()); if (!$view->file_exists($appid)) { $view->mkdir($appid); } return new OC_FilesystemView('/' . OC_User::getUser() . '/' . $appid); } else { OC_Log::write('core', 'Can\'t get app storage, app, user not logged in', OC_Log::ERROR); return false; } } else { OC_Log::write('core', 'Can\'t get app storage, app ' . $appid . ' not enabled', OC_Log::ERROR); return false; } }
/** * scan a single file * @param string path * @param string root (optional) * @return int size of the scanned file */ public static function scanFile($path, $root = false) { // NOTE: Ugly hack to prevent shared files from going into the cache (the source already exists somewhere in the cache) if (substr($path, 0, 7) == '/Shared') { return; } if ($root === false) { $view = OC_Filesystem::getView(); } else { $view = new OC_FilesystemView($root); } if (!$view->is_readable($path)) { return; } //cant read, nothing we can do clearstatcache(); $mimetype = $view->getMimeType($path); $stat = $view->stat($path); if ($mimetype == 'httpd/unix-directory') { $stat['size'] = 0; $writable = $view->is_writable($path . '/'); } else { $writable = $view->is_writable($path); } $stat['mimetype'] = $mimetype; $stat['writable'] = $writable; if ($path == '/') { $path = ''; } self::put($path, $stat, $root); return $stat['size']; }