]> source.dussan.org Git - nextcloud-server.git/commitdiff
truncate decrypted files based on filelength
authorRobin Appelman <icewind@owncloud.com>
Thu, 21 Jun 2012 15:37:53 +0000 (17:37 +0200)
committerRobin Appelman <icewind@owncloud.com>
Thu, 21 Jun 2012 15:38:00 +0000 (17:38 +0200)
apps/files_encryption/lib/crypt.php
apps/files_encryption/lib/cryptstream.php
apps/files_encryption/lib/proxy.php
apps/files_encryption/tests/encryption.php
apps/files_encryption/tests/proxy.php
apps/files_encryption/tests/stream.php
apps/files_encryption/tests/zeros [new file with mode: 0644]
lib/filecache.php

index 4c0ffa978ed8e8d5ce1be8fc68c85692d61e10ff..1c90954cec8840215d93bd605bd20c6a478f0f01 100644 (file)
@@ -206,12 +206,16 @@ class OC_Crypt {
        /**
         * decrypt data in 8192b sized blocks
         */
-       public static function blockDecrypt($data, $key=''){
+       public static function blockDecrypt($data, $key='',$maxLength=0){
                $result='';
                while(strlen($data)){
                        $result.=self::decrypt(substr($data,0,8192),$key);
                        $data=substr($data,8192);
                }
-               return rtrim($result, "\0");
+               if($maxLength>0){
+                       return substr($result,0,$maxLength);
+               }else{
+                       return rtrim($result, "\0");
+               }
        }
 }
index 64fec381dedbc4a12e12ba7bc1912fa1cbbd5e84..4ef7d1e08bb9c06f0fbd1c01bc9482040d2ab51b 100644 (file)
@@ -35,6 +35,7 @@ class OC_CryptStream{
        private $meta=array();//header/meta for source stream
        private $count;
        private $writeCache;
+       private $size;
        private static $rootView;
 
        public function stream_open($path, $mode, $options, &$opened_path){
@@ -45,8 +46,14 @@ class OC_CryptStream{
                if(dirname($path)=='streams' and isset(self::$sourceStreams[basename($path)])){
                        $this->source=self::$sourceStreams[basename($path)]['stream'];
                        $this->path=self::$sourceStreams[basename($path)]['path'];
+                       $this->size=self::$sourceStreams[basename($path)]['size'];
                }else{
                        $this->path=$path;
+                       if($mode=='w' or $mode=='w+' or $mode=='wb' or $mode=='wb+'){
+                               $this->size=0;
+                       }else{
+                               $this->size=self::$rootView->filesize($path,$mode);
+                       }
                        OC_FileProxy::$enabled=false;//disable fileproxies so we can open the source file
                        $this->source=self::$rootView->fopen($path,$mode);
                        OC_FileProxy::$enabled=true;
@@ -77,14 +84,16 @@ class OC_CryptStream{
                        OCP\Util::writeLog('files_encryption','php bug 21641 no longer holds, decryption will not work',OCP\Util::FATAL);
                        die();
                }
+               $pos=ftell($this->source);
                $data=fread($this->source,8192);
                if(strlen($data)){
                        $result=OC_Crypt::decrypt($data);
                }else{
                        $result='';
                }
-               if($this->stream_eof()){
-                       $result=rtrim($result, "\0");
+               $length=$this->size-$pos;
+               if($length<8192){
+                       $result=substr($result,0,$length);
                }
                return $result;
        }
@@ -116,6 +125,8 @@ class OC_CryptStream{
                                $data=substr($data,8192);
                        }
                }
+               $currentPos=ftell($this->source);
+               $this->size=max($this->size,$currentPos);
                return $length;
        }
 
@@ -159,7 +170,7 @@ class OC_CryptStream{
        public function stream_close(){
                $this->flush();
                if($this->meta['mode']!='r' and $this->meta['mode']!='rb'){
-                       OC_FileCache::put($this->path,array('encrypted'=>true),'');
+                       OC_FileCache::put($this->path,array('encrypted'=>true,'size'=>$this->size),'');
                }
                return fclose($this->source);
        }
index b9e719448a3b5087195f8f3ed0a97510586a5b2f..f25e4a662f6ea568bcc6dc245dcef240780041f1 100644 (file)
@@ -66,15 +66,17 @@ class OC_FileProxy_Encryption extends OC_FileProxy{
        public function preFile_put_contents($path,&$data){
                if(self::shouldEncrypt($path)){
                        if (!is_resource($data)) {//stream put contents should have been converter to fopen
+                               $size=strlen($data);
                                $data=OC_Crypt::blockEncrypt($data);
-                               OC_FileCache::put($path,array('encrypted'=>true),'');
+                               OC_FileCache::put($path,array('encrypted'=>true,'size'=>$size),'');
                        }
                }
        }
        
        public function postFile_get_contents($path,$data){
                if(self::isEncrypted($path)){
-                       $data=OC_Crypt::blockDecrypt($data);
+                       $cached=OC_FileCache_Cached::get($path,'');
+                       $data=OC_Crypt::blockDecrypt($data,'',$cached['size']);
                }
                return $data;
        }
@@ -108,4 +110,21 @@ class OC_FileProxy_Encryption extends OC_FileProxy{
                }
                return $mime;
        }
+
+       public function postStat($path,$data){
+               if(self::isEncrypted($path)){
+                       $cached=OC_FileCache_Cached::get($path,'');
+                       $data['size']=$cached['size'];
+               }
+               return $data;
+       }
+
+       public function postFileSize($path,$size){
+               if(self::isEncrypted($path)){
+                       $cached=OC_FileCache_Cached::get($path,'');
+                       return  $cached['size'];
+               }else{
+                       return $size;
+               }
+       }
 }
index 70aa1daf4c3f4f83933fcf763eed5a76504777ed..286770a69f51b5abcb882ac1e7cf6b4d5e94edae 100644 (file)
@@ -66,7 +66,7 @@ class Test_Encryption extends UnitTestCase {
                $this->assertEqual($decrypted,$source);
 
                $encrypted=OC_Crypt::blockEncrypt($source,$key);
-               $decrypted=OC_Crypt::blockDecrypt($encrypted,$key);
+               $decrypted=OC_Crypt::blockDecrypt($encrypted,$key,strlen($source));
                $this->assertEqual($decrypted,$source);
        }
 }
index 5616e2091a9e85e245e9409853dac552b0eae24b..4533289265a316abc47e96299da1125990288048 100644 (file)
@@ -50,6 +50,7 @@ class Test_CryptProxy extends UnitTestCase {
                
                $fromFile=OC_Filesystem::file_get_contents('/file');
                $this->assertNotEqual($original,$stored);
+               $this->assertEqual(strlen($original),strlen($fromFile));
                $this->assertEqual($original,$fromFile);
 
        }
@@ -88,6 +89,20 @@ class Test_CryptProxy extends UnitTestCase {
 
                $fromFile=OC_Filesystem::file_get_contents('/file');
                $this->assertNotEqual($original,$stored);
+               $this->assertEqual(strlen($original),strlen($fromFile));
                $this->assertEqual($original,$fromFile);
+
+               $file=__DIR__.'/zeros';
+               $original=file_get_contents($file);
+
+               OC_Filesystem::file_put_contents('/file',$original);
+
+               OC_FileProxy::$enabled=false;
+               $stored=OC_Filesystem::file_get_contents('/file');
+               OC_FileProxy::$enabled=true;
+
+               $fromFile=OC_Filesystem::file_get_contents('/file');
+               $this->assertNotEqual($original,$stored);
+               $this->assertEqual(strlen($original),strlen($fromFile));
        }
 }
index 4ffeb6210a9d18f871b828c6396cda93cca75fbd..d95ea792f729ba24b1c98e588bab8d291e011cb2 100644 (file)
@@ -10,23 +10,23 @@ class Test_CryptStream extends UnitTestCase {
        private $tmpFiles=array();
        
        function testStream(){
-               $stream=$this->getStream('test1','w');
+               $stream=$this->getStream('test1','w',strlen('foobar'));
                fwrite($stream,'foobar');
                fclose($stream);
 
-               $stream=$this->getStream('test1','r');
+               $stream=$this->getStream('test1','r',strlen('foobar'));
                $data=fread($stream,6);
                fclose($stream);
                $this->assertEqual('foobar',$data);
 
                $file=OC::$SERVERROOT.'/3rdparty/MDB2.php';
                $source=fopen($file,'r');
-               $target=$this->getStream('test2','w');
+               $target=$this->getStream('test2','w',0);
                OCP\Files::streamCopy($source,$target);
                fclose($target);
                fclose($source);
 
-               $stream=$this->getStream('test2','r');
+               $stream=$this->getStream('test2','r',filesize($file));
                $data=stream_get_contents($stream);
                $original=file_get_contents($file);
                $this->assertEqual(strlen($original),strlen($data));
@@ -37,9 +37,10 @@ class Test_CryptStream extends UnitTestCase {
         * get a cryptstream to a temporary file
         * @param string $id
         * @param string $mode
+        * @param int size
         * @return resource
         */
-       function getStream($id,$mode){
+       function getStream($id,$mode,$size){
                if($id===''){
                        $id=uniqid();
                }
@@ -50,7 +51,7 @@ class Test_CryptStream extends UnitTestCase {
                        $file=$this->tmpFiles[$id];
                }
                $stream=fopen($file,$mode);
-               OC_CryptStream::$sourceStreams[$id]=array('path'=>'dummy'.$id,'stream'=>$stream);
+               OC_CryptStream::$sourceStreams[$id]=array('path'=>'dummy'.$id,'stream'=>$stream,'size'=>$size);
                return fopen('crypt://streams/'.$id,$mode);
        }
 
@@ -58,11 +59,24 @@ class Test_CryptStream extends UnitTestCase {
                $file=__DIR__.'/binary';
                $source=file_get_contents($file);
 
-               $stream=$this->getStream('test','w');
+               $stream=$this->getStream('test','w',strlen($source));
                fwrite($stream,$source);
                fclose($stream);
 
-               $stream=$this->getStream('test','r');
+               $stream=$this->getStream('test','r',strlen($source));
+               $data=stream_get_contents($stream);
+               fclose($stream);
+               $this->assertEqual(strlen($data),strlen($source));
+               $this->assertEqual($source,$data);
+
+               $file=__DIR__.'/zeros';
+               $source=file_get_contents($file);
+
+               $stream=$this->getStream('test2','w',strlen($source));
+               fwrite($stream,$source);
+               fclose($stream);
+
+               $stream=$this->getStream('test2','r',strlen($source));
                $data=stream_get_contents($stream);
                fclose($stream);
                $this->assertEqual(strlen($data),strlen($source));
diff --git a/apps/files_encryption/tests/zeros b/apps/files_encryption/tests/zeros
new file mode 100644 (file)
index 0000000..ff982ac
Binary files /dev/null and b/apps/files_encryption/tests/zeros differ
index 9963a5a3baf66be27ab4f5b4917b0995be8356eb..d5458834e08277d1e3d3107cfea475c8323c8e93 100644 (file)
@@ -68,18 +68,18 @@ class OC_FileCache{
                $path=$root.$path;
                $parent=self::getParentId($path);
                $id=self::getId($path,'');
-               if($id!=-1){
-                       self::update($id,$data);
-                       return;
-               }
                if(isset(OC_FileCache_Cached::$savedData[$path])){
-                       $data=array_merge($data,OC_FileCache_Cached::$savedData[$path]);
+                       $data=array_merge(OC_FileCache_Cached::$savedData[$path],$data);
                        unset(OC_FileCache_Cached::$savedData[$path]);
                }
                if(!isset($data['size']) or !isset($data['mtime'])){//save incomplete data for the next time we write it
                        OC_FileCache_Cached::$savedData[$path]=$data;
                        return;
                }
+               if($id!=-1){
+                       self::update($id,$data);
+                       return;
+               }
                if(!isset($data['encrypted'])){
                        $data['encrypted']=false;
                }