summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/base.php1
-rw-r--r--lib/streamwrappers.php86
-rw-r--r--tests/lib/streamwrappers.php31
3 files changed, 118 insertions, 0 deletions
diff --git a/lib/base.php b/lib/base.php
index 336ff9fa231..4e24f9f44ac 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -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']);
diff --git a/lib/streamwrappers.php b/lib/streamwrappers.php
index 05d5598819a..f1e0fa0e1d9 100644
--- a/lib/streamwrappers.php
+++ b/lib/streamwrappers.php
@@ -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);
+ }
+}
diff --git a/tests/lib/streamwrappers.php b/tests/lib/streamwrappers.php
index c4784a62976..17a92c6658c 100644
--- a/tests/lib/streamwrappers.php
+++ b/tests/lib/streamwrappers.php
@@ -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