]> source.dussan.org Git - nextcloud-server.git/commitdiff
add streamwrapper that provides a callback on stream close
authorRobin Appelman <icewind@owncloud.com>
Fri, 2 Mar 2012 17:42:23 +0000 (18:42 +0100)
committerRobin Appelman <icewind@owncloud.com>
Fri, 2 Mar 2012 17:42:57 +0000 (18:42 +0100)
lib/base.php
lib/streamwrappers.php
tests/lib/streamwrappers.php

index 336ff9fa231fbec4a53c49eeef4b7bc30636270c..4e24f9f44ac96c5ee44ece8b0436a7cef3e82d1c 100644 (file)
@@ -148,6 +148,7 @@ class OC{
                require_once('streamwrappers.php');
                stream_wrapper_register("fakedir", "OC_FakeDirStream");
                stream_wrapper_register('static', 'OC_StaticStreamWrapper');
+               stream_wrapper_register('close', 'OC_CloseStreamWrapper');
                
                // calculate the documentroot
                OC::$DOCUMENTROOT=realpath($_SERVER['DOCUMENT_ROOT']);
index 05d5598819a1488306b47f9935bef64edf473fa9..f1e0fa0e1d9cadffdca404212b1630ae87a80905 100644 (file)
@@ -218,3 +218,89 @@ class OC_StaticStreamWrapper {
                return false;
        }
 }
+
+/**
+ * stream wrapper that provides a callback on stream close
+ */
+class OC_CloseStreamWrapper{
+       public static $callBacks=array();
+       private $path='';
+       private $source;
+       private static $open=array();
+       public function stream_open($path, $mode, $options, &$opened_path){
+               $path=substr($path,strlen('close://'));
+               $this->path=$path;
+               $this->source=fopen($path,$mode);
+               if(is_resource($this->source)){
+                       $this->meta=stream_get_meta_data($this->source);
+               }
+               self::$open[]=$path;
+               return is_resource($this->source);
+       }
+
+       public function stream_seek($offset, $whence=SEEK_SET){
+               fseek($this->source,$offset,$whence);
+       }
+
+       public function stream_tell(){
+               return ftell($this->source);
+       }
+
+       public function stream_read($count){
+               return fread($this->source,$count);
+       }
+
+       public function stream_write($data){
+               return fwrite($this->source,$data);
+       }
+
+       public function stream_set_option($option,$arg1,$arg2){
+               switch($option){
+                       case STREAM_OPTION_BLOCKING:
+                               stream_set_blocking($this->source,$arg1);
+                               break;
+                       case STREAM_OPTION_READ_TIMEOUT:
+                               stream_set_timeout($this->source,$arg1,$arg2);
+                               break;
+                       case STREAM_OPTION_WRITE_BUFFER:
+                               stream_set_write_buffer($this->source,$arg1,$arg2);
+               }
+       }
+
+       public function stream_stat(){
+               return fstat($this->source);
+       }
+
+       public function stream_lock($mode){
+               flock($this->source,$mode);
+       }
+
+       public function stream_flush(){
+               return fflush($this->source);
+       }
+
+       public function stream_eof(){
+               return feof($this->source);
+       }
+
+       public function url_stat($path) {
+               $path=substr($path,strlen('close://'));
+               if(file_exists($path)){
+                       return stat($path);
+               }else{
+                       return false;
+               }
+       }
+
+       public function stream_close(){
+               fclose($this->source);
+               if(isset(self::$callBacks[$this->path])){
+                       call_user_func(self::$callBacks[$this->path],$this->path);
+               }
+       }
+
+       public function unlink($path){
+               $path=substr($path,strlen('close://'));
+               return unlink($path);
+       }
+}
index c4784a62976a1c924839ad73fc7b6e9537d7bd96..17a92c6658c1f12e6a4d490821af44dc605112ae 100644 (file)
@@ -44,4 +44,35 @@ class Test_StreamWrappers extends UnitTestCase {
                clearstatcache();
                $this->assertFalse(file_exists($staticFile));
        }
+
+       public function testCloseStream(){
+               //ensure all basic stream stuff works
+               $sourceFile=OC::$SERVERROOT.'/tests/data/lorem.txt';
+               $tmpFile=OC_Helper::TmpFile('.txt');
+               $file='close://'.$tmpFile;
+               $this->assertTrue(file_exists($file));
+               file_put_contents($file,file_get_contents($sourceFile));
+               $this->assertEqual(file_get_contents($sourceFile),file_get_contents($file));
+               unlink($file);
+               clearstatcache();
+               $this->assertFalse(file_exists($file));
+               
+               //test callback
+               $tmpFile=OC_Helper::TmpFile('.txt');
+               $file='close://'.$tmpFile;
+               OC_CloseStreamWrapper::$callBacks[$tmpFile]=array('Test_StreamWrappers','closeCallBack');
+               $fh=fopen($file,'w');
+               fwrite($fh,'asd');
+               try{
+                       fclose($fh);
+                       $this->fail('Expected exception');
+               }catch(Exception $e){
+                       $path=$e->getMessage();
+                       $this->assertEqual($path,$tmpFile);
+               }
+       }
+
+       public static function closeCallBack($path){
+               throw new Exception($path);
+       }
 }
\ No newline at end of file