From fac288a4ad8f6db907c0a2ddfeb0b772fe616db5 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Thu, 25 Apr 2013 15:20:06 +0200 Subject: [PATCH] added unencrypted file size to file cache improved file size calculation and speeds --- apps/files_encryption/lib/proxy.php | 113 ++++++++++----------------- apps/files_encryption/lib/stream.php | 14 ++-- db_structure.xml | 8 ++ lib/files/cache/cache.php | 11 +-- 4 files changed, 62 insertions(+), 84 deletions(-) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index b805ec648d..c07b9a8a7a 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -108,7 +108,8 @@ class Proxy extends \OC_FileProxy { $size = strlen( $data ); // Disable encryption proxy to prevent recursive calls - \OC_FileProxy::$enabled = false; + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; // Check if there is an existing key we can reuse if ( $encKeyfile = Keymanager::getFileKey( $rootView, $userId, $filePath ) ) { @@ -135,10 +136,8 @@ class Proxy extends \OC_FileProxy { // Fetch public keys for all users who will share the file $publicKeys = Keymanager::getPublicKeys( $rootView, $uniqueUserIds ); - - \OC_FileProxy::$enabled = false; - - // Encrypt plain keyfile to multiple sharefiles + + // Encrypt plain keyfile to multiple sharefiles $multiEncrypted = Crypt::multiKeyEncrypt( $plainKey, $publicKeys ); // Save sharekeys to user folders @@ -157,7 +156,7 @@ class Proxy extends \OC_FileProxy { \OC\Files\Filesystem::putFileInfo( $path, array( 'encrypted'=>true, 'size' => $size ), '' ); // Re-enable proxy - our work is done - \OC_FileProxy::$enabled = true; + \OC_FileProxy::$enabled = $proxyStatus; } } @@ -182,9 +181,10 @@ class Proxy extends \OC_FileProxy { // TODO check for existing key file and reuse it if possible to avoid problems with versioning etc. // Disable encryption proxy to prevent recursive calls - \OC_FileProxy::$enabled = false; - - // If data is a catfile + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + + // If data is a catfile if ( Crypt::mode() == 'server' && Crypt::isCatfileContent( $data ) // TODO: Do we really need this check? Can't we assume it is properly encrypted? @@ -215,7 +215,7 @@ class Proxy extends \OC_FileProxy { } - \OC_FileProxy::$enabled = true; + \OC_FileProxy::$enabled = $proxyStatus; if ( ! isset( $plainData ) ) { @@ -240,7 +240,8 @@ class Proxy extends \OC_FileProxy { $path = Keymanager::fixPartialFilePath( $path ); // Disable encryption proxy to prevent recursive calls - \OC_FileProxy::$enabled = false; + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; $view = new \OC_FilesystemView( '/' ); @@ -265,7 +266,7 @@ class Proxy extends \OC_FileProxy { } - \OC_FileProxy::$enabled = true; + \OC_FileProxy::$enabled = $proxyStatus; // If we don't return true then file delete will fail; better // to leave orphaned keyfiles than to disallow file deletion @@ -282,6 +283,7 @@ class Proxy extends \OC_FileProxy { { // Disable encryption proxy to prevent recursive calls + $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; $view = new \OC_FilesystemView('/'); @@ -318,7 +320,7 @@ class Proxy extends \OC_FileProxy { // Rename keyfile so it isn't orphaned $result = $view->rename($oldKeyfilePath, $newKeyfilePath); - \OC_FileProxy::$enabled = true; + \OC_FileProxy::$enabled = $proxyStatus; return $result; @@ -337,9 +339,10 @@ class Proxy extends \OC_FileProxy { $path_f = implode( '/', array_slice( $path_split, 3 ) ); // Disable encryption proxy to prevent recursive calls - \OC_FileProxy::$enabled = false; - - $meta = stream_get_meta_data( $result ); + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + + $meta = stream_get_meta_data( $result ); $view = new \OC_FilesystemView( '' ); @@ -369,13 +372,13 @@ class Proxy extends \OC_FileProxy { // NOTE: this is the case for new files saved via WebDAV - if ( - $view->file_exists( $path ) - and $view->filesize( $path ) > 0 - ) { - $x = $view->file_get_contents( $path ); - - $tmp = tmpfile(); +// if ( +// $view->file_exists( $path ) +// and $view->filesize( $path ) > 0 +// ) { +// $x = $view->file_get_contents( $path ); +// +// $tmp = tmpfile(); // // Make a temporary copy of the original file // \OCP\Files::streamCopy( $result, $tmp ); @@ -387,14 +390,14 @@ class Proxy extends \OC_FileProxy { // // fclose( $tmp ); - } +// } $result = fopen( 'crypt://'.$path_f, $meta['mode'] ); } // Re-enable the proxy - \OC_FileProxy::$enabled = true; + \OC_FileProxy::$enabled = $proxyStatus; return $result; @@ -417,15 +420,15 @@ class Proxy extends \OC_FileProxy { // if path is a folder do nothing if(is_array($data) && array_key_exists('size', $data)) { // Disable encryption proxy to prevent recursive calls + $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; + // get file size $data['size'] = self::postFileSize($path, $data['size']); // Re-enable the proxy - \OC_FileProxy::$enabled = true; - - trigger_error('postGetFileInfo '.$path.' size: '.$data['size']); + \OC_FileProxy::$enabled = $proxyStatus; } return $data; @@ -437,7 +440,7 @@ class Proxy extends \OC_FileProxy { $cached = \OC\Files\Filesystem::getFileInfo( $path, '' ); - $data['size'] = $cached['size']; + $data['size'] = $cached['unencrypted_size']; } @@ -453,56 +456,20 @@ class Proxy extends \OC_FileProxy { return $size; } + $path = Keymanager::fixPartialFilePath( $path ); + // Reformat path for use with OC_FSV $path_split = explode('/', $path); $path_f = implode('/', array_slice($path_split, 3)); - $userId = \OCP\User::getUser(); - $util = new Util( $view, $userId ); - - - // FIXME: is there a better solution to check if file belongs to files path? - // only get file size if file is in 'files' path - if (count($path_split) >= 2 && $path_split[2] == 'files' && $util->isEncryptedPath($path)) { - - // Disable encryption proxy to prevent recursive calls - \OC_FileProxy::$enabled = false; - - // open stream - $result = fopen('crypt://' . $path_f, "r"); - - if(is_resource($result)) { - // don't trust the given size, allways get the size from filesystem - $size = $view->filesize($path); - - // calculate last chunk nr - $lastChunckNr = floor($size / 8192); - - // calculate last chunk position - $lastChunckPos = ($lastChunckNr * 8192); - - // seek to end - fseek($result, $lastChunckPos); - - // get the content of the last chunck - $lastChunkContent = fgets($result); - - // calc the real file size with the size of the last chunk - $realSize = (($lastChunckNr * 6126) + strlen($lastChunkContent)); - - // set the size - $size = $realSize; - } - - // enable proxy - \OC_FileProxy::$enabled = true; - - return $size; + // get file info from database/cache + $fileInfo = \OC\Files\Filesystem::getFileInfo($path_f); + // if file is encrypted return real file size + if(is_array($fileInfo) && $fileInfo['encrypted'] == 1) { + return $fileInfo['unencrypted_size']; } else { - - return $size; - + return $fileInfo['size']; } } } diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 9a37c3b08e..7e42627f8c 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -64,6 +64,7 @@ class Stream { private $count; private $writeCache; public $size; + public $unencryptedSize; private $publicKey; private $keyfile; private $encKeyfile; @@ -105,6 +106,7 @@ class Stream { } else { // Disable fileproxies so we can get the file size and open the source file without recursive encryption + $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; if ( @@ -116,6 +118,7 @@ class Stream { // We're writing a new file so start write counter with 0 bytes $this->size = 0; + $this->unencryptedSize = 0; } else { @@ -129,7 +132,7 @@ class Stream { $this->handle = $this->rootView->fopen( $this->rawPath, $mode ); - \OC_FileProxy::$enabled = true; + \OC_FileProxy::$enabled = $proxyStatus; if ( ! is_resource( $this->handle ) ) { @@ -301,7 +304,7 @@ class Stream { // automatically attempted when the file is written to disk - // we are handling that separately here and we don't want to // get into an infinite loop - \OC_FileProxy::$enabled = false; + //\OC_FileProxy::$enabled = false; // Get the length of the unencrypted data that we are handling $length = strlen( $data ); @@ -438,7 +441,8 @@ class Stream { } $this->size = max( $this->size, $pointer + $length ); - + $this->unencryptedSize += $length; + return $length; } @@ -501,9 +505,7 @@ class Stream { $this->meta['mode']!='r' and $this->meta['mode']!='rb' ) { - - \OC\Files\Filesystem::putFileInfo( $this->relPath, array( 'encrypted' => true, 'size' => $this->size ), '' ); - + \OC\Files\Filesystem::putFileInfo( $this->relPath, array( 'encrypted' => 1, 'size' => $this->size, 'unencrypted_size' => $this->unencryptedSize ), '' ); } return fclose( $this->handle ); diff --git a/db_structure.xml b/db_structure.xml index dce90697b1..366f51a82d 100644 --- a/db_structure.xml +++ b/db_structure.xml @@ -288,6 +288,14 @@ 4 + + unencrypted_size + integer + + true + 8 + + etag text diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 71b70abe3f..4e32ff2ba8 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -117,7 +117,7 @@ class Cache { $params = array($file); } $query = \OC_DB::prepare( - 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` + 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `unencrypted_size`, `etag` FROM `*PREFIX*filecache` ' . $where); $result = $query->execute($params); $data = $result->fetchRow(); @@ -133,6 +133,7 @@ class Cache { $data['size'] = (int)$data['size']; $data['mtime'] = (int)$data['mtime']; $data['encrypted'] = (bool)$data['encrypted']; + $data['unencrypted_size'] = (int)$data['unencrypted_size']; $data['storage'] = $this->storageId; $data['mimetype'] = $this->getMimetype($data['mimetype']); $data['mimepart'] = $this->getMimetype($data['mimepart']); @@ -151,7 +152,7 @@ class Cache { $fileId = $this->getId($folder); if ($fileId > -1) { $query = \OC_DB::prepare( - 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` + 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `unencrypted_size`, `etag` FROM `*PREFIX*filecache` WHERE parent = ? ORDER BY `name` ASC'); $result = $query->execute(array($fileId)); $files = $result->fetchAll(); @@ -234,7 +235,7 @@ class Cache { * @return array */ function buildParts(array $data) { - $fields = array('path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'encrypted', 'etag'); + $fields = array('path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'encrypted', 'unencrypted_size', 'etag'); $params = array(); $queryParts = array(); foreach ($data as $name => $value) { @@ -391,7 +392,7 @@ class Cache { */ public function search($pattern) { $query = \OC_DB::prepare(' - SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` + SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `unencrypted_size`, `etag` FROM `*PREFIX*filecache` WHERE `name` LIKE ? AND `storage` = ?' ); $result = $query->execute(array($pattern, $this->numericId)); @@ -417,7 +418,7 @@ class Cache { $where = '`mimepart` = ?'; } $query = \OC_DB::prepare(' - SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` + SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `unencrypted_size`, `etag` FROM `*PREFIX*filecache` WHERE ' . $where . ' AND `storage` = ?' ); $mimetype = $this->getMimetypeId($mimetype);