]> source.dussan.org Git - nextcloud-server.git/commitdiff
extend the encryption stream wrapper to handle local files and add a fall back for...
authorBjoern Schiessle <schiessle@owncloud.com>
Tue, 17 Dec 2013 17:13:46 +0000 (18:13 +0100)
committerBjoern Schiessle <schiessle@owncloud.com>
Wed, 18 Dec 2013 14:43:50 +0000 (15:43 +0100)
apps/files_encryption/lib/helper.php
apps/files_encryption/lib/stream.php
apps/files_encryption/lib/util.php

index 17bcac5c585dd050c5f82546f77b33892094c257..f893cf16e5a4718e4dfee491885685e4c6501de6 100755 (executable)
@@ -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;
+       }
 }
 
index c3cbdd54f564a9d9bea8d9fdb8f9fdb82506c783..b3bf34ddb827b6e509a172b96059e60e3b1f418b 100644 (file)
@@ -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
                ) {
index 577b656077f6a007640e032ad145f0010cc50bd8..70398183f8b31cca666898b5bf0ba1e3e5a613c9 100644 (file)
@@ -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);