From cdd816c930328f8ff721f9fa476184145eb3f41a Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Mon, 16 Dec 2013 12:16:07 +0100 Subject: only remove encryption keys if a real file gets deleted, skip this method if a file outside of /data/user/files was deleted --- apps/files_encryption/lib/proxy.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'apps/files_encryption/lib') diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 5ba3bfa784f..4a41c978139 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -182,8 +182,11 @@ class Proxy extends \OC_FileProxy { */ public function preUnlink($path) { - // let the trashbin handle this - if (\OCP\App::isEnabled('files_trashbin')) { + $relPath = Helper::stripUserFilesPath($path); + + // skip this method if the trash bin is enabled or if we delete a file + // outside of /data/user/files + if (\OCP\App::isEnabled('files_trashbin') || $relPath === false) { return true; } -- cgit v1.2.3 From 95892c8be9c1e5a35e8f31e2ab34d233c69e6c35 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Mon, 16 Dec 2013 15:24:11 +0100 Subject: update file cache for target file --- apps/files_encryption/lib/proxy.php | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'apps/files_encryption/lib') diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 4a41c978139..96667493a51 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -114,6 +114,15 @@ class Proxy extends \OC_FileProxy { // get encrypted content $data = $view->file_get_contents($tmpPath); + // update file cache for target file + $tmpFileInfo = $view->getFileInfo($tmpPath); + $fileInfo = $view->getFileInfo($path); + if (is_array($fileInfo) && is_array($tmpFileInfo)) { + $fileInfo['encrypted'] = true; + $fileInfo['unencrypted_size'] = $tmpFileInfo['size']; + $view->putFileInfo($path, $fileInfo); + } + // remove our temp file $view->deleteAll('/' . \OCP\User::getUser() . '/cache/' . $cacheFolder); -- cgit v1.2.3 From 83417d69be216c4ed58402006df3b901a95483ea Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Tue, 17 Dec 2013 11:28:05 +0100 Subject: remove duplicated code --- apps/files_encryption/lib/proxy.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'apps/files_encryption/lib') diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 96667493a51..41f352d853a 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -209,10 +209,7 @@ class Proxy extends \OC_FileProxy { $util = new Util($view, $userId); - // get relative path - $relativePath = \OCA\Encryption\Helper::stripUserFilesPath($path); - - list($owner, $ownerPath) = $util->getUidAndFilename($relativePath); + list($owner, $ownerPath) = $util->getUidAndFilename($relPath); // Delete keyfile & shareKey so it isn't orphaned if (!Keymanager::deleteFileKey($view, $ownerPath)) { -- cgit v1.2.3 From 69b89454a4070c0ae3e7e8b6e37f310a2ee28e73 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Tue, 17 Dec 2013 15:53:25 +0100 Subject: reliable detect encrypted files --- apps/files_encryption/lib/util.php | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'apps/files_encryption/lib') diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index bf7c49504a2..d4aa4d31649 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -464,20 +464,22 @@ class Util { */ public function isEncryptedPath($path) { - $relPath = Helper::getPathToRealFile($path); - - if ($relPath === false) { - $relPath = Helper::stripUserFilesPath($path); - } - - $fileKey = Keymanager::getFileKey($this->view, $this, $relPath); + // Disable encryption proxy so data retrieved is in its + // original form + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; - if ($fileKey === false) { - return false; + // we only need 24 byte from the last chunk + $data = ''; + $handle = $this->view->fopen($path, 'r'); + if (is_resource($handle) && !fseek($handle, -24, SEEK_END)) { + $data = fgets($handle); } - return true; + // re-enable proxy + \OC_FileProxy::$enabled = $proxyStatus; + return Crypt::isCatfileContent($data); } /** -- cgit v1.2.3 From c955381d5691be00053e52a0e43df698478d979c Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Tue, 17 Dec 2013 16:18:05 +0100 Subject: fall back to getLocalFile if storage doesn't support fseek --- apps/files_encryption/lib/util.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'apps/files_encryption/lib') diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index d4aa4d31649..577b656077f 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -472,8 +472,20 @@ class Util { // we only need 24 byte from the last chunk $data = ''; $handle = $this->view->fopen($path, 'r'); - if (is_resource($handle) && !fseek($handle, -24, SEEK_END)) { - $data = fgets($handle); + if (is_resource($handle)) { + if (fseek($handle, -24, SEEK_END) === 0) { + $data = fgets($handle); + } else { + // if fseek failed on the storage we create a local copy from the file + // and read this one + fclose($handle); + $localFile = $this->view->getLocalFile($path); + $handle = fopen($localFile, 'r'); + if (is_resource($handle) && fseek($handle, -24, SEEK_END) === 0) { + $data = fgets($handle); + } + } + fclose($handle); } // re-enable proxy -- cgit v1.2.3 From 9a94c0755339daeda54cbd1084077cde26255a2a Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Tue, 17 Dec 2013 16:19:00 +0100 Subject: remove unused method tail() --- apps/files_encryption/lib/util.php | 43 -------------------------------------- 1 file changed, 43 deletions(-) (limited to 'apps/files_encryption/lib') diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index bf7c49504a2..e090070f5ba 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -414,49 +414,6 @@ class Util { } - /** - * @brief Fetch the last lines of a file efficiently - * @note Safe to use on large files; does not read entire file to memory - * @note Derivative of http://tekkie.flashbit.net/php/tail-functionality-in-php - */ - public function tail($filename, $numLines) { - - \OC_FileProxy::$enabled = false; - - $text = ''; - $pos = -1; - $handle = $this->view->fopen($filename, 'r'); - - while ($numLines > 0) { - - --$pos; - - if (fseek($handle, $pos, SEEK_END) !== 0) { - - rewind($handle); - $numLines = 0; - - } elseif (fgetc($handle) === "\n") { - - --$numLines; - - } - - $block_size = (-$pos) % 8192; - if ($block_size === 0 || $numLines === 0) { - - $text = fread($handle, ($block_size === 0 ? 8192 : $block_size)) . $text; - - } - } - - fclose($handle); - - \OC_FileProxy::$enabled = true; - - return $text; - } - /** * @brief Check if a given path identifies an encrypted file * @param string $path -- cgit v1.2.3 From d9668977cd23a3989a412ba3412240bf3cf38c94 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Wed, 18 Dec 2013 15:40:43 +0100 Subject: implement ftell stream wrapper and fix return value from fseek stream wrapper --- apps/files_encryption/lib/stream.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'apps/files_encryption/lib') diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 7a37d2200a4..c3cbdd54f56 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -163,15 +163,26 @@ class Stream { } + /** + * @brief Returns the current position of the file pointer + * @return int position of the file pointer + */ + public function stream_tell() { + return ftell($this->handle); + } + /** * @param $offset * @param int $whence + * @return bool true if fseek was successful, otherwise false */ public function stream_seek($offset, $whence = SEEK_SET) { $this->flush(); - fseek($this->handle, $offset, $whence); + // this wrapper needs to return "true" for success. + // the fseek call itself returns 0 on succeess + return !fseek($this->handle, $offset, $whence); } -- cgit v1.2.3 From 4f8ae789ae0248401f292c2c2889f3ba566ef5f5 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Tue, 17 Dec 2013 18:13:46 +0100 Subject: extend the encryption stream wrapper to handle local files and add a fall back for file size calculation if the storage doesn't support fseek --- apps/files_encryption/lib/helper.php | 24 ++++++++++++++++++++++++ apps/files_encryption/lib/stream.php | 25 +++++++++++++++++++------ apps/files_encryption/lib/util.php | 19 +++++++++++++++++-- 3 files changed, 60 insertions(+), 8 deletions(-) (limited to 'apps/files_encryption/lib') diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php index 17bcac5c585..f893cf16e5a 100755 --- a/apps/files_encryption/lib/helper.php +++ b/apps/files_encryption/lib/helper.php @@ -29,6 +29,8 @@ namespace OCA\Encryption; */ class Helper { + private static $tmpFileMapping; // Map tmp files to files in data/user/files + /** * @brief register share related hooks * @@ -423,5 +425,27 @@ class Helper { public static function escapeGlobPattern($path) { return preg_replace('/(\*|\?|\[)/', '[$1]', $path); } + + /** + * @brief remember from which file the tmp file (getLocalFile() call) was created + * @param string $tmpFile path of tmp file + * @param string $originalFile path of the original file relative to data/ + */ + public static function addTmpFileToMapper($tmpFile, $originalFile) { + self::$tmpFileMapping[$tmpFile] = $originalFile; + } + + /** + * @brief get the path of the original file + * @param string $tmpFile path of the tmp file + * @return mixed path of the original file or false + */ + public static function getPathFromTmpFile($tmpFile) { + if (isset(self::$tmpFileMapping[$tmpFile])) { + return self::$tmpFileMapping[$tmpFile]; + } + + return false; + } } diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index c3cbdd54f56..b3bf34ddb82 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -64,6 +64,9 @@ class Stream { private $publicKey; private $encKeyfile; private $newFile; // helper var, we only need to write the keyfile for new files + private $isLocalTmpFile = false; // do we operate on a local tmp file + private $localTmpFile; // path of local tmp file + /** * @var \OC\Files\View */ @@ -91,13 +94,18 @@ class Stream { $this->rootView = new \OC_FilesystemView('/'); } - $this->session = new \OCA\Encryption\Session($this->rootView); $this->privateKey = $this->session->getPrivateKey(); - // rawPath is relative to the data directory - $this->rawPath = \OC\Files\Filesystem::normalizePath(str_replace('crypt://', '', $path)); + $normalizedPath = \OC\Files\Filesystem::normalizePath(str_replace('crypt://', '', $path)); + if ($originalFile = Helper::getPathFromTmpFile($normalizedPath)) { + $this->rawPath = $originalFile; + $this->isLocalTmpFile = true; + $this->localTmpFile = $normalizedPath; + } else { + $this->rawPath = $normalizedPath; + } $this->userId = Helper::getUser($this->rawPath); @@ -141,10 +149,14 @@ class Stream { \OCA\Encryption\Helper::redirectToErrorPage($this->session); } - $this->size = $this->rootView->filesize($this->rawPath, $mode); + $this->size = $this->rootView->filesize($this->rawPath); } - $this->handle = $this->rootView->fopen($this->rawPath, $mode); + if ($this->isLocalTmpFile) { + $this->handle = fopen($this->localTmpFile, $mode); + } else { + $this->handle = $this->rootView->fopen($this->rawPath, $mode); + } \OC_FileProxy::$enabled = $proxyStatus; @@ -488,7 +500,7 @@ class Stream { if ($this->privateKey === false) { // cleanup - if ($this->meta['mode'] !== 'r' && $this->meta['mode'] !== 'rb') { + if ($this->meta['mode'] !== 'r' && $this->meta['mode'] !== 'rb' && !$this->isLocalTmpFile) { // Disable encryption proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; @@ -509,6 +521,7 @@ class Stream { if ( $this->meta['mode'] !== 'r' && $this->meta['mode'] !== 'rb' && + $this->isLocalTmpFile === false && $this->size > 0 && $this->unencryptedSize > 0 ) { diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 577b656077f..70398183f8b 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -473,7 +473,9 @@ class Util { $data = ''; $handle = $this->view->fopen($path, 'r'); if (is_resource($handle)) { - if (fseek($handle, -24, SEEK_END) === 0) { + // suppress fseek warining, we handle the case that fseek doesn't + // work in the else branch + if (@fseek($handle, -24, SEEK_END) === 0) { $data = fgets($handle); } else { // if fseek failed on the storage we create a local copy from the file @@ -537,7 +539,20 @@ class Util { $lastChunckPos = ($lastChunkNr * 8192); // seek to end - fseek($stream, $lastChunckPos); + if (@fseek($stream, $lastChunckPos) === -1) { + // storage doesn't support fseek, we need a local copy + fclose($stream); + $localFile = $this->view->getLocalFile($path); + Helper::addTmpFileToMapper($localFile, $path); + $stream = fopen('crypt://' . $localFile, "r"); + if (fseek($stream, $lastChunckPos) === -1) { + // if fseek also fails on the local storage, than + // there is nothing we can do + fclose($stream); + \OCP\Util::writeLog('Encryption library', 'couldn\'t determine size of "' . $path, \OCP\Util::ERROR); + return $result; + } + } // get the content of the last chunk $lastChunkContent = fread($stream, $lastChunkSize); -- cgit v1.2.3 From 963ee31efb4d0cbae9a743d9bffb3ad39107b498 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Wed, 18 Dec 2013 18:23:07 +0100 Subject: Removed numRows usage from encryption app numRows on Oracle always seem to return 0. This fix removes numRows usage from the encryption and sharing app. This fixes unit tests and potentially the encryption app itself (migration status) when running on Oracle --- apps/files_encryption/lib/util.php | 46 ++++++++++++++------------------------ apps/files_sharing/tests/base.php | 4 ++-- 2 files changed, 19 insertions(+), 31 deletions(-) (limited to 'apps/files_encryption/lib') diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index a3852312200..552ddc324c0 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -241,11 +241,9 @@ class Util { if (\OCP\DB::isError($result)) { \OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR); } else { - if ($result->numRows() > 0) { - $row = $result->fetchRow(); - if (isset($row['recovery_enabled'])) { - $recoveryEnabled[] = $row['recovery_enabled']; - } + $row = $result->fetchRow(); + if ($row && isset($row['recovery_enabled'])) { + $recoveryEnabled[] = $row['recovery_enabled']; } } @@ -289,7 +287,7 @@ class Util { $sql = 'UPDATE `*PREFIX*encryption` SET `recovery_enabled` = ? WHERE `uid` = ?'; $args = array( - $enabled, + $enabled ? '1' : '0', $this->userId ); @@ -944,8 +942,8 @@ class Util { if (\OCP\DB::isError($result)) { \OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR); } else { - if ($result->numRows() > 0) { - $row = $result->fetchRow(); + $row = $result->fetchRow(); + if ($row) { $path = substr($row['path'], strlen('files')); } } @@ -1225,11 +1223,9 @@ class Util { if (\OCP\DB::isError($result)) { \OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR); } else { - if ($result->numRows() > 0) { - $row = $result->fetchRow(); - if (isset($row['migration_status'])) { - $migrationStatus[] = $row['migration_status']; - } + $row = $result->fetchRow(); + if ($row && isset($row['migration_status'])) { + $migrationStatus[] = $row['migration_status']; } } @@ -1409,9 +1405,7 @@ class Util { if (\OCP\DB::isError($result)) { \OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR); } else { - if ($result->numRows() > 0) { - $row = $result->fetchRow(); - } + $row = $result->fetchRow(); } return $row; @@ -1435,9 +1429,7 @@ class Util { if (\OCP\DB::isError($result)) { \OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR); } else { - if ($result->numRows() > 0) { - $row = $result->fetchRow(); - } + $row = $result->fetchRow(); } return $row; @@ -1456,18 +1448,16 @@ class Util { $result = $query->execute(array($id)); - $source = array(); + $source = null; if (\OCP\DB::isError($result)) { \OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR); } else { - if ($result->numRows() > 0) { - $source = $result->fetchRow(); - } + $source = $result->fetchRow(); } $fileOwner = false; - if (isset($source['parent'])) { + if ($source && isset($source['parent'])) { $parent = $source['parent']; @@ -1477,16 +1467,14 @@ class Util { $result = $query->execute(array($parent)); - $item = array(); + $item = null; if (\OCP\DB::isError($result)) { \OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR); } else { - if ($result->numRows() > 0) { - $item = $result->fetchRow(); - } + $item = $result->fetchRow(); } - if (isset($item['parent'])) { + if ($item && isset($item['parent'])) { $parent = $item['parent']; diff --git a/apps/files_sharing/tests/base.php b/apps/files_sharing/tests/base.php index 689c80cb9e6..3e283271f5d 100644 --- a/apps/files_sharing/tests/base.php +++ b/apps/files_sharing/tests/base.php @@ -132,8 +132,8 @@ abstract class Test_Files_Sharing_Base extends \PHPUnit_Framework_TestCase { $share = Null; - if ($result && $result->numRows() > 0) { - $share = $result->fetchRow(); + if ($result) { + $share = $result->fetchRow(); } return $share; -- cgit v1.2.3 From fe7fb66ef871df59e5a0327817d06150aa803e99 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Thu, 19 Dec 2013 10:32:56 +0100 Subject: we can also have a path user/cache/... --- apps/files_encryption/lib/helper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apps/files_encryption/lib') diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php index 17bcac5c585..f176c7714fd 100755 --- a/apps/files_encryption/lib/helper.php +++ b/apps/files_encryption/lib/helper.php @@ -274,7 +274,7 @@ class Helper { $split = explode('/', $trimmed); // it is not a file relative to data/user/files - if (count($split) < 2 || $split[1] !== 'files') { + if (count($split) < 2 || $split[1] !== 'files' || $split[1] !== 'cache') { return false; } -- cgit v1.2.3 From 165542f27dbd0b3bf05eb714111ff81f1fe79fea Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Thu, 19 Dec 2013 17:29:38 +0100 Subject: fix rename of shared files --- apps/files_encryption/hooks/hooks.php | 56 +++++++++++++++++++++++------------ apps/files_encryption/lib/helper.php | 1 + 2 files changed, 38 insertions(+), 19 deletions(-) (limited to 'apps/files_encryption/lib') diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 7b13ae2a1d0..3e453e210f3 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -30,6 +30,9 @@ use OC\Files\Filesystem; */ class Hooks { + // file for which we want to rename the keys after the rename operation was successful + private static $renamedFiles = array(); + /** * @brief Startup encryption backend upon user login * @note This method should never be called for users using client side encryption @@ -479,6 +482,18 @@ class Hooks { } } + /** + * @brief mark file as renamed so that we know the original source after the file was renamed + * @param string $path + */ + public static function preRename($params) { + $util = new Util(new \OC_FilesystemView('/'), \OCP\User::getUser()); + list($ownerOld, $pathOld) = $util->getUidAndFilename($params['oldpath']); + self::$renamedFiles[$params['oldpath']] = array( + 'uid' => $ownerOld, + 'path' => $pathOld); + } + /** * @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 @@ -501,19 +516,25 @@ class Hooks { $userId = \OCP\User::getUser(); $util = new Util($view, $userId); + $ownerOld = self::$renamedFiles[$params['oldpath']]['uid']; + $pathOld = self::$renamedFiles[$params['oldpath']]['path']; + list($ownerNew, $pathNew) = $util->getUidAndFilename($params['newpath']); + // Format paths to be relative to user files dir - if ($util->isSystemWideMountPoint($params['oldpath'])) { - $baseDir = 'files_encryption/'; - $oldKeyfilePath = $baseDir . 'keyfiles/' . $params['oldpath']; + if ($util->isSystemWideMountPoint($pathOld)) { + $oldKeyfilePath = 'files_encryption/keyfiles/' . $pathOld; + $oldShareKeyPath = 'files_encryption/share-keys/' . $pathOld; } else { - $baseDir = $userId . '/' . 'files_encryption/'; - $oldKeyfilePath = $baseDir . 'keyfiles/' . $params['oldpath']; + $oldKeyfilePath = $ownerOld . '/' . 'files_encryption/keyfiles/' . $pathOld; + $oldShareKeyPath = $ownerOld . '/' . 'files_encryption/share-keys/' . $pathOld; } - if ($util->isSystemWideMountPoint($params['newpath'])) { - $newKeyfilePath = $baseDir . 'keyfiles/' . $params['newpath']; + if ($util->isSystemWideMountPoint($pathNew)) { + $newKeyfilePath = 'files_encryption/keyfiles/' . $pathNew; + $newShareKeyPath = 'files_encryption/share-keys/' . $pathNew; } else { - $newKeyfilePath = $baseDir . 'keyfiles/' . $params['newpath']; + $newKeyfilePath = $ownerNew . '/files_encryption/keyfiles/' . $pathNew; + $newShareKeyPath = $ownerNew . '/files_encryption/share-keys/' . $pathNew; } // add key ext if this is not an folder @@ -522,11 +543,11 @@ class Hooks { $newKeyfilePath .= '.key'; // handle share-keys - $localKeyPath = $view->getLocalFile($baseDir . 'share-keys/' . $params['oldpath']); + $localKeyPath = $view->getLocalFile($oldShareKeyPath); $escapedPath = Helper::escapeGlobPattern($localKeyPath); $matches = glob($escapedPath . '*.shareKey'); foreach ($matches as $src) { - $dst = \OC\Files\Filesystem::normalizePath(str_replace($params['oldpath'], $params['newpath'], $src)); + $dst = \OC\Files\Filesystem::normalizePath(str_replace($pathOld, $pathNew, $src)); // create destination folder if not exists if (!file_exists(dirname($dst))) { @@ -538,15 +559,13 @@ class Hooks { } 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); + if (!$view->file_exists(dirname($newShareKeyPath))) { + $view->mkdir(dirname($newShareKeyPath), 0750, true); } - $view->rename($oldShareKeyfilePath, $newShareKeyfilePath); + $view->rename($oldShareKeyPath, $newShareKeyPath); } // Rename keyfile so it isn't orphaned @@ -561,18 +580,17 @@ class Hooks { } // build the path to the file - $newPath = '/' . $userId . '/files' . $params['newpath']; - $newPathRelative = $params['newpath']; + $newPath = '/' . $ownerNew . '/files' . $pathNew; if ($util->fixFileSize($newPath)) { // get sharing app state $sharingEnabled = \OCP\Share::isEnabled(); // get users - $usersSharing = $util->getSharingUsersArray($sharingEnabled, $newPathRelative); + $usersSharing = $util->getSharingUsersArray($sharingEnabled, $pathNew); // update sharing-keys - $util->setSharedFileKeyfiles($session, $usersSharing, $newPathRelative); + $util->setSharedFileKeyfiles($session, $usersSharing, $pathNew); } \OC_FileProxy::$enabled = $proxyStatus; diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php index 17bcac5c585..0f63e1aca98 100755 --- a/apps/files_encryption/lib/helper.php +++ b/apps/files_encryption/lib/helper.php @@ -59,6 +59,7 @@ class Helper { */ public static function registerFilesystemHooks() { + \OCP\Util::connectHook('OC_Filesystem', 'rename', 'OCA\Encryption\Hooks', 'preRename'); \OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OCA\Encryption\Hooks', 'postRename'); } -- cgit v1.2.3 From 517a55a437b5c5f455a3b294a80709345e7625ec Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Thu, 19 Dec 2013 11:15:59 +0100 Subject: tests added --- apps/files_encryption/lib/helper.php | 2 +- apps/files_encryption/tests/helper.php | 37 ++++++++++++++++++++++++++++++++++ apps/files_encryption/tests/util.php | 6 ++++++ 3 files changed, 44 insertions(+), 1 deletion(-) (limited to 'apps/files_encryption/lib') diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php index f176c7714fd..08941077258 100755 --- a/apps/files_encryption/lib/helper.php +++ b/apps/files_encryption/lib/helper.php @@ -274,7 +274,7 @@ class Helper { $split = explode('/', $trimmed); // it is not a file relative to data/user/files - if (count($split) < 2 || $split[1] !== 'files' || $split[1] !== 'cache') { + if (count($split) < 2 || ($split[1] !== 'files' && $split[1] !== 'cache')) { return false; } diff --git a/apps/files_encryption/tests/helper.php b/apps/files_encryption/tests/helper.php index cd2be70a8fe..4b46e976b81 100644 --- a/apps/files_encryption/tests/helper.php +++ b/apps/files_encryption/tests/helper.php @@ -8,6 +8,7 @@ require_once __DIR__ . '/../lib/helper.php'; +require_once __DIR__ . '/util.php'; use OCA\Encryption; @@ -16,6 +17,18 @@ use OCA\Encryption; */ class Test_Encryption_Helper extends \PHPUnit_Framework_TestCase { + const TEST_ENCRYPTION_HELPER_USER1 = "test-helper-user1"; + + public static function setUpBeforeClass() { + // create test user + \Test_Encryption_Util::loginHelper(\Test_Encryption_Helper::TEST_ENCRYPTION_HELPER_USER1, true); + } + + public static function tearDownAfterClass() { + // cleanup test user + \OC_User::deleteUser(\Test_Encryption_Helper::TEST_ENCRYPTION_HELPER_USER1); + } + /** * @medium */ @@ -64,4 +77,28 @@ class Test_Encryption_Helper extends \PHPUnit_Framework_TestCase { $this->assertEquals($relativePath, Encryption\Helper::getPathToRealFile($cachePath)); } + function testGetUser() { + + $path1 = "/" . self::TEST_ENCRYPTION_HELPER_USER1 . "/files/foo/bar.txt"; + $path2 = "/" . self::TEST_ENCRYPTION_HELPER_USER1 . "/cache/foo/bar.txt"; + $path3 = "/" . self::TEST_ENCRYPTION_HELPER_USER1 . "/thumbnails/foo"; + $path4 ="/" . "/" . self::TEST_ENCRYPTION_HELPER_USER1; + + // if we are logged-in every path should return the currently logged-in user + $this->assertEquals(self::TEST_ENCRYPTION_HELPER_USER1, Encryption\Helper::getUser($path3)); + + // now log out + \Test_Encryption_Util::logoutHelper(); + + // now we should only get the user from /user/files and user/cache paths + $this->assertEquals(self::TEST_ENCRYPTION_HELPER_USER1, Encryption\Helper::getUser($path1)); + $this->assertEquals(self::TEST_ENCRYPTION_HELPER_USER1, Encryption\Helper::getUser($path2)); + + $this->assertFalse(Encryption\Helper::getUser($path3)); + $this->assertFalse(Encryption\Helper::getUser($path4)); + + // Log-in again + \Test_Encryption_Util::loginHelper(\Test_Encryption_Helper::TEST_ENCRYPTION_HELPER_USER1); + } + } diff --git a/apps/files_encryption/tests/util.php b/apps/files_encryption/tests/util.php index e8dfb74f3f3..c83c3836157 100755 --- a/apps/files_encryption/tests/util.php +++ b/apps/files_encryption/tests/util.php @@ -416,6 +416,12 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { OCA\Encryption\Hooks::login($params); } + public static function logoutHelper() { + \OC_Util::tearDownFS(); + \OC_User::setUserId(''); + \OC\Files\Filesystem::tearDown(); + } + /** * helper function to set migration status to the right value * to be able to test the migration path -- cgit v1.2.3 From f4179a3f5aa14c047b466dd69d6e0844091e527e Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Wed, 15 Jan 2014 14:29:33 +0100 Subject: don't try to encrypt/decrypt cache chunks or files in the trash bin --- apps/files_encryption/lib/proxy.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'apps/files_encryption/lib') diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 41f352d853a..4fe76b97711 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -255,8 +255,8 @@ class Proxy extends \OC_FileProxy { // split the path parts $pathParts = explode('/', $path); - // FIXME: handling for /userId/cache used by webdav for chunking. The cache chunks are NOT encrypted - if (isset($pathParts[2]) && $pathParts[2] === 'cache') { + // don't try to encrypt/decrypt cache chunks or files in the trash bin + if (isset($pathParts[2]) && ($pathParts[2] === 'cache' || $pathParts[2] === 'files_trashbin')) { return $result; } -- cgit v1.2.3 From b489d6b0af1577031de017b5b01bd76ed5c871e0 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Wed, 22 Jan 2014 16:55:04 +0100 Subject: fix infinite loop if folder and subfolder has the same name --- apps/files_encryption/lib/util.php | 52 ++++++++++---------------------------- 1 file changed, 13 insertions(+), 39 deletions(-) (limited to 'apps/files_encryption/lib') diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 8a5dfabeec1..8816d4d649a 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -2,9 +2,10 @@ /** * ownCloud * - * @author Sam Tuke, Frank Karlitschek + * @author Sam Tuke, Frank Karlitschek, Bjoern Schiessle * @copyright 2012 Sam Tuke , - * Frank Karlitschek + * Frank Karlitschek , + * Bjoern Schiessle * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE @@ -1360,59 +1361,32 @@ class Util { } } - /** * @brief go recursively through a dir and collect all files and sub files. * @param string $dir relative to the users files folder * @return array with list of files relative to the users files folder */ public function getAllFiles($dir) { - $result = array(); + $dirList = array($dir); - $content = $this->view->getDirectoryContent(\OC\Files\Filesystem::normalizePath( - $this->userFilesDir . '/' . $dir)); - - // handling for re shared folders - $pathSplit = explode('/', $dir); - - foreach ($content as $c) { - - $sharedPart = $pathSplit[sizeof($pathSplit) - 1]; - $targetPathSplit = array_reverse(explode('/', $c['path'])); - - $path = ''; - - // rebuild path - foreach ($targetPathSplit as $pathPart) { - - if ($pathPart !== $sharedPart) { - - $path = '/' . $pathPart . $path; + while ($dirList) { + $dir = array_pop($dirList); + $content = $this->view->getDirectoryContent(\OC\Files\Filesystem::normalizePath( + $this->userFilesDir . '/' . $dir)); + foreach ($content as $c) { + $usersPath = isset($c['usersPath']) ? $c['usersPath'] : $c['path']; + if ($c['type'] === 'dir') { + $dirList[] = substr($usersPath, strlen("files")); } else { - - break; - + $result[] = substr($usersPath, strlen("files")); } - } - $path = $dir . $path; - - if ($c['type'] === 'dir') { - - $result = array_merge($result, $this->getAllFiles($path)); - - } else { - - $result[] = $path; - - } } return $result; - } /** -- cgit v1.2.3 From 83878b9a7dc364c5f51c2ad7eb0960250e2fe42e Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Thu, 23 Jan 2014 15:45:34 +0100 Subject: only update file cache with the unenecrypted size when the file was written --- apps/files_encryption/lib/proxy.php | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) (limited to 'apps/files_encryption/lib') diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 4fe76b97711..4e71ab1dd5d 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -37,6 +37,7 @@ namespace OCA\Encryption; class Proxy extends \OC_FileProxy { private static $blackList = null; //mimetypes blacklisted from encryption + private static $unencryptedSizes = array(); // remember unencrypted size /** * Check if a file requires encryption @@ -114,14 +115,12 @@ class Proxy extends \OC_FileProxy { // get encrypted content $data = $view->file_get_contents($tmpPath); - // update file cache for target file + // store new unenecrypted size so that it can be updated + // in the post proxy $tmpFileInfo = $view->getFileInfo($tmpPath); - $fileInfo = $view->getFileInfo($path); - if (is_array($fileInfo) && is_array($tmpFileInfo)) { - $fileInfo['encrypted'] = true; - $fileInfo['unencrypted_size'] = $tmpFileInfo['size']; - $view->putFileInfo($path, $fileInfo); - } + if ( isset($tmpFileInfo['size']) ) { + self::$unencryptedSizes[\OC_Filesystem::normalizePath($path)] = $tmpFileInfo['size']; + } // remove our temp file $view->deleteAll('/' . \OCP\User::getUser() . '/cache/' . $cacheFolder); @@ -136,6 +135,24 @@ class Proxy extends \OC_FileProxy { } + /** + * @brief update file cache with the new unencrypted size after file was written + * @param string $path + * @param mixed $result + * @return mixed + */ + public function postFile_put_contents($path, $result) { + $normalizedPath = \OC_Filesystem::normalizePath($path); + if ( isset(self::$unencryptedSizes[$normalizedPath]) ) { + $view = new \OC_FilesystemView('/'); + $view->putFileInfo($normalizedPath, + array('encrypted' => true, 'encrypted_size' => self::$unencryptedSizes[$normalizedPath])); + unset(self::$unencryptedSizes[$normalizedPath]); + } + + return $result; + } + /** * @param string $path Path of file from which has been read * @param string $data Data that has been read from file -- cgit v1.2.3