aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files_external/3rdparty/icewind/streams/src
diff options
context:
space:
mode:
Diffstat (limited to 'apps/files_external/3rdparty/icewind/streams/src')
-rw-r--r--apps/files_external/3rdparty/icewind/streams/src/CallbackWrapper.php67
-rw-r--r--apps/files_external/3rdparty/icewind/streams/src/DirectoryFilter.php60
-rw-r--r--apps/files_external/3rdparty/icewind/streams/src/DirectoryWrapper.php88
-rw-r--r--apps/files_external/3rdparty/icewind/streams/src/File.php2
-rw-r--r--apps/files_external/3rdparty/icewind/streams/src/IteratorDirectory.php4
-rw-r--r--apps/files_external/3rdparty/icewind/streams/src/NullWrapper.php15
-rw-r--r--apps/files_external/3rdparty/icewind/streams/src/Path.php104
-rw-r--r--apps/files_external/3rdparty/icewind/streams/src/RetryWrapper.php66
-rw-r--r--apps/files_external/3rdparty/icewind/streams/src/SeekableWrapper.php92
-rw-r--r--apps/files_external/3rdparty/icewind/streams/src/Url.php64
-rw-r--r--apps/files_external/3rdparty/icewind/streams/src/UrlCallBack.php121
-rw-r--r--apps/files_external/3rdparty/icewind/streams/src/Wrapper.php31
12 files changed, 673 insertions, 41 deletions
diff --git a/apps/files_external/3rdparty/icewind/streams/src/CallbackWrapper.php b/apps/files_external/3rdparty/icewind/streams/src/CallbackWrapper.php
index fd99aa6ebe8..c5847b95fdb 100644
--- a/apps/files_external/3rdparty/icewind/streams/src/CallbackWrapper.php
+++ b/apps/files_external/3rdparty/icewind/streams/src/CallbackWrapper.php
@@ -13,10 +13,11 @@ namespace Icewind\Streams;
* The following options should be passed in the context when opening the stream
* [
* 'callback' => [
- * 'source' => resource
- * 'read' => function($count){} (optional)
- * 'write' => function($data){} (optional)
- * 'close' => function(){} (optional)
+ * 'source' => resource
+ * 'read' => function($count){} (optional)
+ * 'write' => function($data){} (optional)
+ * 'close' => function(){} (optional)
+ * 'readdir' => function(){} (optional)
* ]
* ]
*
@@ -39,54 +40,56 @@ class CallbackWrapper extends Wrapper {
protected $closeCallback;
/**
+ * @var callable
+ */
+ protected $readDirCallBack;
+
+ /**
* Wraps a stream with the provided callbacks
*
* @param resource $source
* @param callable $read (optional)
* @param callable $write (optional)
* @param callable $close (optional)
+ * @param callable $readDir (optional)
* @return resource
*
* @throws \BadMethodCallException
*/
- public static function wrap($source, $read = null, $write = null, $close = null) {
+ public static function wrap($source, $read = null, $write = null, $close = null, $readDir = null) {
$context = stream_context_create(array(
'callback' => array(
'source' => $source,
'read' => $read,
'write' => $write,
- 'close' => $close
+ 'close' => $close,
+ 'readDir' => $readDir
)
));
- stream_wrapper_register('callback', '\Icewind\Streams\CallbackWrapper');
- try {
- $wrapped = fopen('callback://', 'r+', false, $context);
- } catch (\BadMethodCallException $e) {
- stream_wrapper_unregister('callback');
- throw $e;
- }
- stream_wrapper_unregister('callback');
- return $wrapped;
+ return Wrapper::wrapSource($source, $context, 'callback', '\Icewind\Streams\CallbackWrapper');
}
- public function stream_open($path, $mode, $options, &$opened_path) {
+ protected function open() {
$context = $this->loadContext('callback');
- if (isset($context['read']) and is_callable($context['read'])) {
- $this->readCallback = $context['read'];
- }
- if (isset($context['write']) and is_callable($context['write'])) {
- $this->writeCallback = $context['write'];
- }
- if (isset($context['close']) and is_callable($context['close'])) {
- $this->closeCallback = $context['close'];
- }
+ $this->readCallback = $context['read'];
+ $this->writeCallback = $context['write'];
+ $this->closeCallback = $context['close'];
+ $this->readDirCallBack = $context['readDir'];
return true;
}
+ public function dir_opendir($path, $options) {
+ return $this->open();
+ }
+
+ public function stream_open($path, $mode, $options, &$opened_path) {
+ return $this->open();
+ }
+
public function stream_read($count) {
$result = parent::stream_read($count);
- if ($this->readCallback) {
+ if (is_callable($this->readCallback)) {
call_user_func($this->readCallback, $count);
}
return $result;
@@ -94,7 +97,7 @@ class CallbackWrapper extends Wrapper {
public function stream_write($data) {
$result = parent::stream_write($data);
- if ($this->writeCallback) {
+ if (is_callable($this->writeCallback)) {
call_user_func($this->writeCallback, $data);
}
return $result;
@@ -102,9 +105,17 @@ class CallbackWrapper extends Wrapper {
public function stream_close() {
$result = parent::stream_close();
- if ($this->closeCallback) {
+ if (is_callable($this->closeCallback)) {
call_user_func($this->closeCallback);
}
return $result;
}
+
+ public function dir_readdir() {
+ $result = parent::dir_readdir();
+ if (is_callable($this->readDirCallBack)) {
+ call_user_func($this->readDirCallBack);
+ }
+ return $result;
+ }
}
diff --git a/apps/files_external/3rdparty/icewind/streams/src/DirectoryFilter.php b/apps/files_external/3rdparty/icewind/streams/src/DirectoryFilter.php
new file mode 100644
index 00000000000..4b869699000
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/streams/src/DirectoryFilter.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Copyright (c) 2015 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\Streams;
+
+/**
+ * Wrapper allows filtering of directories
+ *
+ * The filter callback will be called for each entry in the folder
+ * when the callback return false the entry will be filtered out
+ */
+class DirectoryFilter extends DirectoryWrapper {
+ /**
+ * @var callable
+ */
+ private $filter;
+
+ /**
+ * @param string $path
+ * @param array $options
+ * @return bool
+ */
+ public function dir_opendir($path, $options) {
+ $context = $this->loadContext('filter');
+ $this->filter = $context['filter'];
+ return true;
+ }
+
+ /**
+ * @return string
+ */
+ public function dir_readdir() {
+ $file = readdir($this->source);
+ $filter = $this->filter;
+ // keep reading untill we have an accepted entry or we're at the end of the folder
+ while ($file !== false && $filter($file) === false) {
+ $file = readdir($this->source);
+ }
+ return $file;
+ }
+
+ /**
+ * @param resource $source
+ * @param callable $filter
+ * @return resource
+ */
+ public static function wrap($source, callable $filter) {
+ $options = array(
+ 'filter' => array(
+ 'source' => $source,
+ 'filter' => $filter
+ )
+ );
+ return self::wrapWithOptions($options, '\Icewind\Streams\DirectoryFilter');
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/src/DirectoryWrapper.php b/apps/files_external/3rdparty/icewind/streams/src/DirectoryWrapper.php
new file mode 100644
index 00000000000..63e4805a807
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/streams/src/DirectoryWrapper.php
@@ -0,0 +1,88 @@
+<?php
+/**
+ * Copyright (c) 2015 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\Streams;
+
+class DirectoryWrapper implements Directory {
+ /**
+ * @var resource
+ */
+ public $context;
+
+ /**
+ * @var resource
+ */
+ protected $source;
+
+ /**
+ * Load the source from the stream context and return the context options
+ *
+ * @param string $name
+ * @return array
+ * @throws \Exception
+ */
+ protected function loadContext($name) {
+ $context = stream_context_get_options($this->context);
+ if (isset($context[$name])) {
+ $context = $context[$name];
+ } else {
+ throw new \BadMethodCallException('Invalid context, "' . $name . '" options not set');
+ }
+ if (isset($context['source']) and is_resource($context['source'])) {
+ $this->source = $context['source'];
+ } else {
+ throw new \BadMethodCallException('Invalid context, source not set');
+ }
+ return $context;
+ }
+
+ /**
+ * @param string $path
+ * @param array $options
+ * @return bool
+ */
+ public function dir_opendir($path, $options) {
+ $this->loadContext('dir');
+ return true;
+ }
+
+ /**
+ * @return string
+ */
+ public function dir_readdir() {
+ return readdir($this->source);
+ }
+
+ /**
+ * @return bool
+ */
+ public function dir_closedir() {
+ closedir($this->source);
+ return true;
+ }
+
+ /**
+ * @return bool
+ */
+ public function dir_rewinddir() {
+ rewinddir($this->source);
+ return true;
+ }
+
+ /**
+ * @param array $options the options for the context to wrap the stream with
+ * @param string $class
+ * @return resource
+ */
+ protected static function wrapWithOptions($options, $class) {
+ $context = stream_context_create($options);
+ stream_wrapper_register('dirwrapper', $class);
+ $wrapped = opendir('dirwrapper://', $context);
+ stream_wrapper_unregister('dirwrapper');
+ return $wrapped;
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/src/File.php b/apps/files_external/3rdparty/icewind/streams/src/File.php
index 6202ef4a4b4..252b7b8971f 100644
--- a/apps/files_external/3rdparty/icewind/streams/src/File.php
+++ b/apps/files_external/3rdparty/icewind/streams/src/File.php
@@ -21,7 +21,7 @@ interface File {
public function stream_open($path, $mode, $options, &$opened_path);
/**
- * @param string $offset
+ * @param int $offset
* @param int $whence
* @return bool
*/
diff --git a/apps/files_external/3rdparty/icewind/streams/src/IteratorDirectory.php b/apps/files_external/3rdparty/icewind/streams/src/IteratorDirectory.php
index c4eac5d4ed3..6dfa42a8b68 100644
--- a/apps/files_external/3rdparty/icewind/streams/src/IteratorDirectory.php
+++ b/apps/files_external/3rdparty/icewind/streams/src/IteratorDirectory.php
@@ -45,9 +45,9 @@ class IteratorDirectory implements Directory {
} else {
throw new \BadMethodCallException('Invalid context, "' . $name . '" options not set');
}
- if (isset($context['iterator']) and $context['iterator'] instanceof \Iterator) {
+ if (isset($context['iterator'])) {
$this->iterator = $context['iterator'];
- } else if (isset($context['array']) and is_array($context['array'])) {
+ } else if (isset($context['array'])) {
$this->iterator = new \ArrayIterator($context['array']);
} else {
throw new \BadMethodCallException('Invalid context, iterator or array not set');
diff --git a/apps/files_external/3rdparty/icewind/streams/src/NullWrapper.php b/apps/files_external/3rdparty/icewind/streams/src/NullWrapper.php
index 8cbaaa756d3..b6c71d98fc4 100644
--- a/apps/files_external/3rdparty/icewind/streams/src/NullWrapper.php
+++ b/apps/files_external/3rdparty/icewind/streams/src/NullWrapper.php
@@ -24,19 +24,16 @@ class NullWrapper extends Wrapper {
'null' => array(
'source' => $source)
));
- stream_wrapper_register('null', '\Icewind\Streams\NullWrapper');
- try {
- $wrapped = fopen('null://', 'r+', false, $context);
- } catch (\BadMethodCallException $e) {
- stream_wrapper_unregister('null');
- throw $e;
- }
- stream_wrapper_unregister('null');
- return $wrapped;
+ return Wrapper::wrapSource($source, $context, 'null', '\Icewind\Streams\NullWrapper');
}
public function stream_open($path, $mode, $options, &$opened_path) {
$this->loadContext('null');
return true;
}
+
+ public function dir_opendir($path, $options) {
+ $this->loadContext('null');
+ return true;
+ }
}
diff --git a/apps/files_external/3rdparty/icewind/streams/src/Path.php b/apps/files_external/3rdparty/icewind/streams/src/Path.php
new file mode 100644
index 00000000000..46d2156b69a
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/streams/src/Path.php
@@ -0,0 +1,104 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\Streams;
+
+/**
+ * A string-like object that automatically registers a stream wrapper when used and removes the stream wrapper when no longer used
+ *
+ * Can optionally pass context options to the stream wrapper
+ */
+class Path {
+
+ /**
+ * @var bool
+ */
+ protected $registered = false;
+
+ /**
+ * @var string
+ */
+ protected $protocol;
+
+ /**
+ * @var string
+ */
+ protected $class;
+
+ /**
+ * @var array
+ */
+ protected $contextOptions;
+
+ /**
+ * @param string $class
+ * @param array $contextOptions
+ */
+ public function __construct($class, $contextOptions = array()) {
+ $this->class = $class;
+ $this->contextOptions = $contextOptions;
+ }
+
+ public function getProtocol() {
+ if (!$this->protocol) {
+ $this->protocol = 'auto' . uniqid();
+ }
+ return $this->protocol;
+ }
+
+ public function wrapPath($path) {
+ return $this->getProtocol() . '://' . $path;
+ }
+
+ protected function register() {
+ if (!$this->registered) {
+ $this->appendDefaultContent($this->getProtocol(), $this->contextOptions);
+ stream_wrapper_register($this->getProtocol(), $this->class);
+ $this->registered = true;
+ }
+ }
+
+ protected function unregister() {
+ stream_wrapper_unregister($this->getProtocol());
+ $this->unsetDefaultContent($this->getProtocol());
+ $this->registered = false;
+ }
+
+ /**
+ * Add values to the default stream context
+ *
+ * @param string $key
+ * @param array $values
+ */
+ protected function appendDefaultContent($key, $values) {
+ $context = stream_context_get_default();
+ $defaults = stream_context_get_options($context);
+ $defaults[$key] = $values;
+ stream_context_set_default($defaults);
+ }
+
+ /**
+ * Remove values from the default stream context
+ *
+ * @param string $key
+ */
+ protected function unsetDefaultContent($key) {
+ $context = stream_context_get_default();
+ $defaults = stream_context_get_options($context);
+ unset($defaults[$key]);
+ stream_context_set_default($defaults);
+ }
+
+ public function __toString() {
+ $this->register();
+ return $this->protocol . '://';
+ }
+
+ public function __destruct() {
+ $this->unregister();
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/src/RetryWrapper.php b/apps/files_external/3rdparty/icewind/streams/src/RetryWrapper.php
new file mode 100644
index 00000000000..84b43f6bd02
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/streams/src/RetryWrapper.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Copyright (c) 2016 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\Streams;
+
+/**
+ * Wrapper that retries reads/writes to remote streams that dont deliver/recieve all requested data at once
+ */
+class RetryWrapper extends Wrapper {
+
+ /**
+ * Wraps a stream with the provided callbacks
+ *
+ * @param resource $source
+ * @return resource
+ */
+ public static function wrap($source) {
+ $context = stream_context_create(array(
+ 'retry' => array(
+ 'source' => $source
+ )
+ ));
+ return Wrapper::wrapSource($source, $context, 'retry', '\Icewind\Streams\RetryWrapper');
+ }
+
+ protected function open() {
+ $this->loadContext('retry');
+ return true;
+ }
+
+ public function dir_opendir($path, $options) {
+ return false;
+ }
+
+ public function stream_open($path, $mode, $options, &$opened_path) {
+ return $this->open();
+ }
+
+ public function stream_read($count) {
+ $result = parent::stream_read($count);
+
+ $bytesReceived = strlen($result);
+ while ($bytesReceived < $count && !$this->stream_eof()) {
+ $result .= parent::stream_read($count - $bytesReceived);
+ $bytesReceived = strlen($result);
+ }
+
+ return $result;
+ }
+
+ public function stream_write($data) {
+ $bytesToSend = strlen($data);
+ $result = parent::stream_write($data);
+
+ while ($result < $bytesToSend && !$this->stream_eof()) {
+ $dataLeft = substr($data, $result);
+ $result += parent::stream_write($dataLeft);
+ }
+
+ return $result;
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/src/SeekableWrapper.php b/apps/files_external/3rdparty/icewind/streams/src/SeekableWrapper.php
new file mode 100644
index 00000000000..d41fd73ec9c
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/streams/src/SeekableWrapper.php
@@ -0,0 +1,92 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\Streams;
+
+/**
+ * Wrapper that provides callbacks for write, read and close
+ *
+ * The following options should be passed in the context when opening the stream
+ * [
+ * 'callback' => [
+ * 'source' => resource
+ * ]
+ * ]
+ *
+ * All callbacks are called after the operation is executed on the source stream
+ */
+class SeekableWrapper extends Wrapper {
+ /**
+ * @var resource
+ */
+ protected $cache;
+
+ /**
+ * Wraps a stream to make it seekable
+ *
+ * @param resource $source
+ * @return resource
+ *
+ * @throws \BadMethodCallException
+ */
+ public static function wrap($source) {
+ $context = stream_context_create(array(
+ 'callback' => array(
+ 'source' => $source
+ )
+ ));
+ return Wrapper::wrapSource($source, $context, 'callback', '\Icewind\Streams\SeekableWrapper');
+ }
+
+ public function dir_opendir($path, $options) {
+ return false;
+ }
+
+ public function stream_open($path, $mode, $options, &$opened_path) {
+ $this->loadContext('callback');
+ $this->cache = fopen('php://temp', 'w+');
+ return true;
+ }
+
+ protected function readTill($position) {
+ $current = ftell($this->source);
+ if ($position > $current) {
+ $data = parent::stream_read($position - $current);
+ $cachePosition = ftell($this->cache);
+ fseek($this->cache, $current);
+ fwrite($this->cache, $data);
+ fseek($this->cache, $cachePosition);
+ }
+ }
+
+ public function stream_read($count) {
+ $current = ftell($this->cache);
+ $this->readTill($current + $count);
+ return fread($this->cache, $count);
+ }
+
+ public function stream_seek($offset, $whence = SEEK_SET) {
+ if ($whence === SEEK_SET) {
+ $target = $offset;
+ } else if ($whence === SEEK_CUR) {
+ $current = ftell($this->cache);
+ $target = $current + $offset;
+ } else {
+ return false;
+ }
+ $this->readTill($target);
+ return fseek($this->cache, $target) === 0;
+ }
+
+ public function stream_tell() {
+ return ftell($this->cache);
+ }
+
+ public function stream_eof() {
+ return parent::stream_eof() and (ftell($this->source) === ftell($this->cache));
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/src/Url.php b/apps/files_external/3rdparty/icewind/streams/src/Url.php
new file mode 100644
index 00000000000..d6822608a33
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/streams/src/Url.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\Streams;
+
+/**
+ * Interface for stream wrappers that implement url functions such as unlink, stat
+ */
+interface Url {
+ /**
+ * @param string $path
+ * @param array $options
+ * @return bool
+ */
+ public function dir_opendir($path, $options);
+
+ /**
+ * @param string $path
+ * @param string $mode
+ * @param int $options
+ * @param string &$opened_path
+ * @return bool
+ */
+ public function stream_open($path, $mode, $options, &$opened_path);
+
+ /**
+ * @param string $path
+ * @param int $mode
+ * @param int $options
+ * @return bool
+ */
+ public function mkdir($path, $mode, $options);
+
+ /**
+ * @param string $source
+ * @param string $target
+ * @return bool
+ */
+ public function rename($source, $target);
+
+ /**
+ * @param string $path
+ * @param int $options
+ * @return bool
+ */
+ public function rmdir($path, $options);
+
+ /**
+ * @param string
+ * @return bool
+ */
+ public function unlink($path);
+
+ /**
+ * @param string $path
+ * @param int $flags
+ * @return array
+ */
+ public function url_stat($path, $flags);
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/src/UrlCallBack.php b/apps/files_external/3rdparty/icewind/streams/src/UrlCallBack.php
new file mode 100644
index 00000000000..580bfc6ba22
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/streams/src/UrlCallBack.php
@@ -0,0 +1,121 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\Streams;
+
+/**
+ * Wrapper that provides callbacks for url actions such as fopen, unlink, rename
+ *
+ * Usage:
+ *
+ * $path = UrlCallBack('/path/so/source', function(){
+ * echo 'fopen';
+ * }, function(){
+ * echo 'opendir';
+ * }, function(){
+ * echo 'mkdir';
+ * }, function(){
+ * echo 'rename';
+ * }, function(){
+ * echo 'rmdir';
+ * }, function(){
+ * echo 'unlink';
+ * }, function(){
+ * echo 'stat';
+ * });
+ *
+ * mkdir($path);
+ * ...
+ *
+ * All callbacks are called after the operation is executed on the source stream
+ */
+class UrlCallback extends Wrapper implements Url {
+
+ /**
+ * @param string $source
+ * @param callable $fopen
+ * @param callable $opendir
+ * @param callable $mkdir
+ * @param callable $rename
+ * @param callable $rmdir
+ * @param callable $unlink
+ * @param callable $stat
+ * @return \Icewind\Streams\Path
+ *
+ * @throws \BadMethodCallException
+ * @throws \Exception
+ */
+ public static function wrap($source, $fopen = null, $opendir = null, $mkdir = null, $rename = null, $rmdir = null,
+ $unlink = null, $stat = null) {
+ $options = array(
+ 'source' => $source,
+ 'fopen' => $fopen,
+ 'opendir' => $opendir,
+ 'mkdir' => $mkdir,
+ 'rename' => $rename,
+ 'rmdir' => $rmdir,
+ 'unlink' => $unlink,
+ 'stat' => $stat
+ );
+ return new Path('\Icewind\Streams\UrlCallBack', $options);
+ }
+
+ protected function loadContext($url) {
+ list($protocol) = explode('://', $url);
+ $options = stream_context_get_options($this->context);
+ return $options[$protocol];
+ }
+
+ protected function callCallBack($context, $callback) {
+ if (is_callable($context[$callback])) {
+ call_user_func($context[$callback]);
+ }
+ }
+
+ public function stream_open($path, $mode, $options, &$opened_path) {
+ $context = $this->loadContext($path);
+ $this->callCallBack($context, 'fopen');
+ $this->setSourceStream(fopen($context['source'], $mode));
+ return true;
+ }
+
+ public function dir_opendir($path, $options) {
+ $context = $this->loadContext($path);
+ $this->callCallBack($context, 'opendir');
+ $this->setSourceStream(opendir($context['source']));
+ return true;
+ }
+
+ public function mkdir($path, $mode, $options) {
+ $context = $this->loadContext($path);
+ $this->callCallBack($context, 'mkdir');
+ return mkdir($context['source'], $mode, $options & STREAM_MKDIR_RECURSIVE);
+ }
+
+ public function rmdir($path, $options) {
+ $context = $this->loadContext($path);
+ $this->callCallBack($context, 'rmdir');
+ return rmdir($context['source']);
+ }
+
+ public function rename($source, $target) {
+ $context = $this->loadContext($source);
+ $this->callCallBack($context, 'rename');
+ list(, $target) = explode('://', $target);
+ return rename($context['source'], $target);
+ }
+
+ public function unlink($path) {
+ $context = $this->loadContext($path);
+ $this->callCallBack($context, 'unlink');
+ return unlink($context['source']);
+ }
+
+ public function url_stat($path, $flags) {
+ throw new \Exception('stat is not supported due to php bug 50526');
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/src/Wrapper.php b/apps/files_external/3rdparty/icewind/streams/src/Wrapper.php
index 2e3a6e6cd88..53de2942ca9 100644
--- a/apps/files_external/3rdparty/icewind/streams/src/Wrapper.php
+++ b/apps/files_external/3rdparty/icewind/streams/src/Wrapper.php
@@ -12,7 +12,7 @@ namespace Icewind\Streams;
*
* This wrapper itself doesn't implement any functionality but is just a base class for other wrappers to extend
*/
-abstract class Wrapper implements File {
+abstract class Wrapper implements File, Directory {
/**
* @var resource
*/
@@ -25,6 +25,22 @@ abstract class Wrapper implements File {
*/
protected $source;
+ protected static function wrapSource($source, $context, $protocol, $class) {
+ try {
+ stream_wrapper_register($protocol, $class);
+ if (@rewinddir($source) === false) {
+ $wrapped = fopen($protocol . '://', 'r+', false, $context);
+ } else {
+ $wrapped = opendir($protocol . '://', $context);
+ }
+ } catch (\BadMethodCallException $e) {
+ stream_wrapper_unregister($protocol);
+ throw $e;
+ }
+ stream_wrapper_unregister($protocol);
+ return $wrapped;
+ }
+
/**
* Load the source from the stream context and return the context options
*
@@ -107,4 +123,17 @@ abstract class Wrapper implements File {
public function stream_close() {
return fclose($this->source);
}
+
+ public function dir_readdir() {
+ return readdir($this->source);
+ }
+
+ public function dir_closedir() {
+ closedir($this->source);
+ return true;
+ }
+
+ public function dir_rewinddir() {
+ return rewind($this->source);
+ }
}