]> source.dussan.org Git - nextcloud-server.git/commitdiff
New SMB storage backend
authorRobin Appelman <icewind@owncloud.com>
Tue, 26 Aug 2014 16:46:07 +0000 (18:46 +0200)
committerThomas Müller <thomas.mueller@tmit.eu>
Mon, 16 Feb 2015 12:52:11 +0000 (13:52 +0100)
75 files changed:
apps/files_external/3rdparty/autoload.php [new file with mode: 0644]
apps/files_external/3rdparty/composer.json [new file with mode: 0644]
apps/files_external/3rdparty/composer.lock [new file with mode: 0644]
apps/files_external/3rdparty/composer/ClassLoader.php [new file with mode: 0644]
apps/files_external/3rdparty/composer/autoload_classmap.php [new file with mode: 0644]
apps/files_external/3rdparty/composer/autoload_namespaces.php [new file with mode: 0644]
apps/files_external/3rdparty/composer/autoload_psr4.php [new file with mode: 0644]
apps/files_external/3rdparty/composer/autoload_real.php [new file with mode: 0644]
apps/files_external/3rdparty/composer/installed.json [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/.gitignore [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/.travis.yml [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/LICENSE.txt [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/README.md [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/composer.json [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/Connection.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/ErrorCodes.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/Exception/AccessDeniedException.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/Exception/AlreadyExistsException.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/Exception/AuthenticationException.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectException.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionException.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionRefusedException.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/Exception/Exception.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/Exception/FileInUseException.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/Exception/ForbiddenException.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/Exception/HostDownException.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidHostException.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidRequestException.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidTypeException.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/Exception/NoRouteToHostException.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/Exception/NotEmptyException.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/Exception/NotFoundException.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/Exception/TimedOutException.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/FileInfo.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/IFileInfo.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/IShare.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/NativeFileInfo.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/NativeServer.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/NativeShare.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/NativeState.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/NativeStream.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/Parser.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/RawConnection.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/Server.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/src/Share.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/tests/AbstractShare.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/tests/NativeShare.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/tests/NativeStream.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/tests/Parser.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/tests/Server.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/tests/Share.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/tests/bootstrap.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/tests/config.json [new file with mode: 0644]
apps/files_external/3rdparty/icewind/smb/tests/phpunit.xml [new file with mode: 0644]
apps/files_external/3rdparty/icewind/streams/.gitignore [new file with mode: 0644]
apps/files_external/3rdparty/icewind/streams/.travis.yml [new file with mode: 0644]
apps/files_external/3rdparty/icewind/streams/README.md [new file with mode: 0644]
apps/files_external/3rdparty/icewind/streams/composer.json [new file with mode: 0644]
apps/files_external/3rdparty/icewind/streams/src/CallbackWrapper.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/streams/src/Directory.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/streams/src/File.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/streams/src/IteratorDirectory.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/streams/src/NullWrapper.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/streams/src/Wrapper.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/streams/tests/CallbackWrapper.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/streams/tests/IteratorDirectory.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/streams/tests/NullWrapper.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/streams/tests/Wrapper.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/streams/tests/bootstrap.php [new file with mode: 0644]
apps/files_external/3rdparty/icewind/streams/tests/phpunit.xml [new file with mode: 0644]
apps/files_external/3rdparty/smb4php/smb.php [deleted file]
apps/files_external/appinfo/app.php
apps/files_external/lib/smb.php
apps/files_external/lib/smb_oc.php
apps/files_external/tests/backends/smb.php

diff --git a/apps/files_external/3rdparty/autoload.php b/apps/files_external/3rdparty/autoload.php
new file mode 100644 (file)
index 0000000..78e3de4
--- /dev/null
@@ -0,0 +1,7 @@
+<?php
+
+// autoload.php @generated by Composer
+
+require_once __DIR__ . '/composer' . '/autoload_real.php';
+
+return ComposerAutoloaderInit98fe9b281934250b3a93f69a5ce843b3::getLoader();
diff --git a/apps/files_external/3rdparty/composer.json b/apps/files_external/3rdparty/composer.json
new file mode 100644 (file)
index 0000000..b131565
--- /dev/null
@@ -0,0 +1,13 @@
+{
+       "name": "files_external/3rdparty",
+       "description": "3rdparty components for files_external",
+       "license": "MIT",
+       "config": {
+               "vendor-dir": "."
+       },
+       "require": {
+               "icewind/smb": "dev-master",
+               "icewind/streams": "0.2"
+       }
+}
+
diff --git a/apps/files_external/3rdparty/composer.lock b/apps/files_external/3rdparty/composer.lock
new file mode 100644 (file)
index 0000000..3da75b2
--- /dev/null
@@ -0,0 +1,101 @@
+{
+    "_readme": [
+        "This file locks the dependencies of your project to a known state",
+        "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
+        "This file is @generated automatically"
+    ],
+    "hash": "c854ee7f5bdcb3f2c8ee0a8cfe5e193a",
+    "packages": [
+        {
+            "name": "icewind/smb",
+            "version": "dev-master",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/icewind1991/SMB.git",
+                "reference": "ededbfbaa3d7124ce8d4b6c119cd225fa342916d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/icewind1991/SMB/zipball/ededbfbaa3d7124ce8d4b6c119cd225fa342916d",
+                "reference": "ededbfbaa3d7124ce8d4b6c119cd225fa342916d",
+                "shasum": ""
+            },
+            "require": {
+                "icewind/streams": "0.2.x",
+                "php": ">=5.3"
+            },
+            "require-dev": {
+                "satooshi/php-coveralls": "dev-master"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Icewind\\SMB\\": "src/",
+                    "Icewind\\SMB\\Test\\": "tests/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Robin Appelman",
+                    "email": "icewind@owncloud.com"
+                }
+            ],
+            "description": "php wrapper for smbclient and libsmbclient-php",
+            "time": "2015-02-10 16:37:37"
+        },
+        {
+            "name": "icewind/streams",
+            "version": "0.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/icewind1991/Streams.git",
+                "reference": "5aae45f2ddd3d1a6e2a496dd5d1e7857bfeb605a"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/icewind1991/Streams/zipball/5aae45f2ddd3d1a6e2a496dd5d1e7857bfeb605a",
+                "reference": "5aae45f2ddd3d1a6e2a496dd5d1e7857bfeb605a",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3"
+            },
+            "require-dev": {
+                "satooshi/php-coveralls": "dev-master"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Icewind\\Streams\\Tests\\": "tests/",
+                    "Icewind\\Streams\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Robin Appelman",
+                    "email": "icewind@owncloud.com"
+                }
+            ],
+            "description": "A set of generic stream wrappers",
+            "time": "2014-07-30 23:46:15"
+        }
+    ],
+    "packages-dev": [],
+    "aliases": [],
+    "minimum-stability": "stable",
+    "stability-flags": {
+        "icewind/smb": 20
+    },
+    "prefer-stable": false,
+    "prefer-lowest": false,
+    "platform": [],
+    "platform-dev": []
+}
diff --git a/apps/files_external/3rdparty/composer/ClassLoader.php b/apps/files_external/3rdparty/composer/ClassLoader.php
new file mode 100644 (file)
index 0000000..5e1469e
--- /dev/null
@@ -0,0 +1,413 @@
+<?php
+
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ *     Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\Autoload;
+
+/**
+ * ClassLoader implements a PSR-0 class loader
+ *
+ * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
+ *
+ *     $loader = new \Composer\Autoload\ClassLoader();
+ *
+ *     // register classes with namespaces
+ *     $loader->add('Symfony\Component', __DIR__.'/component');
+ *     $loader->add('Symfony',           __DIR__.'/framework');
+ *
+ *     // activate the autoloader
+ *     $loader->register();
+ *
+ *     // to enable searching the include path (eg. for PEAR packages)
+ *     $loader->setUseIncludePath(true);
+ *
+ * In this example, if you try to use a class in the Symfony\Component
+ * namespace or one of its children (Symfony\Component\Console for instance),
+ * the autoloader will first look for the class under the component/
+ * directory, and it will then fallback to the framework/ directory if not
+ * found before giving up.
+ *
+ * This class is loosely based on the Symfony UniversalClassLoader.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ */
+class ClassLoader
+{
+    // PSR-4
+    private $prefixLengthsPsr4 = array();
+    private $prefixDirsPsr4 = array();
+    private $fallbackDirsPsr4 = array();
+
+    // PSR-0
+    private $prefixesPsr0 = array();
+    private $fallbackDirsPsr0 = array();
+
+    private $useIncludePath = false;
+    private $classMap = array();
+
+    private $classMapAuthoritative = false;
+
+    public function getPrefixes()
+    {
+        if (!empty($this->prefixesPsr0)) {
+            return call_user_func_array('array_merge', $this->prefixesPsr0);
+        }
+
+        return array();
+    }
+
+    public function getPrefixesPsr4()
+    {
+        return $this->prefixDirsPsr4;
+    }
+
+    public function getFallbackDirs()
+    {
+        return $this->fallbackDirsPsr0;
+    }
+
+    public function getFallbackDirsPsr4()
+    {
+        return $this->fallbackDirsPsr4;
+    }
+
+    public function getClassMap()
+    {
+        return $this->classMap;
+    }
+
+    /**
+     * @param array $classMap Class to filename map
+     */
+    public function addClassMap(array $classMap)
+    {
+        if ($this->classMap) {
+            $this->classMap = array_merge($this->classMap, $classMap);
+        } else {
+            $this->classMap = $classMap;
+        }
+    }
+
+    /**
+     * Registers a set of PSR-0 directories for a given prefix, either
+     * appending or prepending to the ones previously set for this prefix.
+     *
+     * @param string       $prefix  The prefix
+     * @param array|string $paths   The PSR-0 root directories
+     * @param bool         $prepend Whether to prepend the directories
+     */
+    public function add($prefix, $paths, $prepend = false)
+    {
+        if (!$prefix) {
+            if ($prepend) {
+                $this->fallbackDirsPsr0 = array_merge(
+                    (array) $paths,
+                    $this->fallbackDirsPsr0
+                );
+            } else {
+                $this->fallbackDirsPsr0 = array_merge(
+                    $this->fallbackDirsPsr0,
+                    (array) $paths
+                );
+            }
+
+            return;
+        }
+
+        $first = $prefix[0];
+        if (!isset($this->prefixesPsr0[$first][$prefix])) {
+            $this->prefixesPsr0[$first][$prefix] = (array) $paths;
+
+            return;
+        }
+        if ($prepend) {
+            $this->prefixesPsr0[$first][$prefix] = array_merge(
+                (array) $paths,
+                $this->prefixesPsr0[$first][$prefix]
+            );
+        } else {
+            $this->prefixesPsr0[$first][$prefix] = array_merge(
+                $this->prefixesPsr0[$first][$prefix],
+                (array) $paths
+            );
+        }
+    }
+
+    /**
+     * Registers a set of PSR-4 directories for a given namespace, either
+     * appending or prepending to the ones previously set for this namespace.
+     *
+     * @param string       $prefix  The prefix/namespace, with trailing '\\'
+     * @param array|string $paths   The PSR-0 base directories
+     * @param bool         $prepend Whether to prepend the directories
+     *
+     * @throws \InvalidArgumentException
+     */
+    public function addPsr4($prefix, $paths, $prepend = false)
+    {
+        if (!$prefix) {
+            // Register directories for the root namespace.
+            if ($prepend) {
+                $this->fallbackDirsPsr4 = array_merge(
+                    (array) $paths,
+                    $this->fallbackDirsPsr4
+                );
+            } else {
+                $this->fallbackDirsPsr4 = array_merge(
+                    $this->fallbackDirsPsr4,
+                    (array) $paths
+                );
+            }
+        } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
+            // Register directories for a new namespace.
+            $length = strlen($prefix);
+            if ('\\' !== $prefix[$length - 1]) {
+                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+            }
+            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+            $this->prefixDirsPsr4[$prefix] = (array) $paths;
+        } elseif ($prepend) {
+            // Prepend directories for an already registered namespace.
+            $this->prefixDirsPsr4[$prefix] = array_merge(
+                (array) $paths,
+                $this->prefixDirsPsr4[$prefix]
+            );
+        } else {
+            // Append directories for an already registered namespace.
+            $this->prefixDirsPsr4[$prefix] = array_merge(
+                $this->prefixDirsPsr4[$prefix],
+                (array) $paths
+            );
+        }
+    }
+
+    /**
+     * Registers a set of PSR-0 directories for a given prefix,
+     * replacing any others previously set for this prefix.
+     *
+     * @param string       $prefix The prefix
+     * @param array|string $paths  The PSR-0 base directories
+     */
+    public function set($prefix, $paths)
+    {
+        if (!$prefix) {
+            $this->fallbackDirsPsr0 = (array) $paths;
+        } else {
+            $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
+        }
+    }
+
+    /**
+     * Registers a set of PSR-4 directories for a given namespace,
+     * replacing any others previously set for this namespace.
+     *
+     * @param string       $prefix The prefix/namespace, with trailing '\\'
+     * @param array|string $paths  The PSR-4 base directories
+     *
+     * @throws \InvalidArgumentException
+     */
+    public function setPsr4($prefix, $paths)
+    {
+        if (!$prefix) {
+            $this->fallbackDirsPsr4 = (array) $paths;
+        } else {
+            $length = strlen($prefix);
+            if ('\\' !== $prefix[$length - 1]) {
+                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+            }
+            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+            $this->prefixDirsPsr4[$prefix] = (array) $paths;
+        }
+    }
+
+    /**
+     * Turns on searching the include path for class files.
+     *
+     * @param bool $useIncludePath
+     */
+    public function setUseIncludePath($useIncludePath)
+    {
+        $this->useIncludePath = $useIncludePath;
+    }
+
+    /**
+     * Can be used to check if the autoloader uses the include path to check
+     * for classes.
+     *
+     * @return bool
+     */
+    public function getUseIncludePath()
+    {
+        return $this->useIncludePath;
+    }
+
+    /**
+     * Turns off searching the prefix and fallback directories for classes
+     * that have not been registered with the class map.
+     *
+     * @param bool $classMapAuthoritative
+     */
+    public function setClassMapAuthoritative($classMapAuthoritative)
+    {
+        $this->classMapAuthoritative = $classMapAuthoritative;
+    }
+
+    /**
+     * Should class lookup fail if not found in the current class map?
+     *
+     * @return bool
+     */
+    public function isClassMapAuthoritative()
+    {
+        return $this->classMapAuthoritative;
+    }
+
+    /**
+     * Registers this instance as an autoloader.
+     *
+     * @param bool $prepend Whether to prepend the autoloader or not
+     */
+    public function register($prepend = false)
+    {
+        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
+    }
+
+    /**
+     * Unregisters this instance as an autoloader.
+     */
+    public function unregister()
+    {
+        spl_autoload_unregister(array($this, 'loadClass'));
+    }
+
+    /**
+     * Loads the given class or interface.
+     *
+     * @param  string    $class The name of the class
+     * @return bool|null True if loaded, null otherwise
+     */
+    public function loadClass($class)
+    {
+        if ($file = $this->findFile($class)) {
+            includeFile($file);
+
+            return true;
+        }
+    }
+
+    /**
+     * Finds the path to the file where the class is defined.
+     *
+     * @param string $class The name of the class
+     *
+     * @return string|false The path if found, false otherwise
+     */
+    public function findFile($class)
+    {
+        // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
+        if ('\\' == $class[0]) {
+            $class = substr($class, 1);
+        }
+
+        // class map lookup
+        if (isset($this->classMap[$class])) {
+            return $this->classMap[$class];
+        }
+        if ($this->classMapAuthoritative) {
+            return false;
+        }
+
+        $file = $this->findFileWithExtension($class, '.php');
+
+        // Search for Hack files if we are running on HHVM
+        if ($file === null && defined('HHVM_VERSION')) {
+            $file = $this->findFileWithExtension($class, '.hh');
+        }
+
+        if ($file === null) {
+            // Remember that this class does not exist.
+            return $this->classMap[$class] = false;
+        }
+
+        return $file;
+    }
+
+    private function findFileWithExtension($class, $ext)
+    {
+        // PSR-4 lookup
+        $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
+
+        $first = $class[0];
+        if (isset($this->prefixLengthsPsr4[$first])) {
+            foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
+                if (0 === strpos($class, $prefix)) {
+                    foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
+                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
+                            return $file;
+                        }
+                    }
+                }
+            }
+        }
+
+        // PSR-4 fallback dirs
+        foreach ($this->fallbackDirsPsr4 as $dir) {
+            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
+                return $file;
+            }
+        }
+
+        // PSR-0 lookup
+        if (false !== $pos = strrpos($class, '\\')) {
+            // namespaced class name
+            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
+                . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
+        } else {
+            // PEAR-like class name
+            $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
+        }
+
+        if (isset($this->prefixesPsr0[$first])) {
+            foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
+                if (0 === strpos($class, $prefix)) {
+                    foreach ($dirs as $dir) {
+                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+                            return $file;
+                        }
+                    }
+                }
+            }
+        }
+
+        // PSR-0 fallback dirs
+        foreach ($this->fallbackDirsPsr0 as $dir) {
+            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+                return $file;
+            }
+        }
+
+        // PSR-0 include paths.
+        if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
+            return $file;
+        }
+    }
+}
+
+/**
+ * Scope isolated include.
+ *
+ * Prevents access to $this/self from included files.
+ */
+function includeFile($file)
+{
+    include $file;
+}
diff --git a/apps/files_external/3rdparty/composer/autoload_classmap.php b/apps/files_external/3rdparty/composer/autoload_classmap.php
new file mode 100644 (file)
index 0000000..1bd6482
--- /dev/null
@@ -0,0 +1,9 @@
+<?php
+
+// autoload_classmap.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = $vendorDir;
+
+return array(
+);
diff --git a/apps/files_external/3rdparty/composer/autoload_namespaces.php b/apps/files_external/3rdparty/composer/autoload_namespaces.php
new file mode 100644 (file)
index 0000000..71c9e91
--- /dev/null
@@ -0,0 +1,9 @@
+<?php
+
+// autoload_namespaces.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = $vendorDir;
+
+return array(
+);
diff --git a/apps/files_external/3rdparty/composer/autoload_psr4.php b/apps/files_external/3rdparty/composer/autoload_psr4.php
new file mode 100644 (file)
index 0000000..7cfe0f1
--- /dev/null
@@ -0,0 +1,13 @@
+<?php
+
+// autoload_psr4.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = $vendorDir;
+
+return array(
+    'Icewind\\Streams\\Tests\\' => array($vendorDir . '/icewind/streams/tests'),
+    'Icewind\\Streams\\' => array($vendorDir . '/icewind/streams/src'),
+    'Icewind\\SMB\\Test\\' => array($vendorDir . '/icewind/smb/tests'),
+    'Icewind\\SMB\\' => array($vendorDir . '/icewind/smb/src'),
+);
diff --git a/apps/files_external/3rdparty/composer/autoload_real.php b/apps/files_external/3rdparty/composer/autoload_real.php
new file mode 100644 (file)
index 0000000..3391b32
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+
+// autoload_real.php @generated by Composer
+
+class ComposerAutoloaderInit98fe9b281934250b3a93f69a5ce843b3
+{
+    private static $loader;
+
+    public static function loadClassLoader($class)
+    {
+        if ('Composer\Autoload\ClassLoader' === $class) {
+            require __DIR__ . '/ClassLoader.php';
+        }
+    }
+
+    public static function getLoader()
+    {
+        if (null !== self::$loader) {
+            return self::$loader;
+        }
+
+        spl_autoload_register(array('ComposerAutoloaderInit98fe9b281934250b3a93f69a5ce843b3', 'loadClassLoader'), true, true);
+        self::$loader = $loader = new \Composer\Autoload\ClassLoader();
+        spl_autoload_unregister(array('ComposerAutoloaderInit98fe9b281934250b3a93f69a5ce843b3', 'loadClassLoader'));
+
+        $map = require __DIR__ . '/autoload_namespaces.php';
+        foreach ($map as $namespace => $path) {
+            $loader->set($namespace, $path);
+        }
+
+        $map = require __DIR__ . '/autoload_psr4.php';
+        foreach ($map as $namespace => $path) {
+            $loader->setPsr4($namespace, $path);
+        }
+
+        $classMap = require __DIR__ . '/autoload_classmap.php';
+        if ($classMap) {
+            $loader->addClassMap($classMap);
+        }
+
+        $loader->register(true);
+
+        return $loader;
+    }
+}
+
+function composerRequire98fe9b281934250b3a93f69a5ce843b3($file)
+{
+    require $file;
+}
diff --git a/apps/files_external/3rdparty/composer/installed.json b/apps/files_external/3rdparty/composer/installed.json
new file mode 100644 (file)
index 0000000..03bad8a
--- /dev/null
@@ -0,0 +1,87 @@
+[
+    {
+        "name": "icewind/streams",
+        "version": "0.2",
+        "version_normalized": "0.2.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/icewind1991/Streams.git",
+            "reference": "5aae45f2ddd3d1a6e2a496dd5d1e7857bfeb605a"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/icewind1991/Streams/zipball/5aae45f2ddd3d1a6e2a496dd5d1e7857bfeb605a",
+            "reference": "5aae45f2ddd3d1a6e2a496dd5d1e7857bfeb605a",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3"
+        },
+        "require-dev": {
+            "satooshi/php-coveralls": "dev-master"
+        },
+        "time": "2014-07-30 23:46:15",
+        "type": "library",
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "Icewind\\Streams\\Tests\\": "tests/",
+                "Icewind\\Streams\\": "src/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Robin Appelman",
+                "email": "icewind@owncloud.com"
+            }
+        ],
+        "description": "A set of generic stream wrappers"
+    },
+    {
+        "name": "icewind/smb",
+        "version": "dev-master",
+        "version_normalized": "9999999-dev",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/icewind1991/SMB.git",
+            "reference": "ededbfbaa3d7124ce8d4b6c119cd225fa342916d"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/icewind1991/SMB/zipball/ededbfbaa3d7124ce8d4b6c119cd225fa342916d",
+            "reference": "ededbfbaa3d7124ce8d4b6c119cd225fa342916d",
+            "shasum": ""
+        },
+        "require": {
+            "icewind/streams": "0.2.x",
+            "php": ">=5.3"
+        },
+        "require-dev": {
+            "satooshi/php-coveralls": "dev-master"
+        },
+        "time": "2015-02-10 16:37:37",
+        "type": "library",
+        "installation-source": "source",
+        "autoload": {
+            "psr-4": {
+                "Icewind\\SMB\\": "src/",
+                "Icewind\\SMB\\Test\\": "tests/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Robin Appelman",
+                "email": "icewind@owncloud.com"
+            }
+        ],
+        "description": "php wrapper for smbclient and libsmbclient-php"
+    }
+]
diff --git a/apps/files_external/3rdparty/icewind/smb/.gitignore b/apps/files_external/3rdparty/icewind/smb/.gitignore
new file mode 100644 (file)
index 0000000..3ce5adb
--- /dev/null
@@ -0,0 +1,2 @@
+.idea
+vendor
diff --git a/apps/files_external/3rdparty/icewind/smb/.travis.yml b/apps/files_external/3rdparty/icewind/smb/.travis.yml
new file mode 100644 (file)
index 0000000..c1ac372
--- /dev/null
@@ -0,0 +1,50 @@
+language: php
+php:
+  - 5.3
+  - 5.4
+  - 5.5
+
+env:
+  global:
+    - CURRENT_DIR=`pwd`
+
+before_install:
+  - pass=$(perl -e 'print crypt("test", "password")')
+  - sudo useradd -m -p $pass test
+  - sudo apt-get update -qq
+  - sudo apt-get install samba smbclient libsmbclient-dev libsmbclient
+  - wget -O /tmp/libsmbclient-php.zip https://github.com/eduardok/libsmbclient-php/archive/master.zip
+  - unzip /tmp/libsmbclient-php.zip -d /tmp
+  - cd /tmp/libsmbclient-php-master
+  - phpize && ./configure && make && sudo make install
+  - echo 'extension="libsmbclient.so"' >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
+  - cd $CURRENT_DIR
+  - chmod go+w $HOME
+  - printf "%s\n%s\n" test test|sudo smbpasswd -s test
+  - sudo mkdir /home/test/test
+  - sudo chown test /home/test/test
+  - |
+    echo "[test]
+    comment = test
+    path = /home/test
+    guest ok = yes
+    writeable = yes
+    map archive = yes
+    map system = yes
+    map hidden = yes
+    create mask = 0777
+    inherit permissions = yes" | sudo tee -a /etc/samba/smb.conf
+  - sudo service smbd restart
+  - testparm -s
+
+install:
+  - composer install --dev --no-interaction
+
+script:
+  - mkdir -p build/logs
+  - cd tests
+  - phpunit --coverage-clover ../build/logs/clover.xml --configuration phpunit.xml
+
+after_script:
+ - cd $CURRENT_DIR
+ - php vendor/bin/coveralls -v
diff --git a/apps/files_external/3rdparty/icewind/smb/LICENSE.txt b/apps/files_external/3rdparty/icewind/smb/LICENSE.txt
new file mode 100644 (file)
index 0000000..16e3a10
--- /dev/null
@@ -0,0 +1,19 @@
+Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/apps/files_external/3rdparty/icewind/smb/README.md b/apps/files_external/3rdparty/icewind/smb/README.md
new file mode 100644 (file)
index 0000000..a086471
--- /dev/null
@@ -0,0 +1,136 @@
+SMB
+===
+
+[![Coverage Status](https://img.shields.io/coveralls/icewind1991/SMB.svg)](https://coveralls.io/r/icewind1991/SMB?branch=master)
+[![Build Status](https://travis-ci.org/icewind1991/SMB.svg?branch=master)](https://travis-ci.org/icewind1991/SMB)
+[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/icewind1991/SMB/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/icewind1991/SMB/?branch=master)
+
+PHP wrapper for `smbclient` and [`libsmbclient-php`](https://github.com/eduardok/libsmbclient-php)
+
+- Reuses a single `smbclient` instance for multiple requests
+- Doesn't leak the password to the process list
+- Simple 1-on-1 mapping of SMB commands
+- A stream-based api to remove the need for temporary files
+- Support for using libsmbclient directly trough [`libsmbclient-php`](https://github.com/eduardok/libsmbclient-php)
+
+Examples
+----
+
+### Upload a file ###
+
+```php
+<?php
+use Icewind\SMB\Server;
+
+require('vendor/autoload.php');
+
+$fileToUpload = __FILE__;
+
+$server = new Server('localhost', 'test', 'test');
+$share = $server->getShare('test');
+$share->put($fileToUpload, 'example.txt');
+```
+
+### Download a file ###
+
+```php
+<?php
+use Icewind\SMB\Server;
+
+require('vendor/autoload.php');
+
+$target = __DIR__ . '/target.txt';
+
+$server = new Server('localhost', 'test', 'test');
+$share = $server->getShare('test');
+$share->get('example.txt', $target);
+```
+
+### List shares on the remote server ###
+
+```php
+<?php
+use Icewind\SMB\Server;
+
+require('vendor/autoload.php');
+
+$server = new Server('localhost', 'test', 'test');
+$shares = $server->listShares();
+
+foreach ($shares as $share) {
+       echo $share->getName() . "\n";
+}
+```
+
+### List the content of a folder ###
+
+```php
+<?php
+use Icewind\SMB\Server;
+
+require('vendor/autoload.php');
+
+$server = new Server('localhost', 'test', 'test');
+$share = $server->getShare('test');
+$content = $share->dir('test');
+
+foreach ($content as $info) {
+       echo $name->getName() . "\n";
+       echo "\tsize :" . $info->getSize() . "\n";
+}
+```
+
+### Using read streams
+
+```php
+<?php
+use Icewind\SMB\Server;
+
+require('vendor/autoload.php');
+
+$server = new Server('localhost', 'test', 'test');
+$share = $server->getShare('test');
+
+$fh = $share->read('test.txt');
+echo fread($fh, 4086);
+fclose($fh);
+```
+
+### Using write streams
+
+```php
+<?php
+use Icewind\SMB\Server;
+
+require('vendor/autoload.php');
+
+$server = new Server('localhost', 'test', 'test');
+$share = $server->getShare('test');
+
+$fh = $share->write('test.txt');
+fwrite($fh, 'bar');
+fclose($fh);
+```
+
+### Using libsmbclient-php ###
+
+Install [libsmbclient-php](https://github.com/eduardok/libsmbclient-php)
+
+```php
+<?php
+use Icewind\SMB\Server;
+use Icewind\SMB\NativeServer;
+
+require('vendor/autoload.php');
+
+$fileToUpload = __FILE__;
+
+if (Server::NativeAvailable()) {
+    $server = new NativeServer('localhost', 'test', 'test');
+} else {
+    echo 'libsmbclient-php not available, falling back to wrapping smbclient';
+    $server = new Server('localhost', 'test', 'test');
+}
+$share = $server->getShare('test');
+$share->put($fileToUpload, 'example.txt');
+```
diff --git a/apps/files_external/3rdparty/icewind/smb/composer.json b/apps/files_external/3rdparty/icewind/smb/composer.json
new file mode 100644 (file)
index 0000000..92f4280
--- /dev/null
@@ -0,0 +1,24 @@
+{
+       "name"             : "icewind/smb",
+       "description"      : "php wrapper for smbclient and libsmbclient-php",
+       "license"          : "MIT",
+       "authors"          : [
+               {
+                       "name" : "Robin Appelman",
+                       "email": "icewind@owncloud.com"
+               }
+       ],
+       "require"          : {
+               "php": ">=5.3",
+               "icewind/streams": "0.2.x"
+       },
+       "require-dev": {
+               "satooshi/php-coveralls"  : "dev-master"
+       },
+       "autoload"         : {
+               "psr-4": {
+                       "Icewind\\SMB\\": "src/",
+                       "Icewind\\SMB\\Test\\": "tests/"
+               }
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Connection.php b/apps/files_external/3rdparty/icewind/smb/src/Connection.php
new file mode 100644 (file)
index 0000000..6191b11
--- /dev/null
@@ -0,0 +1,78 @@
+<?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\SMB;
+
+use Icewind\SMB\Exception\AuthenticationException;
+use Icewind\SMB\Exception\ConnectionException;
+use Icewind\SMB\Exception\InvalidHostException;
+
+class Connection extends RawConnection {
+       const DELIMITER = 'smb:';
+
+       /**
+        * send input to smbclient
+        *
+        * @param string $input
+        */
+       public function write($input) {
+               parent::write($input . PHP_EOL);
+       }
+
+       /**
+        * get all unprocessed output from smbclient until the next prompt
+        *
+        * @throws ConnectionException
+        * @return string
+        */
+       public function read() {
+               if (!$this->isValid()) {
+                       throw new ConnectionException();
+               }
+               $line = $this->readLine(); //first line is prompt
+               $this->checkConnectionError($line);
+
+               $output = array();
+               $line = $this->readLine();
+               $length = mb_strlen(self::DELIMITER);
+               while (mb_substr($line, 0, $length) !== self::DELIMITER) { //next prompt functions as delimiter
+                       $output[] .= $line;
+                       $line = $this->readLine();
+               }
+               return $output;
+       }
+
+       /**
+        * check if the first line holds a connection failure
+        *
+        * @param $line
+        * @throws AuthenticationException
+        * @throws InvalidHostException
+        */
+       private function checkConnectionError($line) {
+               $line = rtrim($line, ')');
+               if (substr($line, -23) === ErrorCodes::LogonFailure) {
+                       throw new AuthenticationException();
+               }
+               if (substr($line, -26) === ErrorCodes::BadHostName) {
+                       throw new InvalidHostException();
+               }
+               if (substr($line, -22) === ErrorCodes::Unsuccessful) {
+                       throw new InvalidHostException();
+               }
+               if (substr($line, -28) === ErrorCodes::ConnectionRefused) {
+                       throw new InvalidHostException();
+               }
+       }
+
+       public function close($terminate = true) {
+               if (is_resource($this->getInputStream())) {
+                       $this->write('close' . PHP_EOL);
+               }
+               parent::close($terminate);
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/ErrorCodes.php b/apps/files_external/3rdparty/icewind/smb/src/ErrorCodes.php
new file mode 100644 (file)
index 0000000..d9f2507
--- /dev/null
@@ -0,0 +1,28 @@
+<?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\SMB;
+
+class ErrorCodes {
+       /**
+        * connection errors
+        */
+       const LogonFailure = 'NT_STATUS_LOGON_FAILURE';
+       const BadHostName = 'NT_STATUS_BAD_NETWORK_NAME';
+       const Unsuccessful = 'NT_STATUS_UNSUCCESSFUL';
+       const ConnectionRefused = 'NT_STATUS_CONNECTION_REFUSED';
+
+       const PathNotFound = 'NT_STATUS_OBJECT_PATH_NOT_FOUND';
+       const NoSuchFile = 'NT_STATUS_NO_SUCH_FILE';
+       const ObjectNotFound = 'NT_STATUS_OBJECT_NAME_NOT_FOUND';
+       const NameCollision = 'NT_STATUS_OBJECT_NAME_COLLISION';
+       const AccessDenied = 'NT_STATUS_ACCESS_DENIED';
+       const DirectoryNotEmpty = 'NT_STATUS_DIRECTORY_NOT_EMPTY';
+       const FileIsADirectory = 'NT_STATUS_FILE_IS_A_DIRECTORY';
+       const NotADirectory = 'NT_STATUS_NOT_A_DIRECTORY';
+       const SharingViolation = 'NT_STATUS_SHARING_VIOLATION';
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/AccessDeniedException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/AccessDeniedException.php
new file mode 100644 (file)
index 0000000..4b7d22b
--- /dev/null
@@ -0,0 +1,10 @@
+<?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\SMB\Exception;
+
+class AccessDeniedException extends ConnectException {}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/AlreadyExistsException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/AlreadyExistsException.php
new file mode 100644 (file)
index 0000000..4636b9d
--- /dev/null
@@ -0,0 +1,10 @@
+<?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\SMB\Exception;
+
+class AlreadyExistsException extends InvalidRequestException {}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/AuthenticationException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/AuthenticationException.php
new file mode 100644 (file)
index 0000000..ddf5d7e
--- /dev/null
@@ -0,0 +1,10 @@
+<?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\SMB\Exception;
+
+class AuthenticationException extends ConnectException{}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectException.php
new file mode 100644 (file)
index 0000000..310d441
--- /dev/null
@@ -0,0 +1,10 @@
+<?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\SMB\Exception;
+
+class ConnectException extends Exception {}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionException.php
new file mode 100644 (file)
index 0000000..2103356
--- /dev/null
@@ -0,0 +1,10 @@
+<?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\SMB\Exception;
+
+class ConnectionException extends ConnectException {}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionRefusedException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionRefusedException.php
new file mode 100644 (file)
index 0000000..ffebb4c
--- /dev/null
@@ -0,0 +1,11 @@
+<?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\SMB\Exception;
+
+class ConnectionRefusedException extends ConnectException {
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/Exception.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/Exception.php
new file mode 100644 (file)
index 0000000..3307ad5
--- /dev/null
@@ -0,0 +1,10 @@
+<?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\SMB\Exception;
+
+class Exception extends \Exception {}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/FileInUseException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/FileInUseException.php
new file mode 100644 (file)
index 0000000..46460eb
--- /dev/null
@@ -0,0 +1,10 @@
+<?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\SMB\Exception;
+
+class FileInUseException extends InvalidRequestException {}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/ForbiddenException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/ForbiddenException.php
new file mode 100644 (file)
index 0000000..117d6a4
--- /dev/null
@@ -0,0 +1,10 @@
+<?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\SMB\Exception;
+
+class ForbiddenException extends InvalidRequestException {}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/HostDownException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/HostDownException.php
new file mode 100644 (file)
index 0000000..9ae762b
--- /dev/null
@@ -0,0 +1,11 @@
+<?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\SMB\Exception;
+
+class HostDownException extends ConnectException {
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidHostException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidHostException.php
new file mode 100644 (file)
index 0000000..4b17f1a
--- /dev/null
@@ -0,0 +1,10 @@
+<?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\SMB\Exception;
+
+class InvalidHostException extends ConnectException {}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidRequestException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidRequestException.php
new file mode 100644 (file)
index 0000000..0dccd8b
--- /dev/null
@@ -0,0 +1,31 @@
+<?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\SMB\Exception;
+
+class InvalidRequestException extends Exception {
+       /**
+        * @var string
+        */
+       protected $path;
+
+       /**
+        * @param string $path
+        * @param int $code
+        */
+       public function __construct($path, $code = 0) {
+               parent::__construct('Invalid request for ' . $path, $code);
+               $this->path = $path;
+       }
+
+       /**
+        * @return string
+        */
+       public function getPath() {
+               return $this->path;
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidTypeException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidTypeException.php
new file mode 100644 (file)
index 0000000..63b7930
--- /dev/null
@@ -0,0 +1,10 @@
+<?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\SMB\Exception;
+
+class InvalidTypeException extends InvalidRequestException {}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/NoRouteToHostException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/NoRouteToHostException.php
new file mode 100644 (file)
index 0000000..03daf36
--- /dev/null
@@ -0,0 +1,11 @@
+<?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\SMB\Exception;
+
+class NoRouteToHostException extends ConnectException {
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/NotEmptyException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/NotEmptyException.php
new file mode 100644 (file)
index 0000000..789a76b
--- /dev/null
@@ -0,0 +1,10 @@
+<?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\SMB\Exception;
+
+class NotEmptyException extends InvalidRequestException {}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/NotFoundException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/NotFoundException.php
new file mode 100644 (file)
index 0000000..9ce97cd
--- /dev/null
@@ -0,0 +1,10 @@
+<?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\SMB\Exception;
+
+class NotFoundException extends InvalidRequestException {}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/TimedOutException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/TimedOutException.php
new file mode 100644 (file)
index 0000000..dd57c9b
--- /dev/null
@@ -0,0 +1,11 @@
+<?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\SMB\Exception;
+
+class TimedOutException extends ConnectException {
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/FileInfo.php b/apps/files_external/3rdparty/icewind/smb/src/FileInfo.php
new file mode 100644 (file)
index 0000000..ef9121a
--- /dev/null
@@ -0,0 +1,126 @@
+<?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\SMB;
+
+class FileInfo implements IFileInfo {
+       /*
+        * Mappings of the DOS mode bits, as returned by smbc_getxattr() when the
+        * attribute name "system.dos_attr.mode" (or "system.dos_attr.*" or
+        * "system.*") is specified.
+        */
+       const MODE_READONLY = 0x01;
+       const MODE_HIDDEN = 0x02;
+       const MODE_SYSTEM = 0x04;
+       const MODE_VOLUME_ID = 0x08;
+       const MODE_DIRECTORY = 0x10;
+       const MODE_ARCHIVE = 0x20;
+       const MODE_NORMAL = 0x80;
+
+       /**
+        * @var string
+        */
+       protected $path;
+
+       /**
+        * @var string
+        */
+       protected $name;
+
+       /**
+        * @var int
+        */
+       protected $size;
+
+       /**
+        * @var int
+        */
+       protected $time;
+
+       /**
+        * @var int
+        */
+       protected $mode;
+
+       /**
+        * @param string $path
+        * @param string $name
+        * @param int $size
+        * @param int $time
+        * @param int $mode
+        */
+       public function __construct($path, $name, $size, $time, $mode) {
+               $this->path = $path;
+               $this->name = $name;
+               $this->size = $size;
+               $this->time = $time;
+               $this->mode = $mode;
+       }
+
+       /**
+        * @return string
+        */
+       public function getPath() {
+               return $this->path;
+       }
+
+       /**
+        * @return string
+        */
+       public function getName() {
+               return $this->name;
+       }
+
+       /**
+        * @return int
+        */
+       public function getSize() {
+               return $this->size;
+       }
+
+       /**
+        * @return int
+        */
+       public function getMTime() {
+               return $this->time;
+       }
+
+       /**
+        * @return bool
+        */
+       public function isDirectory() {
+               return (bool)($this->mode & self::MODE_DIRECTORY);
+       }
+
+       /**
+        * @return bool
+        */
+       public function isReadOnly() {
+               return (bool)($this->mode & self::MODE_READONLY);
+       }
+
+       /**
+        * @return bool
+        */
+       public function isHidden() {
+               return (bool)($this->mode & self::MODE_HIDDEN);
+       }
+
+       /**
+        * @return bool
+        */
+       public function isSystem() {
+               return (bool)($this->mode & self::MODE_SYSTEM);
+       }
+
+       /**
+        * @return bool
+        */
+       public function isArchived() {
+               return (bool)($this->mode & self::MODE_ARCHIVE);
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/IFileInfo.php b/apps/files_external/3rdparty/icewind/smb/src/IFileInfo.php
new file mode 100644 (file)
index 0000000..16ea8cf
--- /dev/null
@@ -0,0 +1,55 @@
+<?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\SMB;
+
+interface IFileInfo {
+       /**
+        * @return string
+        */
+       public function getPath();
+
+       /**
+        * @return string
+        */
+       public function getName();
+
+       /**
+        * @return int
+        */
+       public function getSize();
+
+       /**
+        * @return int
+        */
+       public function getMTime();
+
+       /**
+        * @return bool
+        */
+       public function isDirectory();
+
+       /**
+        * @return bool
+        */
+       public function isReadOnly();
+
+       /**
+        * @return bool
+        */
+       public function isHidden();
+
+       /**
+        * @return bool
+        */
+       public function isSystem();
+
+       /**
+        * @return bool
+        */
+       public function isArchived();
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/IShare.php b/apps/files_external/3rdparty/icewind/smb/src/IShare.php
new file mode 100644 (file)
index 0000000..4851e9d
--- /dev/null
@@ -0,0 +1,134 @@
+<?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\SMB;
+
+interface IShare {
+       /**
+        * Get the name of the share
+        *
+        * @return string
+        */
+       public function getName();
+
+       /**
+        * Download a remote file
+        *
+        * @param string $source remove file
+        * @param string $target local file
+        * @return bool
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\InvalidTypeException
+        */
+       public function get($source, $target);
+
+       /**
+        * Upload a local file
+        *
+        * @param string $source local file
+        * @param string $target remove file
+        * @return bool
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\InvalidTypeException
+        */
+       public function put($source, $target);
+
+       /**
+        * Open a readable stream top a remote file
+        *
+        * @param string $source
+        * @return resource a read only stream with the contents of the remote file
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\InvalidTypeException
+        */
+       public function read($source);
+
+       /**
+        * Open a writable stream to a remote file
+        *
+        * @param string $target
+        * @return resource a write only stream to upload a remote file
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\InvalidTypeException
+        */
+       public function write($target);
+
+       /**
+        * Rename a remote file
+        *
+        * @param string $from
+        * @param string $to
+        * @return bool
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\AlreadyExistsException
+        */
+       public function rename($from, $to);
+
+       /**
+        * Delete a file on the share
+        *
+        * @param string $path
+        * @return bool
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\InvalidTypeException
+        */
+       public function del($path);
+
+       /**
+        * List the content of a remote folder
+        *
+        * @param $path
+        * @return \Icewind\SMB\IFileInfo[]
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\InvalidTypeException
+        */
+       public function dir($path);
+
+       /**
+        * @param string $path
+        * @return \Icewind\SMB\IFileInfo
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        */
+       public function stat($path);
+
+       /**
+        * Create a folder on the share
+        *
+        * @param string $path
+        * @return bool
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\AlreadyExistsException
+        */
+       public function mkdir($path);
+
+       /**
+        * Remove a folder on the share
+        *
+        * @param string $path
+        * @return bool
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\InvalidTypeException
+        */
+       public function rmdir($path);
+
+       /**
+        * @param string $path
+        * @param int $mode a combination of FileInfo::MODE_READONLY, FileInfo::MODE_ARCHIVE, FileInfo::MODE_SYSTEM and FileInfo::MODE_HIDDEN, FileInfo::NORMAL
+        * @return mixed
+        */
+       public function setMode($path, $mode);
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/NativeFileInfo.php b/apps/files_external/3rdparty/icewind/smb/src/NativeFileInfo.php
new file mode 100644 (file)
index 0000000..6ef5cf0
--- /dev/null
@@ -0,0 +1,142 @@
+<?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\SMB;
+
+class NativeFileInfo implements IFileInfo {
+       const MODE_FILE = 0100000;
+
+       /**
+        * @var string
+        */
+       protected $path;
+
+       /**
+        * @var string
+        */
+       protected $name;
+
+       /**
+        * @var \Icewind\SMB\NativeShare
+        */
+       protected $share;
+
+       /**
+        * @var array | null
+        */
+       protected $statCache;
+
+       /**
+        * @var int
+        */
+       protected $modeCache;
+
+       /**
+        * @param \Icewind\SMB\NativeShare $share
+        * @param string $path
+        * @param string $name
+        * @param array $stat
+        */
+       public function __construct($share, $path, $name, $stat = null) {
+               $this->share = $share;
+               $this->path = $path;
+               $this->name = $name;
+               $this->statCache = $stat;
+       }
+
+       /**
+        * @return string
+        */
+       public function getPath() {
+               return $this->path;
+       }
+
+       /**
+        * @return string
+        */
+       public function getName() {
+               return $this->name;
+       }
+
+       /**
+        * @return array
+        */
+       protected function stat() {
+               if (!$this->statCache) {
+                       $this->statCache = $this->share->getStat($this->getPath());
+               }
+               return $this->statCache;
+       }
+
+       /**
+        * @return int
+        */
+       public function getSize() {
+               $stat = $this->stat();
+               return $stat['size'];
+       }
+
+       /**
+        * @return int
+        */
+       public function getMTime() {
+               $stat = $this->stat();
+               return $stat['mtime'];
+       }
+
+       /**
+        * @return bool
+        */
+       public function isDirectory() {
+               $stat = $this->stat();
+               return !($stat['mode'] & self::MODE_FILE);
+       }
+
+       /**
+        * @return int
+        */
+       protected function getMode() {
+               if (!$this->modeCache) {
+                       $attribute = $this->share->getAttribute($this->path, 'system.dos_attr.mode');
+                       // parse hex string
+                       $this->modeCache = (int)hexdec(substr($attribute, 2));
+               }
+               return $this->modeCache;
+       }
+
+       /**
+        * @return bool
+        */
+       public function isReadOnly() {
+               $mode = $this->getMode();
+               return (bool)($mode & FileInfo::MODE_READONLY);
+       }
+
+       /**
+        * @return bool
+        */
+       public function isHidden() {
+               $mode = $this->getMode();
+               return (bool)($mode & FileInfo::MODE_HIDDEN);
+       }
+
+       /**
+        * @return bool
+        */
+       public function isSystem() {
+               $mode = $this->getMode();
+               return (bool)($mode & FileInfo::MODE_SYSTEM);
+       }
+
+       /**
+        * @return bool
+        */
+       public function isArchived() {
+               $mode = $this->getMode();
+               return (bool)($mode & FileInfo::MODE_ARCHIVE);
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/NativeServer.php b/apps/files_external/3rdparty/icewind/smb/src/NativeServer.php
new file mode 100644 (file)
index 0000000..4628e3e
--- /dev/null
@@ -0,0 +1,60 @@
+<?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\SMB;
+
+class NativeServer extends Server {
+       /**
+        * @var \Icewind\SMB\NativeState
+        */
+       protected $state;
+
+       /**
+        * @param string $host
+        * @param string $user
+        * @param string $password
+        */
+       public function __construct($host, $user, $password) {
+               parent::__construct($host, $user, $password);
+               $this->state = new NativeState();
+       }
+
+       protected function connect() {
+               $user = $this->getUser();
+               $workgroup = null;
+               if (strpos($user, '/')) {
+                       list($workgroup, $user) = explode($user, '/');
+               }
+               $this->state->init($workgroup, $user, $this->getPassword());
+       }
+
+       /**
+        * @return \Icewind\SMB\IShare[]
+        * @throws \Icewind\SMB\Exception\AuthenticationException
+        * @throws \Icewind\SMB\Exception\InvalidHostException
+        */
+       public function listShares() {
+               $this->connect();
+               $shares = array();
+               $dh = $this->state->opendir('smb://' . $this->getHost());
+               while ($share = $this->state->readdir($dh)) {
+                       if ($share['type'] === 'file share') {
+                               $shares[] = $this->getShare($share['name']);
+                       }
+               }
+               $this->state->closedir($dh);
+               return $shares;
+       }
+
+       /**
+        * @param string $name
+        * @return \Icewind\SMB\IShare
+        */
+       public function getShare($name) {
+               return new NativeShare($this, $name);
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/NativeShare.php b/apps/files_external/3rdparty/icewind/smb/src/NativeShare.php
new file mode 100644 (file)
index 0000000..c84e961
--- /dev/null
@@ -0,0 +1,288 @@
+<?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\SMB;
+
+class NativeShare implements IShare {
+       /**
+        * @var Server $server
+        */
+       private $server;
+
+       /**
+        * @var string $name
+        */
+       private $name;
+
+       /**
+        * @var \Icewind\SMB\NativeState $state
+        */
+       private $state;
+
+       /**
+        * @param Server $server
+        * @param string $name
+        */
+       public function __construct($server, $name) {
+               $this->server = $server;
+               $this->name = $name;
+               $this->state = new NativeState();
+       }
+
+       /**
+        * @throws \Icewind\SMB\Exception\ConnectionException
+        * @throws \Icewind\SMB\Exception\AuthenticationException
+        * @throws \Icewind\SMB\Exception\InvalidHostException
+        */
+       protected function connect() {
+               if ($this->state and $this->state instanceof NativeShare) {
+                       return;
+               }
+
+               $user = $this->server->getUser();
+               if (strpos($user, '/')) {
+                       list($workgroup, $user) = explode('/', $user);
+               } elseif (strpos($user, '\\')) {
+                       list($workgroup, $user) = explode('\\', $user);
+               } else {
+                       $workgroup = null;
+               }
+               $this->state->init($workgroup, $user, $this->server->getPassword());
+       }
+
+       /**
+        * Get the name of the share
+        *
+        * @return string
+        */
+       public function getName() {
+               return $this->name;
+       }
+
+       private function buildUrl($path) {
+               $url = sprintf('smb://%s/%s', $this->server->getHost(), $this->name);
+               if ($path) {
+                       $path = trim($path, '/');
+                       $url .= '/';
+                       $url .= implode('/', array_map('rawurlencode', explode('/', $path)));
+               }
+               return $url;
+       }
+
+       /**
+        * List the content of a remote folder
+        *
+        * @param string $path
+        * @return \Icewind\SMB\IFileInfo[]
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\InvalidTypeException
+        */
+       public function dir($path) {
+               $this->connect();
+               $files = array();
+
+               $dh = $this->state->opendir($this->buildUrl($path));
+               while ($file = $this->state->readdir($dh)) {
+                       $name = $file['name'];
+                       if ($name !== '.' and $name !== '..') {
+                               $files [] = new NativeFileInfo($this, $path . '/' . $name, $name);
+                       }
+               }
+
+               $this->state->closedir($dh);
+               return $files;
+       }
+
+       /**
+        * @param string $path
+        * @return \Icewind\SMB\IFileInfo[]
+        */
+       public function stat($path) {
+               return new NativeFileInfo($this, $path, basename($path), $this->getStat($path));
+       }
+
+       public function getStat($path) {
+               $this->connect();
+               return $this->state->stat($this->buildUrl($path));
+       }
+
+       /**
+        * Create a folder on the share
+        *
+        * @param string $path
+        * @return bool
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\AlreadyExistsException
+        */
+       public function mkdir($path) {
+               $this->connect();
+               return $this->state->mkdir($this->buildUrl($path));
+       }
+
+       /**
+        * Remove a folder on the share
+        *
+        * @param string $path
+        * @return bool
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\InvalidTypeException
+        */
+       public function rmdir($path) {
+               $this->connect();
+               return $this->state->rmdir($this->buildUrl($path));
+       }
+
+       /**
+        * Delete a file on the share
+        *
+        * @param string $path
+        * @return bool
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\InvalidTypeException
+        */
+       public function del($path) {
+               return $this->state->unlink($this->buildUrl($path));
+       }
+
+       /**
+        * Rename a remote file
+        *
+        * @param string $from
+        * @param string $to
+        * @return bool
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\AlreadyExistsException
+        */
+       public function rename($from, $to) {
+               $this->connect();
+               return $this->state->rename($this->buildUrl($from), $this->buildUrl($to));
+       }
+
+       /**
+        * Upload a local file
+        *
+        * @param string $source local file
+        * @param string $target remove file
+        * @return bool
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\InvalidTypeException
+        */
+       public function put($source, $target) {
+               $this->connect();
+               $sourceHandle = fopen($source, 'rb');
+               $targetHandle = $this->state->create($this->buildUrl($target));
+
+               while ($data = fread($sourceHandle, 4096)) {
+                       $this->state->write($targetHandle, $data);
+               }
+               $this->state->close($targetHandle);
+               return true;
+       }
+
+       /**
+        * Download a remote file
+        *
+        * @param string $source remove file
+        * @param string $target local file
+        * @return bool
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\InvalidTypeException
+        */
+       public function get($source, $target) {
+               $this->connect();
+               $sourceHandle = $this->state->open($this->buildUrl($source), 'r');
+               $targetHandle = fopen($target, 'wb');
+
+               while ($data = $this->state->read($sourceHandle, 4096)) {
+                       fwrite($targetHandle, $data);
+               }
+               $this->state->close($sourceHandle);
+               return true;
+       }
+
+       /**
+        * Open a readable stream top a remote file
+        *
+        * @param string $source
+        * @return resource a read only stream with the contents of the remote file
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\InvalidTypeException
+        */
+       public function read($source) {
+               $this->connect();
+               $handle = $this->state->open($this->buildUrl($source), 'r');
+               return NativeStream::wrap($this->state, $handle, 'r');
+       }
+
+       /**
+        * Open a readable stream top a remote file
+        *
+        * @param string $source
+        * @return resource a read only stream with the contents of the remote file
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\InvalidTypeException
+        */
+       public function write($source) {
+               $this->connect();
+               $handle = $this->state->create($this->buildUrl($source));
+               return NativeStream::wrap($this->state, $handle, 'w');
+       }
+
+       /**
+        * Get extended attributes for the path
+        *
+        * @param string $path
+        * @param string $attribute attribute to get the info
+        * @return string the attribute value
+        */
+       public function getAttribute($path, $attribute) {
+               $this->connect();
+
+               $result = $this->state->getxattr($this->buildUrl($path), $attribute);
+               return $result;
+       }
+
+       /**
+        * Get extended attributes for the path
+        *
+        * @param string $path
+        * @param string $attribute attribute to get the info
+        * @param mixed $value
+        * @return string the attribute value
+        */
+       public function setAttribute($path, $attribute, $value) {
+               $this->connect();
+
+               if ($attribute === 'system.dos_attr.mode' and is_int($value)) {
+                       $value = '0x' . dechex($value);
+               }
+
+               return $this->state->setxattr($this->buildUrl($path), $attribute, $value);
+       }
+
+       /**
+        * @param string $path
+        * @param int $mode a combination of FileInfo::MODE_READONLY, FileInfo::MODE_ARCHIVE, FileInfo::MODE_SYSTEM and FileInfo::MODE_HIDDEN, FileInfo::NORMAL
+        * @return mixed
+        */
+       public function setMode($path, $mode) {
+               return $this->setAttribute($path, 'system.dos_attr.mode', $mode);
+       }
+
+       public function __destruct() {
+               unset($this->state);
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/NativeState.php b/apps/files_external/3rdparty/icewind/smb/src/NativeState.php
new file mode 100644 (file)
index 0000000..e3e344d
--- /dev/null
@@ -0,0 +1,308 @@
+<?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\SMB;
+
+use Icewind\SMB\Exception\AlreadyExistsException;
+use Icewind\SMB\Exception\ConnectionRefusedException;
+use Icewind\SMB\Exception\Exception;
+use Icewind\SMB\Exception\ForbiddenException;
+use Icewind\SMB\Exception\HostDownException;
+use Icewind\SMB\Exception\InvalidTypeException;
+use Icewind\SMB\Exception\NoRouteToHostException;
+use Icewind\SMB\Exception\NotEmptyException;
+use Icewind\SMB\Exception\NotFoundException;
+use Icewind\SMB\Exception\TimedOutException;
+
+/**
+ * Low level wrapper for libsmbclient-php for error handling
+ */
+class NativeState {
+       /**
+        * @var resource
+        */
+       protected $state;
+
+       protected $handlerSet = false;
+
+       protected $connected = false;
+
+       protected function handleError($path) {
+               $error = smbclient_state_errno($this->state);
+               switch ($error) {
+                       // see error.h
+                       case 0;
+                               return;
+                       case 1:
+                       case 13:
+                               throw new ForbiddenException($path, $error);
+                       case 2:
+                               throw new NotFoundException($path, $error);
+                       case 17:
+                               throw new AlreadyExistsException($path, $error);
+                       case 20:
+                               throw new InvalidTypeException($path, $error);
+                       case 21:
+                               throw new InvalidTypeException($path, $error);
+                       case 39:
+                               throw new NotEmptyException($path, $error);
+                       case 110:
+                               throw new TimedOutException($path, $error);
+                       case 111:
+                               throw new ConnectionRefusedException($path, $error);
+                       case 112:
+                               throw new HostDownException($path, $error);
+                       case 113:
+                               throw new NoRouteToHostException($path, $error);
+                       default:
+                               $message = 'Unknown error (' . $error . ')';
+                               if ($path) {
+                                       $message .= ' for ' . $path;
+                               }
+                               throw new Exception($message, $error);
+               }
+       }
+
+       protected function testResult($result, $path) {
+               if ($result === false or $result === null) {
+                       $this->handleError($path);
+               }
+       }
+
+       /**
+        * @param string $workGroup
+        * @param string $user
+        * @param string $password
+        * @return bool
+        */
+       public function init($workGroup, $user, $password) {
+               if ($this->connected) {
+                       return true;
+               }
+               $this->state = smbclient_state_new();
+               $result = @smbclient_state_init($this->state, $workGroup, $user, $password);
+
+               $this->testResult($result, '');
+               $this->connected = true;
+               return $result;
+       }
+
+       /**
+        * @param string $uri
+        * @return resource
+        */
+       public function opendir($uri) {
+               $result = @smbclient_opendir($this->state, $uri);
+
+               $this->testResult($result, $uri);
+               return $result;
+       }
+
+       /**
+        * @param resource $dir
+        * @return array
+        */
+       public function readdir($dir) {
+               $result = @smbclient_readdir($this->state, $dir);
+
+               $this->testResult($result, $dir);
+               return $result;
+       }
+
+       /**
+        * @param $dir
+        * @return bool
+        */
+       public function closedir($dir) {
+               $result = smbclient_closedir($this->state, $dir);
+
+               $this->testResult($result, $dir);
+               return $result;
+       }
+
+       /**
+        * @param string $old
+        * @param string $new
+        * @return bool
+        */
+       public function rename($old, $new) {
+               $result = @smbclient_rename($this->state, $old, $this->state, $new);
+
+               $this->testResult($result, $new);
+               return $result;
+       }
+
+       /**
+        * @param string $uri
+        * @return bool
+        */
+       public function unlink($uri) {
+               $result = @smbclient_unlink($this->state, $uri);
+
+               $this->testResult($result, $uri);
+               return $result;
+       }
+
+       /**
+        * @param string $uri
+        * @param int $mask
+        * @return bool
+        */
+       public function mkdir($uri, $mask = 0777) {
+               $result = @smbclient_mkdir($this->state, $uri, $mask);
+
+               $this->testResult($result, $uri);
+               return $result;
+       }
+
+       /**
+        * @param string $uri
+        * @return bool
+        */
+       public function rmdir($uri) {
+               $result = @smbclient_rmdir($this->state, $uri);
+
+               $this->testResult($result, $uri);
+               return $result;
+       }
+
+       /**
+        * @param string $uri
+        * @return array
+        */
+       public function stat($uri) {
+               $result = @smbclient_stat($this->state, $uri);
+
+               $this->testResult($result, $uri);
+               return $result;
+       }
+
+       /**
+        * @param resource $file
+        * @return array
+        */
+       public function fstat($file) {
+               $result = @smbclient_fstat($this->state, $file);
+
+               $this->testResult($result, $file);
+               return $result;
+       }
+
+       /**
+        * @param string $uri
+        * @param string $mode
+        * @param int $mask
+        * @return resource
+        */
+       public function open($uri, $mode, $mask = 0666) {
+               $result = @smbclient_open($this->state, $uri, $mode, $mask);
+
+               $this->testResult($result, $uri);
+               return $result;
+       }
+
+       /**
+        * @param string $uri
+        * @param int $mask
+        * @return resource
+        */
+       public function create($uri, $mask = 0666) {
+               $result = @smbclient_creat($this->state, $uri, $mask);
+
+               $this->testResult($result, $uri);
+               return $result;
+       }
+
+       /**
+        * @param resource $file
+        * @param int $bytes
+        * @return string
+        */
+       public function read($file, $bytes) {
+               $result = @smbclient_read($this->state, $file, $bytes);
+
+               $this->testResult($result, $file);
+               return $result;
+       }
+
+       /**
+        * @param resource $file
+        * @param string $data
+        * @param int $length
+        * @return int
+        */
+       public function write($file, $data, $length = null) {
+               $result = @smbclient_write($this->state, $file, $data, $length);
+
+               $this->testResult($result, $file);
+               return $result;
+       }
+
+       /**
+        * @param resource $file
+        * @param int $offset
+        * @param int $whence SEEK_SET | SEEK_CUR | SEEK_END
+        * @return int | bool new file offset as measured from the start of the file on success, false on failure.
+        */
+       public function lseek($file, $offset, $whence = SEEK_SET) {
+               $result = @smbclient_lseek($this->state, $file, $offset, $whence);
+
+               $this->testResult($result, $file);
+               return $result;
+       }
+
+       /**
+        * @param resource $file
+        * @param int $size
+        * @return bool
+        */
+       public function ftruncate($file, $size) {
+               $result = @smbclient_ftruncate($this->state, $file, $size);
+
+               $this->testResult($result, $file);
+               return $result;
+       }
+
+       public function close($file) {
+               $result = @smbclient_close($this->state, $file);
+
+               $this->testResult($result, $file);
+               return $result;
+       }
+
+       /**
+        * @param string $uri
+        * @param string $key
+        * @return string
+        */
+       public function getxattr($uri, $key) {
+               $result = @smbclient_getxattr($this->state, $uri, $key);
+
+               $this->testResult($result, $uri);
+               return $result;
+       }
+
+       /**
+        * @param string $uri
+        * @param string $key
+        * @param string $value
+        * @param int $flags
+        * @return mixed
+        */
+       public function setxattr($uri, $key, $value, $flags = 0) {
+               $result = @smbclient_setxattr($this->state, $uri, $key, $value, $flags);
+
+               $this->testResult($result, $uri);
+               return $result;
+       }
+
+       public function __destruct() {
+               if ($this->connected) {
+                       smbclient_state_free($this->state);
+               }
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/NativeStream.php b/apps/files_external/3rdparty/icewind/smb/src/NativeStream.php
new file mode 100644 (file)
index 0000000..07bd2f1
--- /dev/null
@@ -0,0 +1,114 @@
+<?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\SMB;
+
+use Icewind\SMB\Exception\InvalidRequestException;
+use Icewind\Streams\File;
+
+class NativeStream implements File {
+       /**
+        * @var resource
+        */
+       public $context;
+
+       /**
+        * @var \Icewind\SMB\NativeState
+        */
+       private $state;
+
+       /**
+        * @var resource
+        */
+       private $handle;
+
+       /**
+        * @var bool
+        */
+       private $eof = false;
+
+       /**
+        * Wrap a stream from libsmbclient-php into a regular php stream
+        *
+        * @param \Icewind\SMB\NativeState $state
+        * @param resource $smbStream
+        * @param string $mode
+        * @return resource
+        */
+       public static function wrap($state, $smbStream, $mode) {
+               stream_wrapper_register('nativesmb', '\Icewind\SMB\NativeStream');
+               $context = stream_context_create(array(
+                       'nativesmb' => array(
+                               'state' => $state,
+                               'handle' => $smbStream
+                       )
+               ));
+               $fh = fopen('nativesmb://', $mode, false, $context);
+               stream_wrapper_unregister('nativesmb');
+               return $fh;
+       }
+
+       public function stream_close() {
+               return $this->state->close($this->handle);
+       }
+
+       public function stream_eof() {
+               return $this->eof;
+       }
+
+       public function stream_flush() {
+       }
+
+
+       public function stream_open($path, $mode, $options, &$opened_path) {
+               $context = stream_context_get_options($this->context);
+               $this->state = $context['nativesmb']['state'];
+               $this->handle = $context['nativesmb']['handle'];
+               return true;
+       }
+
+       public function stream_read($count) {
+               $result = $this->state->read($this->handle, $count);
+               if (strlen($result) < $count) {
+                       $this->eof = true;
+               }
+               return $result;
+       }
+
+       public function stream_seek($offset, $whence = SEEK_SET) {
+               $this->eof = false;
+               try {
+                       return $this->state->lseek($this->handle, $offset, $whence) !== false;
+               } catch (InvalidRequestException $e) {
+                       return false;
+               }
+       }
+
+       public function stream_stat() {
+               return $this->state->fstat($this->handle);
+       }
+
+       public function stream_tell() {
+               return $this->state->lseek($this->handle, 0, SEEK_CUR);
+       }
+
+       public function stream_write($data) {
+               return $this->state->write($this->handle, $data);
+       }
+
+       public function stream_truncate($size) {
+               return $this->state->ftruncate($this->handle, $size);
+       }
+
+       public function stream_set_option($option, $arg1, $arg2) {
+               return false;
+       }
+
+       public function stream_lock($operation) {
+               return false;
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Parser.php b/apps/files_external/3rdparty/icewind/smb/src/Parser.php
new file mode 100644 (file)
index 0000000..645678d
--- /dev/null
@@ -0,0 +1,130 @@
+<?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\SMB;
+
+use Icewind\SMB\Exception\AccessDeniedException;
+use Icewind\SMB\Exception\AlreadyExistsException;
+use Icewind\SMB\Exception\Exception;
+use Icewind\SMB\Exception\FileInUseException;
+use Icewind\SMB\Exception\InvalidTypeException;
+use Icewind\SMB\Exception\NotEmptyException;
+use Icewind\SMB\Exception\NotFoundException;
+
+class Parser {
+       /**
+        * @var string
+        */
+       protected $timeZone;
+
+       /**
+        * @param string $timeZone
+        */
+       public function __construct($timeZone) {
+               $this->timeZone = $timeZone;
+       }
+
+       public function checkForError($output, $path) {
+               if (count($output) === 0) {
+                       return true;
+               } else {
+                       if (strpos($output[0], 'does not exist')) {
+                               throw new NotFoundException($path);
+                       }
+                       $parts = explode(' ', $output[0]);
+                       $error = false;
+                       foreach ($parts as $part) {
+                               if (substr($part, 0, 9) === 'NT_STATUS') {
+                                       $error = $part;
+                               }
+                       }
+                       switch ($error) {
+                               case ErrorCodes::PathNotFound:
+                               case ErrorCodes::ObjectNotFound:
+                               case ErrorCodes::NoSuchFile:
+                                       throw new NotFoundException($path);
+                               case ErrorCodes::NameCollision:
+                                       throw new AlreadyExistsException($path);
+                               case ErrorCodes::AccessDenied:
+                                       throw new AccessDeniedException($path);
+                               case ErrorCodes::DirectoryNotEmpty:
+                                       throw new NotEmptyException($path);
+                               case ErrorCodes::FileIsADirectory:
+                               case ErrorCodes::NotADirectory:
+                                       throw new InvalidTypeException($path);
+                               case ErrorCodes::SharingViolation:
+                                       throw new FileInUseException($path);
+                               default:
+                                       $message = 'Unknown error (' . $error . ')';
+                                       if ($path) {
+                                               $message .= ' for ' . $path;
+                                       }
+                                       throw new Exception($message);
+                       }
+               }
+       }
+
+       public function parseMode($mode) {
+               $result = 0;
+               $modeStrings = array(
+                       'R' => FileInfo::MODE_READONLY,
+                       'H' => FileInfo::MODE_HIDDEN,
+                       'S' => FileInfo::MODE_SYSTEM,
+                       'D' => FileInfo::MODE_DIRECTORY,
+                       'A' => FileInfo::MODE_ARCHIVE,
+                       'N' => FileInfo::MODE_NORMAL
+               );
+               foreach ($modeStrings as $char => $val) {
+                       if (strpos($mode, $char) !== false) {
+                               $result |= $val;
+                       }
+               }
+               return $result;
+       }
+
+       public function parseStat($output) {
+               $mtime = 0;
+               $mode = 0;
+               $size = 0;
+               foreach ($output as $line) {
+                       list($name, $value) = explode(':', $line, 2);
+                       $value = trim($value);
+                       if ($name === 'write_time') {
+                               $mtime = strtotime($value);
+                       } else if ($name === 'attributes') {
+                               $mode = hexdec(substr($value, 1, -1));
+                       } else if ($name === 'stream') {
+                               list(, $size,) = explode(' ', $value);
+                               $size = intval($size);
+                       }
+               }
+               return array(
+                       'mtime' => $mtime,
+                       'mode' => $mode,
+                       'size' => $size
+               );
+       }
+
+       public function parseDir($output, $basePath) {
+               //last line is used space
+               array_pop($output);
+               $regex = '/^\s*(.*?)\s\s\s\s+(?:([NDHARS]*)\s+)?([0-9]+)\s+(.*)$/';
+               //2 spaces, filename, optional type, size, date
+               $content = array();
+               foreach ($output as $line) {
+                       if (preg_match($regex, $line, $matches)) {
+                               list(, $name, $mode, $size, $time) = $matches;
+                               if ($name !== '.' and $name !== '..') {
+                                       $mode = $this->parseMode($mode);
+                                       $time = strtotime($time . ' ' . $this->timeZone);
+                                       $content[] = new FileInfo($basePath . '/' . $name, $name, $size, $time, $mode);
+                               }
+                       }
+               }
+               return $content;
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/RawConnection.php b/apps/files_external/3rdparty/icewind/smb/src/RawConnection.php
new file mode 100644 (file)
index 0000000..926ce37
--- /dev/null
@@ -0,0 +1,165 @@
+<?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\SMB;
+
+use Icewind\SMB\Exception\ConnectionException;
+
+class RawConnection {
+       /**
+        * @var string
+        */
+       private $command;
+
+       /**
+        * @var string[]
+        */
+       private $env;
+
+       /**
+        * @var resource[] $pipes
+        *
+        * $pipes[0] holds STDIN for smbclient
+        * $pipes[1] holds STDOUT for smbclient
+        */
+       private $pipes;
+
+       /**
+        * @var resource $process
+        */
+       private $process;
+
+       public function __construct($command, $env = array()) {
+               $this->command = $command;
+               $this->env = $env;
+               $this->connect();
+       }
+
+       private function connect() {
+               $descriptorSpec = array(
+                       0 => array('pipe', 'r'), // child reads from stdin
+                       1 => array('pipe', 'w'), // child writes to stdout
+                       2 => array('pipe', 'w'), // child writes to stderr
+                       3 => array('pipe', 'r'), // child reads from fd#3
+                       4 => array('pipe', 'r'), // child reads from fd#4
+                       5 => array('pipe', 'w')  // child writes to fd#5
+               );
+               setlocale(LC_ALL, Server::LOCALE);
+               $env = array_merge($this->env, array(
+                       'CLI_FORCE_INTERACTIVE' => 'y', // Needed or the prompt isn't displayed!!
+                       'LC_ALL' => Server::LOCALE,
+                       'LANG' => Server::LOCALE,
+                       'COLUMNS' => 8192 // prevent smbclient from line-wrapping it's output
+               ));
+               $this->process = proc_open($this->command, $descriptorSpec, $this->pipes, '/', $env);
+               if (!$this->isValid()) {
+                       throw new ConnectionException();
+               }
+       }
+
+       /**
+        * check if the connection is still active
+        *
+        * @return bool
+        */
+       public function isValid() {
+               if (is_resource($this->process)) {
+                       $status = proc_get_status($this->process);
+                       return $status['running'];
+               } else {
+                       return false;
+               }
+       }
+
+       /**
+        * send input to the process
+        *
+        * @param string $input
+        */
+       public function write($input) {
+               fwrite($this->getInputStream(), $input);
+               fflush($this->getInputStream());
+       }
+
+       /**
+        * read a line of output
+        *
+        * @return string
+        */
+       public function readLine() {
+               return stream_get_line($this->getOutputStream(), 4086, "\n");
+       }
+
+       /**
+        * get all output until the process closes
+        *
+        * @return array
+        */
+       public function readAll() {
+               $output = array();
+               while ($line = $this->readLine()) {
+                       $output[] = $line;
+               }
+               return $output;
+       }
+
+       public function getInputStream() {
+               return $this->pipes[0];
+       }
+
+       public function getOutputStream() {
+               return $this->pipes[1];
+       }
+
+       public function getErrorStream() {
+               return $this->pipes[2];
+       }
+
+       public function getAuthStream() {
+               return $this->pipes[3];
+       }
+
+       public function getFileInputStream() {
+               return $this->pipes[4];
+       }
+
+       public function getFileOutputStream() {
+               return $this->pipes[5];
+       }
+
+       public function writeAuthentication($user, $password) {
+               $auth = ($password === false)
+                       ? "username=$user"
+                       : "username=$user\npassword=$password";
+
+               if (fwrite($this->getAuthStream(), $auth) === false) {
+                       fclose($this->getAuthStream());
+                       return false;
+               }
+               fclose($this->getAuthStream());
+               return true;
+       }
+
+       public function close($terminate = true) {
+               if (!is_resource($this->process)) {
+                       return;
+               }
+               if ($terminate) {
+                       proc_terminate($this->process);
+               }
+               proc_close($this->process);
+       }
+
+       public function reconnect() {
+               $this->close();
+               $this->connect();
+       }
+
+       public function __destruct() {
+               $this->close();
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Server.php b/apps/files_external/3rdparty/icewind/smb/src/Server.php
new file mode 100644 (file)
index 0000000..f7227d4
--- /dev/null
@@ -0,0 +1,141 @@
+<?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\SMB;
+
+use Icewind\SMB\Exception\AuthenticationException;
+use Icewind\SMB\Exception\InvalidHostException;
+
+class Server {
+       const CLIENT = 'smbclient';
+       const LOCALE = 'en_US.UTF-8';
+
+       /**
+        * @var string $host
+        */
+       protected $host;
+
+       /**
+        * @var string $user
+        */
+       protected $user;
+
+       /**
+        * @var string $password
+        */
+       protected $password;
+
+       /**
+        * Check if the smbclient php extension is available
+        *
+        * @return bool
+        */
+       public static function NativeAvailable() {
+               return function_exists('smbclient_state_new');
+       }
+
+       /**
+        * @param string $host
+        * @param string $user
+        * @param string $password
+        */
+       public function __construct($host, $user, $password) {
+               $this->host = $host;
+               $this->user = $user;
+               $this->password = $password;
+       }
+
+       /**
+        * @return string
+        */
+       public function getAuthString() {
+               return $this->user . '%' . $this->password;
+       }
+
+       /**
+        * @return string
+        */
+       public function getUser() {
+               return $this->user;
+       }
+
+       /**
+        * @return string
+        */
+       public function getPassword() {
+               return $this->password;
+       }
+
+       /**
+        * return string
+        */
+       public function getHost() {
+               return $this->host;
+       }
+
+       /**
+        * @return \Icewind\SMB\IShare[]
+        *
+        * @throws \Icewind\SMB\Exception\AuthenticationException
+        * @throws \Icewind\SMB\Exception\InvalidHostException
+        */
+       public function listShares() {
+               $command = Server::CLIENT . ' --authentication-file=/proc/self/fd/3' .
+                       ' -gL ' . escapeshellarg($this->getHost());
+               $connection = new RawConnection($command);
+               $connection->writeAuthentication($this->getUser(), $this->getPassword());
+               $output = $connection->readAll();
+
+               $line = $output[0];
+
+               $line = rtrim($line, ')');
+               if (substr($line, -23) === ErrorCodes::LogonFailure) {
+                       throw new AuthenticationException();
+               }
+               if (substr($line, -26) === ErrorCodes::BadHostName) {
+                       throw new InvalidHostException();
+               }
+               if (substr($line, -22) === ErrorCodes::Unsuccessful) {
+                       throw new InvalidHostException();
+               }
+               if (substr($line, -28) === ErrorCodes::ConnectionRefused) {
+                       throw new InvalidHostException();
+               }
+
+               $shareNames = array();
+               foreach ($output as $line) {
+                       if (strpos($line, '|')) {
+                               list($type, $name, $description) = explode('|', $line);
+                               if (strtolower($type) === 'disk') {
+                                       $shareNames[$name] = $description;
+                               }
+                       }
+               }
+
+               $shares = array();
+               foreach ($shareNames as $name => $description) {
+                       $shares[] = $this->getShare($name);
+               }
+               return $shares;
+       }
+
+       /**
+        * @param string $name
+        * @return \Icewind\SMB\IShare
+        */
+       public function getShare($name) {
+               return new Share($this, $name);
+       }
+
+       /**
+        * @return string
+        */
+       public function getTimeZone() {
+               $command = 'net time zone -S ' . escapeshellarg($this->getHost());
+               return exec($command);
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Share.php b/apps/files_external/3rdparty/icewind/smb/src/Share.php
new file mode 100644 (file)
index 0000000..5c48b17
--- /dev/null
@@ -0,0 +1,394 @@
+<?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\SMB;
+
+use Icewind\SMB\Exception\AccessDeniedException;
+use Icewind\SMB\Exception\AlreadyExistsException;
+use Icewind\SMB\Exception\ConnectionException;
+use Icewind\SMB\Exception\Exception;
+use Icewind\SMB\Exception\FileInUseException;
+use Icewind\SMB\Exception\InvalidTypeException;
+use Icewind\SMB\Exception\NotEmptyException;
+use Icewind\SMB\Exception\NotFoundException;
+use Icewind\Streams\CallbackWrapper;
+
+class Share implements IShare {
+       /**
+        * @var Server $server
+        */
+       private $server;
+
+       /**
+        * @var string $name
+        */
+       private $name;
+
+       /**
+        * @var Connection $connection
+        */
+       public $connection;
+
+       /**
+        * @var \Icewind\SMB\Parser
+        */
+       protected $parser;
+
+       private $serverTimezone;
+
+       /**
+        * @param Server $server
+        * @param string $name
+        */
+       public function __construct($server, $name) {
+               $this->server = $server;
+               $this->name = $name;
+               $this->parser = new Parser($this->server->getTimeZone());
+       }
+
+       /**
+        * @throws \Icewind\SMB\Exception\ConnectionException
+        * @throws \Icewind\SMB\Exception\AuthenticationException
+        * @throws \Icewind\SMB\Exception\InvalidHostException
+        */
+       protected function connect() {
+               if ($this->connection and $this->connection->isValid()) {
+                       return;
+               }
+               $command = sprintf('%s --authentication-file=/proc/self/fd/3 //%s/%s',
+                       Server::CLIENT,
+                       $this->server->getHost(),
+                       $this->name
+               );
+               $this->connection = new Connection($command);
+               $this->connection->writeAuthentication($this->server->getUser(), $this->server->getPassword());
+               if (!$this->connection->isValid()) {
+                       throw new ConnectionException();
+               }
+       }
+
+       protected function reconnect() {
+               $this->connection->reconnect();
+               $this->connection->writeAuthentication($this->server->getUser(), $this->server->getPassword());
+               if (!$this->connection->isValid()) {
+                       throw new ConnectionException();
+               }
+       }
+
+       /**
+        * Get the name of the share
+        *
+        * @return string
+        */
+       public function getName() {
+               return $this->name;
+       }
+
+       protected function simpleCommand($command, $path) {
+               $path = $this->escapePath($path);
+               $cmd = $command . ' ' . $path;
+               $output = $this->execute($cmd);
+               return $this->parseOutput($output, $path);
+       }
+
+       /**
+        * List the content of a remote folder
+        *
+        * @param $path
+        * @return \Icewind\SMB\IFileInfo[]
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\InvalidTypeException
+        */
+       public function dir($path) {
+               $escapedPath = $this->escapePath($path);
+               $output = $this->execute('cd ' . $escapedPath);
+               //check output for errors
+               $this->parseOutput($output, $path);
+               $output = $this->execute('dir');
+               $this->execute('cd /');
+
+               return $this->parser->parseDir($output, $path);
+       }
+
+       /**
+        * @param string $path
+        * @return \Icewind\SMB\IFileInfo[]
+        */
+       public function stat($path) {
+               $escapedPath = $this->escapePath($path);
+               $output = $this->execute('allinfo ' . $escapedPath);
+               if (count($output) < 3) {
+                       $this->parseOutput($output, $path);
+               }
+               $stat = $this->parser->parseStat($output);
+               return new FileInfo($path, basename($path), $stat['size'], $stat['mtime'], $stat['mode']);
+       }
+
+       /**
+        * Create a folder on the share
+        *
+        * @param string $path
+        * @return bool
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\AlreadyExistsException
+        */
+       public function mkdir($path) {
+               return $this->simpleCommand('mkdir', $path);
+       }
+
+       /**
+        * Remove a folder on the share
+        *
+        * @param string $path
+        * @return bool
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\InvalidTypeException
+        */
+       public function rmdir($path) {
+               return $this->simpleCommand('rmdir', $path);
+       }
+
+       /**
+        * Delete a file on the share
+        *
+        * @param string $path
+        * @param bool $secondTry
+        * @return bool
+        * @throws InvalidTypeException
+        * @throws NotFoundException
+        * @throws \Exception
+        */
+       public function del($path, $secondTry = false) {
+               //del return a file not found error when trying to delete a folder
+               //we catch it so we can check if $path doesn't exist or is of invalid type
+               try {
+                       return $this->simpleCommand('del', $path);
+               } catch (NotFoundException $e) {
+                       //no need to do anything with the result, we just check if this throws the not found error
+                       try {
+                               $this->simpleCommand('ls', $path);
+                       } catch (NotFoundException $e2) {
+                               throw $e;
+                       } catch (\Exception $e2) {
+                               throw new InvalidTypeException($path);
+                       }
+                       throw $e;
+               } catch (FileInUseException $e) {
+                       if ($secondTry) {
+                               throw $e;
+                       }
+                       $this->reconnect();
+                       return $this->del($path, true);
+               }
+       }
+
+       /**
+        * Rename a remote file
+        *
+        * @param string $from
+        * @param string $to
+        * @return bool
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\AlreadyExistsException
+        */
+       public function rename($from, $to) {
+               $path1 = $this->escapePath($from);
+               $path2 = $this->escapePath($to);
+               $cmd = 'rename ' . $path1 . ' ' . $path2;
+               $output = $this->execute($cmd);
+               return $this->parseOutput($output, $to);
+       }
+
+       /**
+        * Upload a local file
+        *
+        * @param string $source local file
+        * @param string $target remove file
+        * @return bool
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\InvalidTypeException
+        */
+       public function put($source, $target) {
+               $path1 = $this->escapeLocalPath($source); //first path is local, needs different escaping
+               $path2 = $this->escapePath($target);
+               $output = $this->execute('put ' . $path1 . ' ' . $path2);
+               return $this->parseOutput($output, $target);
+       }
+
+       /**
+        * Download a remote file
+        *
+        * @param string $source remove file
+        * @param string $target local file
+        * @return bool
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\InvalidTypeException
+        */
+       public function get($source, $target) {
+               $path1 = $this->escapePath($source);
+               $path2 = $this->escapeLocalPath($target); //second path is local, needs different escaping
+               $output = $this->execute('get ' . $path1 . ' ' . $path2);
+               return $this->parseOutput($output, $source);
+       }
+
+       /**
+        * Open a readable stream to a remote file
+        *
+        * @param string $source
+        * @return resource a read only stream with the contents of the remote file
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\InvalidTypeException
+        */
+       public function read($source) {
+               $source = $this->escapePath($source);
+               // close the single quote, open a double quote where we put the single quote...
+               $source = str_replace('\'', '\'"\'"\'', $source);
+               // since returned stream is closed by the caller we need to create a new instance
+               // since we can't re-use the same file descriptor over multiple calls
+               $command = sprintf('%s --authentication-file=/proc/self/fd/3 //%s/%s -c \'get %s /proc/self/fd/5\'',
+                       Server::CLIENT,
+                       $this->server->getHost(),
+                       $this->name,
+                       $source
+               );
+               $connection = new Connection($command);
+               $connection->writeAuthentication($this->server->getUser(), $this->server->getPassword());
+               $fh = $connection->getFileOutputStream();
+               stream_context_set_option($fh, 'file', 'connection', $connection);
+               return $fh;
+       }
+
+       /**
+        * Open a writable stream to a remote file
+        *
+        * @param string $target
+        * @return resource a write only stream to upload a remote file
+        *
+        * @throws \Icewind\SMB\Exception\NotFoundException
+        * @throws \Icewind\SMB\Exception\InvalidTypeException
+        */
+       public function write($target) {
+               $target = $this->escapePath($target);
+               // close the single quote, open a double quote where we put the single quote...
+               $target = str_replace('\'', '\'"\'"\'', $target);
+               // since returned stream is closed by the caller we need to create a new instance
+               // since we can't re-use the same file descriptor over multiple calls
+               $command = sprintf('%s --authentication-file=/proc/self/fd/3 //%s/%s -c \'put /proc/self/fd/4 %s\'',
+                       Server::CLIENT,
+                       $this->server->getHost(),
+                       $this->name,
+                       $target
+               );
+               $connection = new RawConnection($command);
+               $connection->writeAuthentication($this->server->getUser(), $this->server->getPassword());
+               $fh = $connection->getFileInputStream();
+
+               // use a close callback to ensure the upload is finished before continuing
+               // this also serves as a way to keep the connection in scope
+               return CallbackWrapper::wrap($fh, null, null, function () use ($connection) {
+                       $connection->close(false); // dont terminate, give the upload some time
+               });
+       }
+
+       /**
+        * @param string $path
+        * @param int $mode a combination of FileInfo::MODE_READONLY, FileInfo::MODE_ARCHIVE, FileInfo::MODE_SYSTEM and FileInfo::MODE_HIDDEN, FileInfo::NORMAL
+        * @return mixed
+        */
+       public function setMode($path, $mode) {
+               $modeString = '';
+               $modeMap = array(
+                       FileInfo::MODE_READONLY => 'r',
+                       FileInfo::MODE_HIDDEN => 'h',
+                       FileInfo::MODE_ARCHIVE => 'a',
+                       FileInfo::MODE_SYSTEM => 's'
+               );
+               foreach ($modeMap as $modeByte => $string) {
+                       if ($mode & $modeByte) {
+                               $modeString .= $string;
+                       }
+               }
+               $path = $this->escapePath($path);
+
+               // first reset the mode to normal
+               $cmd = 'setmode ' . $path . ' -rsha';
+               $output = $this->execute($cmd);
+               $this->parseOutput($output, $path);
+
+               // then set the modes we want
+               $cmd = 'setmode ' . $path . ' ' . $modeString;
+               $output = $this->execute($cmd);
+               return $this->parseOutput($output, $path);
+       }
+
+       /**
+        * @param string $command
+        * @return array
+        */
+       protected function execute($command) {
+               $this->connect();
+               $this->connection->write($command . PHP_EOL);
+               $output = $this->connection->read();
+               return $output;
+       }
+
+       /**
+        * check output for errors
+        *
+        * @param string[] $lines
+        * @param string $path
+        *
+        * @throws NotFoundException
+        * @throws \Icewind\SMB\Exception\AlreadyExistsException
+        * @throws \Icewind\SMB\Exception\AccessDeniedException
+        * @throws \Icewind\SMB\Exception\NotEmptyException
+        * @throws \Icewind\SMB\Exception\InvalidTypeException
+        * @throws \Icewind\SMB\Exception\Exception
+        * @return bool
+        */
+       protected function parseOutput($lines, $path = '') {
+               $this->parser->checkForError($lines, $path);
+       }
+
+       /**
+        * @param string $string
+        * @return string
+        */
+       protected function escape($string) {
+               return escapeshellarg($string);
+       }
+
+       /**
+        * @param string $path
+        * @return string
+        */
+       protected function escapePath($path) {
+               $path = str_replace('/', '\\', $path);
+               $path = str_replace('"', '^"', $path);
+               return '"' . $path . '"';
+       }
+
+       /**
+        * @param string $path
+        * @return string
+        */
+       protected function escapeLocalPath($path) {
+               $path = str_replace('"', '\"', $path);
+               return '"' . $path . '"';
+       }
+
+       public function __destruct() {
+               unset($this->connection);
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/tests/AbstractShare.php b/apps/files_external/3rdparty/icewind/smb/tests/AbstractShare.php
new file mode 100644 (file)
index 0000000..117fff1
--- /dev/null
@@ -0,0 +1,534 @@
+<?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\SMB\Test;
+
+use Icewind\SMB\FileInfo;
+
+abstract class AbstractShare extends \PHPUnit_Framework_TestCase {
+       /**
+        * @var \Icewind\SMB\Server $server
+        */
+       protected $server;
+
+       /**
+        * @var \Icewind\SMB\IShare $share
+        */
+       protected $share;
+
+       /**
+        * @var string $root
+        */
+       protected $root;
+
+       protected $config;
+
+       public function tearDown() {
+               try {
+                       if ($this->share) {
+                               $this->cleanDir($this->root);
+                       }
+                       unset($this->share);
+               } catch (\Exception $e) {
+                       unset($this->share);
+                       throw $e;
+               }
+       }
+
+       public function nameProvider() {
+               // / ? < > \ : * | " are illegal characters in path on windows
+               return array(
+                       array('simple'),
+                       array('with spaces_and-underscores'),
+                       array("single'quote'"),
+                       array('日本語'),
+                       array('url %2F +encode'),
+                       array('a somewhat longer filename than the other with more charaters as the all the other filenames'),
+                       array('$as#d€££Ö€ßœĚęĘĞĜΣΥΦΩΫ')
+               );
+       }
+
+       public function fileDataProvider() {
+               return array(
+                       array('Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua'),
+                       array('Mixed language, 日本語 が わからか and Various _/* characters \\|” €')
+               );
+       }
+
+       public function nameAndDataProvider() {
+               $names = $this->nameProvider();
+               $data = $this->fileDataProvider();
+               $result = array();
+               foreach ($names as $name) {
+                       foreach ($data as $text) {
+                               $result[] = array($name[0], $text[0]);
+                       }
+               }
+               return $result;
+       }
+
+       public function cleanDir($dir) {
+               $content = $this->share->dir($dir);
+               foreach ($content as $metadata) {
+                       if ($metadata->isDirectory()) {
+                               $this->cleanDir($metadata->getPath());
+                       } else {
+                               $this->share->del($metadata->getPath());
+                       }
+               }
+               $this->share->rmdir($dir);
+       }
+
+       private function getTextFile($text = '') {
+               if (!$text) {
+                       $text = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua';
+               }
+               $file = tempnam('/tmp', 'smb_test_');
+               file_put_contents($file, $text);
+               return $file;
+       }
+
+       public function testListShares() {
+               $shares = $this->server->listShares();
+               foreach ($shares as $share) {
+                       if ($share->getName() === $this->config->share) {
+                               return;
+                       }
+               }
+               $this->fail('Share "' . $this->config->share . '" not found');
+       }
+
+       public function testRootStartsEmpty() {
+               $this->assertEquals(array(), $this->share->dir($this->root));
+       }
+
+       /**
+        * @dataProvider nameProvider
+        */
+       public function testMkdir($name) {
+               $this->share->mkdir($this->root . '/' . $name);
+               $dirs = $this->share->dir($this->root);
+               $this->assertCount(1, $dirs);
+               $this->assertEquals($name, $dirs[0]->getName());
+               $this->assertTrue($dirs[0]->isDirectory());
+       }
+
+       /**
+        * @dataProvider nameProvider
+        */
+       public function testRenameDirectory($name) {
+               $this->share->mkdir($this->root . '/' . $name);
+               $this->share->rename($this->root . '/' . $name, $this->root . '/' . $name . '_rename');
+               $dirs = $this->share->dir($this->root);
+               $this->assertEquals(1, count($dirs));
+               $this->assertEquals($name . '_rename', $dirs[0]->getName());
+       }
+
+       /**
+        * @dataProvider nameProvider
+        */
+       public function testRmdir($name) {
+               $this->share->mkdir($this->root . '/' . $name);
+               $this->share->rmdir($this->root . '/' . $name);
+               $this->assertCount(0, $this->share->dir($this->root));
+       }
+
+       /**
+        * @dataProvider nameAndDataProvider
+        */
+       public function testPut($name, $text) {
+               $tmpFile = $this->getTextFile($text);
+               $size = filesize($tmpFile);
+
+               $this->share->put($tmpFile, $this->root . '/' . $name);
+               unlink($tmpFile);
+
+               $files = $this->share->dir($this->root);
+               $this->assertCount(1, $files);
+               $this->assertEquals($name, $files[0]->getName());
+               $this->assertEquals($size, $files[0]->getSize());
+               $this->assertFalse($files[0]->isDirectory());
+       }
+
+       /**
+        * @dataProvider nameProvider
+        */
+       public function testRenameFile($name) {
+               $tmpFile = $this->getTextFile();
+
+               $this->share->put($tmpFile, $this->root . '/' . $name);
+               unlink($tmpFile);
+
+               $this->share->rename($this->root . '/' . $name, $this->root . '/' . $name . '_renamed');
+
+               $files = $this->share->dir($this->root);
+               $this->assertEquals(1, count($files));
+               $this->assertEquals($name . '_renamed', $files[0]->getName());
+       }
+
+       /**
+        * @dataProvider nameAndDataProvider
+        */
+       public function testGet($name, $text) {
+               $tmpFile = $this->getTextFile($text);
+
+               $this->share->put($tmpFile, $this->root . '/' . $name);
+               unlink($tmpFile);
+
+               $targetFile = tempnam('/tmp', 'smb_test_');
+               $this->share->get($this->root . '/' . $name, $targetFile);
+
+               $this->assertEquals($text, file_get_contents($targetFile));
+               unlink($targetFile);
+       }
+
+       /**
+        * @dataProvider nameProvider
+        */
+       public function testDel($name) {
+               $tmpFile = $this->getTextFile();
+
+               $this->share->put($tmpFile, $this->root . '/' . $name);
+               unlink($tmpFile);
+
+               $this->share->del($this->root . '/' . $name);
+               $this->assertCount(0, $this->share->dir($this->root));
+       }
+
+       /**
+        * @expectedException \Icewind\SMB\Exception\NotFoundException
+        */
+       public function testCreateFolderInNonExistingFolder() {
+               $this->share->mkdir($this->root . '/foo/bar');
+       }
+
+       /**
+        * @expectedException \Icewind\SMB\Exception\NotFoundException
+        */
+       public function testRemoveFolderInNonExistingFolder() {
+               $this->share->rmdir($this->root . '/foo/bar');
+       }
+
+       /**
+        * @expectedException \Icewind\SMB\Exception\NotFoundException
+        */
+       public function testRemoveNonExistingFolder() {
+               $this->share->rmdir($this->root . '/foo');
+       }
+
+       /**
+        * @expectedException \Icewind\SMB\Exception\AlreadyExistsException
+        */
+       public function testCreateExistingFolder() {
+               $this->share->mkdir($this->root . '/bar');
+               $this->share->mkdir($this->root . '/bar');
+               $this->share->rmdir($this->root . '/bar');
+       }
+
+       /**
+        * @expectedException \Icewind\SMB\Exception\InvalidTypeException
+        */
+       public function testCreateFileExistingFolder() {
+               $this->share->mkdir($this->root . '/bar');
+               $this->share->put($this->getTextFile(), $this->root . '/bar');
+               $this->share->rmdir($this->root . '/bar');
+       }
+
+       /**
+        * @expectedException \Icewind\SMB\Exception\NotFoundException
+        */
+       public function testCreateFileInNonExistingFolder() {
+               $this->share->put($this->getTextFile(), $this->root . '/foo/bar');
+       }
+
+       /**
+        * @expectedException \Icewind\SMB\Exception\NotFoundException
+        */
+       public function testTestRemoveNonExistingFile() {
+               $this->share->del($this->root . '/foo');
+       }
+
+       /**
+        * @expectedException \Icewind\SMB\Exception\NotFoundException
+        */
+       public function testDownloadNonExistingFile() {
+               $this->share->get($this->root . '/foo', '/dev/null');
+       }
+
+       /**
+        * @expectedException \Icewind\SMB\Exception\InvalidTypeException
+        */
+       public function testDownloadFolder() {
+               $this->share->mkdir($this->root . '/foobar');
+               $this->share->get($this->root . '/foobar', '/dev/null');
+               $this->share->rmdir($this->root . '/foobar');
+       }
+
+       /**
+        * @expectedException \Icewind\SMB\Exception\InvalidTypeException
+        */
+       public function testDelFolder() {
+               $this->share->mkdir($this->root . '/foobar');
+               $this->share->del($this->root . '/foobar');
+               $this->share->rmdir($this->root . '/foobar');
+       }
+
+       /**
+        * @expectedException \Icewind\SMB\Exception\InvalidTypeException
+        */
+       public function testRmdirFile() {
+               $this->share->put($this->getTextFile(), $this->root . '/foobar');
+               $this->share->rmdir($this->root . '/foobar');
+               $this->share->del($this->root . '/foobar');
+       }
+
+       /**
+        * @expectedException \Icewind\SMB\Exception\NotEmptyException
+        */
+       public function testRmdirNotEmpty() {
+               $this->share->mkdir($this->root . '/foobar');
+               $this->share->put($this->getTextFile(), $this->root . '/foobar/asd');
+               $this->share->rmdir($this->root . '/foobar');
+       }
+
+       /**
+        * @expectedException \Icewind\SMB\Exception\NotFoundException
+        */
+       public function testDirNonExisting() {
+               $this->share->dir('/foobar/asd');
+       }
+
+       /**
+        * @expectedException \Icewind\SMB\Exception\NotFoundException
+        */
+       public function testRmDirNonExisting() {
+               $this->share->rmdir('/foobar/asd');
+       }
+
+       /**
+        * @expectedException \Icewind\SMB\Exception\NotFoundException
+        */
+       public function testRenameNonExisting() {
+               $this->share->rename('/foobar/asd', '/foobar/bar');
+       }
+
+       /**
+        * @expectedException \Icewind\SMB\Exception\NotFoundException
+        */
+       public function testRenameTargetNonExisting() {
+               $txt = $this->getTextFile();
+               $this->share->put($txt, $this->root . '/foo.txt');
+               unlink($txt);
+               $this->share->rename($this->root . '/foo.txt', $this->root . '/bar/foo.txt');
+       }
+
+       public function testModifiedDate() {
+               $now = time();
+               $this->share->put($this->getTextFile(), $this->root . '/foo.txt');
+               $dir = $this->share->dir($this->root);
+               $mtime = $dir[0]->getMTime();
+               $this->assertTrue(abs($now - $mtime) <= 1, 'Modified time differs by ' . abs($now - $mtime) . ' seconds');
+               $this->share->del($this->root . '/foo.txt');
+       }
+
+       /**
+        * @dataProvider nameAndDataProvider
+        */
+       public function testReadStream($name, $text) {
+               $sourceFile = $this->getTextFile($text);
+               $this->share->put($sourceFile, $this->root . '/' . $name);
+               $fh = $this->share->read($this->root . '/' . $name);
+               $content = stream_get_contents($fh);
+               fclose($fh);
+               $this->share->del($this->root . '/' . $name);
+
+               $this->assertEquals(file_get_contents($sourceFile), $content);
+       }
+
+       /**
+        * @dataProvider nameAndDataProvider
+        */
+       public function testWriteStream($name, $text) {
+               $fh = $this->share->write($this->root . '/' . $name);
+               fwrite($fh, $text);
+               fclose($fh);
+
+               $tmpFile1 = tempnam('/tmp', 'smb_test_');
+               $this->share->get($this->root . '/' . $name, $tmpFile1);
+               $this->assertEquals($text, file_get_contents($tmpFile1));
+               $this->share->del($this->root . '/' . $name);
+               unlink($tmpFile1);
+       }
+
+       public function testDir() {
+               $txtFile = $this->getTextFile();
+
+               $this->share->mkdir($this->root . '/dir');
+               $this->share->put($txtFile, $this->root . '/file.txt');
+               unlink($txtFile);
+
+               $dir = $this->share->dir($this->root);
+               if ($dir[0]->getName() === 'dir') {
+                       $dirEntry = $dir[0];
+               } else {
+                       $dirEntry = $dir[1];
+               }
+               $this->assertTrue($dirEntry->isDirectory());
+               $this->assertFalse($dirEntry->isReadOnly());
+               $this->assertFalse($dirEntry->isReadOnly());
+
+               if ($dir[0]->getName() === 'file.txt') {
+                       $fileEntry = $dir[0];
+               } else {
+                       $fileEntry = $dir[1];
+               }
+               $this->assertFalse($fileEntry->isDirectory());
+               $this->assertFalse($fileEntry->isReadOnly());
+               $this->assertFalse($fileEntry->isReadOnly());
+       }
+
+       /**
+        * @dataProvider nameProvider
+        */
+       public function testStat($name) {
+               $txtFile = $this->getTextFile();
+               $size = filesize($txtFile);
+
+               $this->share->put($txtFile, $this->root . '/' . $name);
+               unlink($txtFile);
+
+               $info = $this->share->stat($this->root . '/' . $name);
+               $this->assertEquals($size, $info->getSize());
+       }
+
+       /**
+        * @expectedException \Icewind\SMB\Exception\NotFoundException
+        */
+       public function testStatNonExisting() {
+               $this->share->stat($this->root . '/fo.txt');
+       }
+
+       /**
+        * note setting archive and system bit is not supported
+        *
+        * @dataProvider nameProvider
+        */
+       public function testSetMode($name) {
+               $txtFile = $this->getTextFile();
+
+               $this->share->put($txtFile, $this->root . '/' . $name);
+
+               $this->share->setMode($this->root . '/' . $name, FileInfo::MODE_NORMAL);
+               $info = $this->share->stat($this->root . '/' . $name);
+               $this->assertFalse($info->isReadOnly());
+               $this->assertFalse($info->isArchived());
+               $this->assertFalse($info->isSystem());
+               $this->assertFalse($info->isHidden());
+
+               $this->share->setMode($this->root . '/' . $name, FileInfo::MODE_READONLY);
+               $info = $this->share->stat($this->root . '/' . $name);
+               $this->assertTrue($info->isReadOnly());
+               $this->assertFalse($info->isArchived());
+               $this->assertFalse($info->isSystem());
+               $this->assertFalse($info->isHidden());
+
+               $this->share->setMode($this->root . '/' . $name, FileInfo::MODE_ARCHIVE);
+               $info = $this->share->stat($this->root . '/' . $name);
+               $this->assertFalse($info->isReadOnly());
+               $this->assertTrue($info->isArchived());
+               $this->assertFalse($info->isSystem());
+               $this->assertFalse($info->isHidden());
+
+               $this->share->setMode($this->root . '/' . $name, FileInfo::MODE_READONLY | FileInfo::MODE_ARCHIVE);
+               $info = $this->share->stat($this->root . '/' . $name);
+               $this->assertTrue($info->isReadOnly());
+               $this->assertTrue($info->isArchived());
+               $this->assertFalse($info->isSystem());
+               $this->assertFalse($info->isHidden());
+
+               $this->share->setMode($this->root . '/' . $name, FileInfo::MODE_HIDDEN);
+               $info = $this->share->stat($this->root . '/' . $name);
+               $this->assertFalse($info->isReadOnly());
+               $this->assertFalse($info->isArchived());
+               $this->assertFalse($info->isSystem());
+               $this->assertTrue($info->isHidden());
+
+               $this->share->setMode($this->root . '/' . $name, FileInfo::MODE_SYSTEM);
+               $info = $this->share->stat($this->root . '/' . $name);
+               $this->assertFalse($info->isReadOnly());
+               $this->assertFalse($info->isArchived());
+               $this->assertTrue($info->isSystem());
+               $this->assertFalse($info->isHidden());
+
+               $this->share->setMode($this->root . '/' . $name, FileInfo::MODE_NORMAL);
+               $info = $this->share->stat($this->root . '/' . $name);
+               $this->assertFalse($info->isReadOnly());
+               $this->assertFalse($info->isArchived());
+               $this->assertFalse($info->isSystem());
+               $this->assertFalse($info->isHidden());
+       }
+
+       public function pathProvider() {
+               // / ? < > \ : * | " are illegal characters in path on windows
+               return array(
+                       array('dir/sub/foo.txt'),
+                       array('bar.txt'),
+                       array("single'quote'/sub/foo.txt"),
+                       array('日本語/url %2F +encode/asd.txt'),
+                       array(
+                               'a somewhat longer folder than the other with more charaters as the all the other filenames/' .
+                               'followed by a somewhat long file name after that.txt'
+                       )
+               );
+       }
+
+       /**
+        * @dataProvider pathProvider
+        */
+       public function testSubDirs($path) {
+               $dirs = explode('/', $path);
+               $name = array_pop($dirs);
+               $fullPath = '';
+               foreach ($dirs as $dir) {
+                       $fullPath .= '/' . $dir;
+                       $this->share->mkdir($this->root . $fullPath);
+               }
+               $txtFile = $this->getTextFile();
+               $size = filesize($txtFile);
+               $this->share->put($txtFile, $this->root . $fullPath . '/' . $name);
+               unlink($txtFile);
+               $info = $this->share->stat($this->root . $fullPath . '/' . $name);
+               $this->assertEquals($size, $info->getSize());
+               $this->assertFalse($info->isHidden());
+       }
+
+       public function testDelAfterStat() {
+               $name = 'foo.txt';
+               $txtFile = $this->getTextFile();
+
+               $this->share->put($txtFile, $this->root . '/' . $name);
+               unlink($txtFile);
+
+               $this->share->stat($this->root . '/' . $name);
+               $this->share->del($this->root . '/foo.txt');
+       }
+
+       /**
+        * @param $name
+        * @dataProvider nameProvider
+        */
+       public function testDirPaths($name) {
+               $txtFile = $this->getTextFile();
+               $this->share->mkdir($this->root . '/' . $name);
+               $this->share->put($txtFile, $this->root . '/' . $name . '/' . $name);
+               unlink($txtFile);
+
+               $content = $this->share->dir($this->root . '/' . $name);
+               $this->assertCount(1, $content);
+               $this->assertEquals($name, $content[0]->getName());
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/tests/NativeShare.php b/apps/files_external/3rdparty/icewind/smb/tests/NativeShare.php
new file mode 100644 (file)
index 0000000..d8e1023
--- /dev/null
@@ -0,0 +1,27 @@
+<?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\SMB\Test;
+
+use Icewind\SMB\NativeServer;
+
+class NativeShare extends AbstractShare {
+       public function setUp() {
+               if (!function_exists('smbclient_state_new')) {
+                       $this->markTestSkipped('libsmbclient php extension not installed');
+               }
+               $this->config = json_decode(file_get_contents(__DIR__ . '/config.json'));
+               $this->server = new NativeServer($this->config->host, $this->config->user, $this->config->password);
+               $this->share = $this->server->getShare($this->config->share);
+               if ($this->config->root) {
+                       $this->root = '/' . $this->config->root . '/' . uniqid();
+               } else {
+                       $this->root = '/' . uniqid();
+               }
+               $this->share->mkdir($this->root);
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/tests/NativeStream.php b/apps/files_external/3rdparty/icewind/smb/tests/NativeStream.php
new file mode 100644 (file)
index 0000000..2d7b62f
--- /dev/null
@@ -0,0 +1,143 @@
+<?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\SMB\Test;
+
+use Icewind\SMB\NativeServer;
+
+class NativeStream extends \PHPUnit_Framework_TestCase {
+       /**
+        * @var \Icewind\SMB\Server $server
+        */
+       protected $server;
+
+       /**
+        * @var \Icewind\SMB\NativeShare $share
+        */
+       protected $share;
+
+       /**
+        * @var string $root
+        */
+       protected $root;
+
+       protected $config;
+
+       public function setUp() {
+               if (!function_exists('smbclient_state_new')) {
+                       $this->markTestSkipped('libsmbclient php extension not installed');
+               }
+               $this->config = json_decode(file_get_contents(__DIR__ . '/config.json'));
+               $this->server = new NativeServer($this->config->host, $this->config->user, $this->config->password);
+               $this->share = $this->server->getShare($this->config->share);
+               if ($this->config->root) {
+                       $this->root = '/' . $this->config->root . '/' . uniqid();
+               } else {
+                       $this->root = '/' . uniqid();
+               }
+               $this->share->mkdir($this->root);
+       }
+
+       private function getTextFile() {
+               $text = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua';
+               $file = tempnam('/tmp', 'smb_test_');
+               file_put_contents($file, $text);
+               return $file;
+       }
+
+       public function testSeekTell() {
+               $sourceFile = $this->getTextFile();
+               $this->share->put($sourceFile, $this->root . '/foobar');
+               $fh = $this->share->read($this->root . '/foobar');
+               $content = fread($fh, 3);
+               $this->assertEquals('Lor', $content);
+
+               fseek($fh, -2, SEEK_CUR);
+
+               $content = fread($fh, 3);
+               $this->assertEquals('ore', $content);
+
+               fseek($fh, 3, SEEK_SET);
+
+               $content = fread($fh, 3);
+               $this->assertEquals('em ', $content);
+
+               fseek($fh, -3, SEEK_END);
+
+               $content = fread($fh, 3);
+               $this->assertEquals('qua', $content);
+
+               fseek($fh, -3, SEEK_END);
+               $this->assertEquals(120, ftell($fh));
+       }
+
+       public function testStat() {
+               $sourceFile = $this->getTextFile();
+               $this->share->put($sourceFile, $this->root . '/foobar');
+               $fh = $this->share->read($this->root . '/foobar');
+               $stat = fstat($fh);
+               $this->assertEquals(filesize($sourceFile), $stat['size']);
+               unlink($sourceFile);
+       }
+
+       public function testTruncate() {
+               if (version_compare(phpversion(), '5.4.0', '<')) {
+                       $this->markTestSkipped('php <5.4 doesn\'t support truncate for stream wrappers');
+               }
+               $fh = $this->share->write($this->root . '/foobar');
+               fwrite($fh, 'foobar');
+               ftruncate($fh, 3);
+               fclose($fh);
+
+               $fh = $this->share->read($this->root . '/foobar');
+               $this->assertEquals('foo', stream_get_contents($fh));
+       }
+
+       public function testEOF() {
+               if (version_compare(phpversion(), '5.4.0', '<')) {
+                       $this->markTestSkipped('php <5.4 doesn\'t support truncate for stream wrappers');
+               }
+               $fh = $this->share->write($this->root . '/foobar');
+               fwrite($fh, 'foobar');
+               fclose($fh);
+
+               $fh = $this->share->read($this->root . '/foobar');
+               fread($fh, 3);
+               $this->assertFalse(feof($fh));
+               fread($fh, 5);
+               $this->assertTrue(feof($fh));
+       }
+
+       public function testLockUnsupported() {
+               $fh = $this->share->write($this->root . '/foobar');
+               $this->assertFalse(flock($fh, LOCK_SH));
+       }
+
+       public function testSetOptionUnsupported() {
+               $fh = $this->share->write($this->root . '/foobar');
+               $this->assertFalse(stream_set_blocking($fh, false));
+       }
+
+       public function tearDown() {
+               if ($this->share) {
+                       $this->cleanDir($this->root);
+               }
+               unset($this->share);
+       }
+
+       public function cleanDir($dir) {
+               $content = $this->share->dir($dir);
+               foreach ($content as $metadata) {
+                       if ($metadata->isDirectory()) {
+                               $this->cleanDir($metadata->getPath());
+                       } else {
+                               $this->share->del($metadata->getPath());
+                       }
+               }
+               $this->share->rmdir($dir);
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/tests/Parser.php b/apps/files_external/3rdparty/icewind/smb/tests/Parser.php
new file mode 100644 (file)
index 0000000..0dd06d6
--- /dev/null
@@ -0,0 +1,87 @@
+<?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\SMB\Test;
+
+
+use Icewind\SMB\FileInfo;
+
+class Parser extends \PHPUnit_Framework_TestCase {
+       public function modeProvider() {
+               return array(
+                       array('D', FileInfo::MODE_DIRECTORY),
+                       array('A', FileInfo::MODE_ARCHIVE),
+                       array('S', FileInfo::MODE_SYSTEM),
+                       array('H', FileInfo::MODE_HIDDEN),
+                       array('R', FileInfo::MODE_READONLY),
+                       array('N', FileInfo::MODE_NORMAL),
+                       array('RA', FileInfo::MODE_READONLY | FileInfo::MODE_ARCHIVE),
+                       array('RAH', FileInfo::MODE_READONLY | FileInfo::MODE_ARCHIVE | FileInfo::MODE_HIDDEN)
+               );
+       }
+
+       /**
+        * @dataProvider modeProvider
+        */
+       public function testParseMode($string, $mode) {
+               $parser = new \Icewind\SMB\Parser('UTC');
+               $this->assertEquals($mode, $parser->parseMode($string), 'Failed parsing ' . $string);
+       }
+
+       public function statProvider() {
+               return array(
+                       array(
+                               array(
+                                       'altname: test.txt',
+                                       'create_time:    Sat Oct 12 07:05:58 PM 2013 CEST',
+                                       'access_time:    Tue Oct 15 02:58:48 PM 2013 CEST',
+                                       'write_time:     Sat Oct 12 07:05:58 PM 2013 CEST',
+                                       'change_time:    Sat Oct 12 07:05:58 PM 2013 CEST',
+                                       'attributes:  (80)',
+                                       'stream: [::$DATA], 29634 bytes'
+                               ),
+                               array(
+                                       'mtime' => strtotime('12 Oct 2013 19:05:58 CEST'),
+                                       'mode' => FileInfo::MODE_NORMAL,
+                                       'size' => 29634
+                               ))
+               );
+       }
+
+       /**
+        * @dataProvider statProvider
+        */
+       public function testStat($output, $stat) {
+               $parser = new \Icewind\SMB\Parser('UTC');
+               $this->assertEquals($stat, $parser->parseStat($output));
+       }
+
+       public function dirProvider() {
+               return array(
+                       array(
+                               array(
+                                       '  .                                   D        0  Tue Aug 26 19:11:56 2014',
+                                       '  ..                                 DR        0  Sun Oct 28 15:24:02 2012',
+                                       '  c.pdf                               N    29634  Sat Oct 12 19:05:58 2013',
+                                       '',
+                                       '                62536 blocks of size 8388608. 57113 blocks available'
+                               ),
+                               array(
+                                       new FileInfo('/c.pdf', 'c.pdf', 29634, strtotime('12 Oct 2013 19:05:58 CEST'), FileInfo::MODE_NORMAL)
+                               )
+                       )
+               );
+       }
+
+       /**
+        * @dataProvider dirProvider
+        */
+       public function testDir($output, $dir) {
+               $parser = new \Icewind\SMB\Parser('CEST');
+               $this->assertEquals($dir, $parser->parseDir($output, ''));
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/tests/Server.php b/apps/files_external/3rdparty/icewind/smb/tests/Server.php
new file mode 100644 (file)
index 0000000..9f62886
--- /dev/null
@@ -0,0 +1,57 @@
+<?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\SMB\Test;
+
+class Server extends \PHPUnit_Framework_TestCase {
+       /**
+        * @var \Icewind\SMB\Server $server
+        */
+       private $server;
+
+       private $config;
+
+       public function setUp() {
+               $this->config = json_decode(file_get_contents(__DIR__ . '/config.json'));
+               $this->server = new \Icewind\SMB\Server($this->config->host, $this->config->user, $this->config->password);
+       }
+
+       public function testListShares() {
+               $shares = $this->server->listShares();
+               foreach ($shares as $share) {
+                       if ($share->getName() === $this->config->share) {
+                               return;
+                       }
+               }
+               $this->fail('Share "' . $this->config->share . '" not found');
+       }
+
+       /**
+        * @expectedException \Icewind\SMB\Exception\AuthenticationException
+        */
+       public function testWrongUserName() {
+               $this->markTestSkipped('This fails for no reason on travis');
+               $server = new \Icewind\SMB\Server($this->config->host, uniqid(), uniqid());
+               $server->listShares();
+       }
+
+       /**
+        * @expectedException \Icewind\SMB\Exception\AuthenticationException
+        */
+       public function testWrongPassword() {
+               $server = new \Icewind\SMB\Server($this->config->host, $this->config->user, uniqid());
+               $server->listShares();
+       }
+
+       /**
+        * @expectedException \Icewind\SMB\Exception\InvalidHostException
+        */
+       public function testWrongHost() {
+               $server = new \Icewind\SMB\Server(uniqid(), $this->config->user, $this->config->password);
+               $server->listShares();
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/tests/Share.php b/apps/files_external/3rdparty/icewind/smb/tests/Share.php
new file mode 100644 (file)
index 0000000..a629914
--- /dev/null
@@ -0,0 +1,24 @@
+<?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\SMB\Test;
+
+use Icewind\SMB\Server as NormalServer;
+
+class Share extends AbstractShare {
+       public function setUp() {
+               $this->config = json_decode(file_get_contents(__DIR__ . '/config.json'));
+               $this->server = new NormalServer($this->config->host, $this->config->user, $this->config->password);
+               $this->share = $this->server->getShare($this->config->share);
+               if ($this->config->root) {
+                       $this->root = '/' . $this->config->root . '/' . uniqid();
+               } else {
+                       $this->root = '/' . uniqid();
+               }
+               $this->share->mkdir($this->root);
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/tests/bootstrap.php b/apps/files_external/3rdparty/icewind/smb/tests/bootstrap.php
new file mode 100644 (file)
index 0000000..dc2e34b
--- /dev/null
@@ -0,0 +1,9 @@
+<?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
+ */
+
+date_default_timezone_set('UTC');
+require_once __DIR__.'/../vendor/autoload.php';
diff --git a/apps/files_external/3rdparty/icewind/smb/tests/config.json b/apps/files_external/3rdparty/icewind/smb/tests/config.json
new file mode 100644 (file)
index 0000000..0ecd7e3
--- /dev/null
@@ -0,0 +1,7 @@
+{
+       "host": "localhost",
+       "user": "test",
+       "password": "test",
+       "share": "test",
+       "root": "test"
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/tests/phpunit.xml b/apps/files_external/3rdparty/icewind/smb/tests/phpunit.xml
new file mode 100644 (file)
index 0000000..3ab244d
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<phpunit bootstrap="bootstrap.php">
+       <testsuite name='SMB'>
+               <directory suffix='.php'>./</directory>
+       </testsuite>
+</phpunit>
diff --git a/apps/files_external/3rdparty/icewind/streams/.gitignore b/apps/files_external/3rdparty/icewind/streams/.gitignore
new file mode 100644 (file)
index 0000000..4f38912
--- /dev/null
@@ -0,0 +1,3 @@
+.idea
+vendor
+composer.lock
diff --git a/apps/files_external/3rdparty/icewind/streams/.travis.yml b/apps/files_external/3rdparty/icewind/streams/.travis.yml
new file mode 100644 (file)
index 0000000..dfa5276
--- /dev/null
@@ -0,0 +1,26 @@
+language: php
+php:
+  - 5.3
+  - 5.4
+  - 5.5
+  - hhvm
+
+matrix:
+    allow_failures:
+        - php: hhvm # due to facebook/hhvm#3321
+
+env:
+  global:
+    - CURRENT_DIR=`pwd`
+
+install:
+  - composer install --dev --no-interaction
+
+script:
+  - mkdir -p build/logs
+  - cd tests
+  - phpunit --coverage-clover ../build/logs/clover.xml --configuration phpunit.xml
+
+after_script:
+ - cd $CURRENT_DIR
+ - php vendor/bin/coveralls -v
diff --git a/apps/files_external/3rdparty/icewind/streams/README.md b/apps/files_external/3rdparty/icewind/streams/README.md
new file mode 100644 (file)
index 0000000..54f6d19
--- /dev/null
@@ -0,0 +1,52 @@
+#Streams#
+
+[![Build Status](https://travis-ci.org/icewind1991/Streams.svg?branch=master)](https://travis-ci.org/icewind1991/Streams)
+[![Coverage Status](https://img.shields.io/coveralls/icewind1991/Streams.svg)](https://coveralls.io/r/icewind1991/Streams?branch=master)
+
+Generic stream wrappers for php.
+
+##CallBackWrapper##
+
+A `CallBackWrapper` can be used to register callbacks on read, write and closing of the stream,
+it wraps an existing stream and can thus be used for any stream in php
+
+The callbacks are passed in the stream context along with the source stream
+and can be any valid [php callable](http://php.net/manual/en/language.types.callable.php)
+
+###Example###
+```php
+<?php
+
+use \Icewind\Streams\CallBackWrapper;
+
+require('vendor/autoload.php');
+
+// get an existing stream to wrap
+$source = fopen('php://temp', 'r+');
+
+// register the callbacks
+$stream = CallbackWrapper::wrap($source,
+       // read callback
+       function ($count) {
+               echo "read " . $count . "bytes\n";
+       },
+       // write callback
+       function ($data) {
+               echo "wrote '" . $data . "'\n";
+       },
+       // close callback
+       function () {
+               echo "stream closed\n";
+       });
+
+fwrite($stream, 'some dummy data');
+
+rewind($stream);
+fread($stream, 5);
+
+fclose($stream);
+```
+
+Note: due to php's internal stream buffering the `$count` passed to the read callback
+will be equal to php's internal buffer size (8192 on default) an not the number of bytes
+requested by `fopen()`
diff --git a/apps/files_external/3rdparty/icewind/streams/composer.json b/apps/files_external/3rdparty/icewind/streams/composer.json
new file mode 100644 (file)
index 0000000..86d3c83
--- /dev/null
@@ -0,0 +1,23 @@
+{
+       "name"             : "icewind/streams",
+       "description"      : "A set of generic stream wrappers",
+       "license"          : "MIT",
+       "authors"          : [
+               {
+                       "name" : "Robin Appelman",
+                       "email": "icewind@owncloud.com"
+               }
+       ],
+       "require"          : {
+               "php": ">=5.3"
+       },
+       "require-dev"      : {
+               "satooshi/php-coveralls": "dev-master"
+       },
+       "autoload"         : {
+               "psr-4": {
+                       "Icewind\\Streams\\Tests\\": "tests/",
+                       "Icewind\\Streams\\": "src/"
+               }
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/src/CallbackWrapper.php b/apps/files_external/3rdparty/icewind/streams/src/CallbackWrapper.php
new file mode 100644 (file)
index 0000000..fd99aa6
--- /dev/null
@@ -0,0 +1,110 @@
+<?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
+ *        'read'   => function($count){} (optional)
+ *        'write'  => function($data){} (optional)
+ *        'close'  => function(){} (optional)
+ *     ]
+ * ]
+ *
+ * All callbacks are called after the operation is executed on the source stream
+ */
+class CallbackWrapper extends Wrapper {
+       /**
+        * @var callable
+        */
+       protected $readCallback;
+
+       /**
+        * @var callable
+        */
+       protected $writeCallback;
+
+       /**
+        * @var callable
+        */
+       protected $closeCallback;
+
+       /**
+        * Wraps a stream with the provided callbacks
+        *
+        * @param resource $source
+        * @param callable $read (optional)
+        * @param callable $write (optional)
+        * @param callable $close (optional)
+        * @return resource
+        *
+        * @throws \BadMethodCallException
+        */
+       public static function wrap($source, $read = null, $write = null, $close = null) {
+               $context = stream_context_create(array(
+                       'callback' => array(
+                               'source' => $source,
+                               'read' => $read,
+                               'write' => $write,
+                               'close' => $close
+                       )
+               ));
+               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;
+       }
+
+       public function stream_open($path, $mode, $options, &$opened_path) {
+               $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'];
+               }
+               return true;
+       }
+
+       public function stream_read($count) {
+               $result = parent::stream_read($count);
+               if ($this->readCallback) {
+                       call_user_func($this->readCallback, $count);
+               }
+               return $result;
+       }
+
+       public function stream_write($data) {
+               $result = parent::stream_write($data);
+               if ($this->writeCallback) {
+                       call_user_func($this->writeCallback, $data);
+               }
+               return $result;
+       }
+
+       public function stream_close() {
+               $result = parent::stream_close();
+               if ($this->closeCallback) {
+                       call_user_func($this->closeCallback);
+               }
+               return $result;
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/src/Directory.php b/apps/files_external/3rdparty/icewind/streams/src/Directory.php
new file mode 100644 (file)
index 0000000..c80a878
--- /dev/null
@@ -0,0 +1,35 @@
+<?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 implements a directory
+ */
+interface Directory {
+       /**
+        * @param string $path
+        * @param array $options
+        * @return bool
+        */
+       public function dir_opendir($path, $options);
+
+       /**
+        * @return string
+        */
+       public function dir_readdir();
+
+       /**
+        * @return bool
+        */
+       public function dir_closedir();
+
+       /**
+        * @return bool
+        */
+       public function dir_rewinddir();
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/src/File.php b/apps/files_external/3rdparty/icewind/streams/src/File.php
new file mode 100644 (file)
index 0000000..6202ef4
--- /dev/null
@@ -0,0 +1,86 @@
+<?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 implements a file
+ */
+interface File {
+       /**
+        * @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 $offset
+        * @param int $whence
+        * @return bool
+        */
+       public function stream_seek($offset, $whence = SEEK_SET);
+
+       /**
+        * @return int
+        */
+       public function stream_tell();
+
+       /**
+        * @param int $count
+        * @return string
+        */
+       public function stream_read($count);
+
+       /**
+        * @param string $data
+        * @return int
+        */
+       public function stream_write($data);
+
+       /**
+        * @param int $option
+        * @param int $arg1
+        * @param int $arg2
+        * @return bool
+        */
+       public function stream_set_option($option, $arg1, $arg2);
+
+       /**
+        * @param int $size
+        * @return bool
+        */
+       public function stream_truncate($size);
+
+       /**
+        * @return array
+        */
+       public function stream_stat();
+
+       /**
+        * @param int $operation
+        * @return bool
+        */
+       public function stream_lock($operation);
+
+       /**
+        * @return bool
+        */
+       public function stream_flush();
+
+       /**
+        * @return bool
+        */
+       public function stream_eof();
+
+       /**
+        * @return bool
+        */
+       public function stream_close();
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/src/IteratorDirectory.php b/apps/files_external/3rdparty/icewind/streams/src/IteratorDirectory.php
new file mode 100644 (file)
index 0000000..c4eac5d
--- /dev/null
@@ -0,0 +1,123 @@
+<?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;
+
+/**
+ * Create a directory handle from an iterator or array
+ *
+ * The following options should be passed in the context when opening the stream
+ * [
+ *     'dir' => [
+ *        'array'    => string[]
+ *        'iterator' => \Iterator
+ *     ]
+ * ]
+ *
+ * Either 'array' or 'iterator' need to be set, if both are set, 'iterator' takes preference
+ */
+class IteratorDirectory implements Directory {
+       /**
+        * @var resource
+        */
+       public $context;
+
+       /**
+        * @var \Iterator
+        */
+       protected $iterator;
+
+       /**
+        * 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['iterator']) and $context['iterator'] instanceof \Iterator) {
+                       $this->iterator = $context['iterator'];
+               } else if (isset($context['array']) and is_array($context['array'])) {
+                       $this->iterator = new \ArrayIterator($context['array']);
+               } else {
+                       throw new \BadMethodCallException('Invalid context, iterator or array 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() {
+               if ($this->iterator->valid()) {
+                       $result = $this->iterator->current();
+                       $this->iterator->next();
+                       return $result;
+               } else {
+                       return false;
+               }
+       }
+
+       /**
+        * @return bool
+        */
+       public function dir_closedir() {
+               return true;
+       }
+
+       /**
+        * @return bool
+        */
+       public function dir_rewinddir() {
+               $this->iterator->rewind();
+               return true;
+       }
+
+       /**
+        * Creates a directory handle from the provided array or iterator
+        *
+        * @param \Iterator | array $source
+        * @return resource
+        *
+        * @throws \BadMethodCallException
+        */
+       public static function wrap($source) {
+               if ($source instanceof \Iterator) {
+                       $context = stream_context_create(array(
+                               'dir' => array(
+                                       'iterator' => $source)
+                       ));
+               } else if (is_array($source)) {
+                       $context = stream_context_create(array(
+                               'dir' => array(
+                                       'array' => $source)
+                       ));
+               } else {
+                       throw new \BadMethodCallException('$source should be an Iterator or array');
+               }
+               stream_wrapper_register('iterator', '\Icewind\Streams\IteratorDirectory');
+               $wrapped = opendir('iterator://', $context);
+               stream_wrapper_unregister('iterator');
+               return $wrapped;
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/src/NullWrapper.php b/apps/files_external/3rdparty/icewind/streams/src/NullWrapper.php
new file mode 100644 (file)
index 0000000..8cbaaa7
--- /dev/null
@@ -0,0 +1,42 @@
+<?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;
+
+/**
+ * Stream wrapper that does nothing, used for tests
+ */
+class NullWrapper extends Wrapper {
+       /**
+        * Wraps a stream with the provided callbacks
+        *
+        * @param resource $source
+        * @return resource
+        *
+        * @throws \BadMethodCallException
+        */
+       public static function wrap($source) {
+               $context = stream_context_create(array(
+                       '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;
+       }
+
+       public function stream_open($path, $mode, $options, &$opened_path) {
+               $this->loadContext('null');
+               return true;
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/src/Wrapper.php b/apps/files_external/3rdparty/icewind/streams/src/Wrapper.php
new file mode 100644 (file)
index 0000000..2e3a6e6
--- /dev/null
@@ -0,0 +1,110 @@
+<?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;
+
+/**
+ * Base class for stream wrappers, wraps an existing stream
+ *
+ * This wrapper itself doesn't implement any functionality but is just a base class for other wrappers to extend
+ */
+abstract class Wrapper implements File {
+       /**
+        * @var resource
+        */
+       public $context;
+
+       /**
+        * The wrapped stream
+        *
+        * @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, "callable" options not set');
+               }
+               if (isset($context['source']) and is_resource($context['source'])) {
+                       $this->setSourceStream($context['source']);
+               } else {
+                       throw new \BadMethodCallException('Invalid context, source not set');
+               }
+               return $context;
+       }
+
+       /**
+        * @param resource $source
+        */
+       protected function setSourceStream($source) {
+               $this->source = $source;
+       }
+
+       public function stream_seek($offset, $whence = SEEK_SET) {
+               $result = fseek($this->source, $offset, $whence);
+               return $result == 0 ? true : false;
+       }
+
+       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);
+               }
+       }
+
+       public function stream_truncate($size) {
+               return ftruncate($this->source, $size);
+       }
+
+       public function stream_stat() {
+               return fstat($this->source);
+       }
+
+       public function stream_lock($mode) {
+               return flock($this->source, $mode);
+       }
+
+       public function stream_flush() {
+               return fflush($this->source);
+       }
+
+       public function stream_eof() {
+               return feof($this->source);
+       }
+
+       public function stream_close() {
+               return fclose($this->source);
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/tests/CallbackWrapper.php b/apps/files_external/3rdparty/icewind/streams/tests/CallbackWrapper.php
new file mode 100644 (file)
index 0000000..229b629
--- /dev/null
@@ -0,0 +1,72 @@
+<?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\Tests;
+
+class CallbackWrapper extends Wrapper {
+
+       /**
+        * @param resource $source
+        * @param callable $read
+        * @param callable $write
+        * @param callable $close
+        * @return resource
+        */
+       protected function wrapSource($source, $read = null, $write = null, $close = null) {
+               return \Icewind\Streams\CallbackWrapper::wrap($source, $read, $write, $close);
+       }
+
+       /**
+        * @expectedException \BadMethodCallException
+        */
+       public function testWrapInvalidSource() {
+               $this->wrapSource('foo');
+       }
+
+       public function testReadCallback() {
+               $called = false;
+               $callBack = function () use (&$called) {
+                       $called = true;
+               };
+
+               $source = fopen('php://temp', 'r+');
+               fwrite($source, 'foobar');
+               rewind($source);
+
+               $wrapped = $this->wrapSource($source, $callBack);
+               $this->assertEquals('foo', fread($wrapped, 3));
+               $this->assertTrue($called);
+       }
+
+       public function testWriteCallback() {
+               $lastData = '';
+               $callBack = function ($data) use (&$lastData) {
+                       $lastData = $data;
+               };
+
+               $source = fopen('php://temp', 'r+');
+
+               $wrapped = $this->wrapSource($source, null, $callBack);
+               fwrite($wrapped, 'foobar');
+               $this->assertEquals('foobar', $lastData);
+       }
+
+       public function testCloseCallback() {
+               $called = false;
+               $callBack = function () use (&$called) {
+                       $called = true;
+               };
+
+               $source = fopen('php://temp', 'r+');
+               fwrite($source, 'foobar');
+               rewind($source);
+
+               $wrapped = $this->wrapSource($source, null, null, $callBack);
+               fclose($wrapped);
+               $this->assertTrue($called);
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/tests/IteratorDirectory.php b/apps/files_external/3rdparty/icewind/streams/tests/IteratorDirectory.php
new file mode 100644 (file)
index 0000000..0d99046
--- /dev/null
@@ -0,0 +1,130 @@
+<?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\Tests;
+
+class IteratorDirectory extends \PHPUnit_Framework_TestCase {
+
+       /**
+        * @param \Iterator | array $source
+        * @return resource
+        */
+       protected function wrapSource($source) {
+               return \Icewind\Streams\IteratorDirectory::wrap($source);
+       }
+
+       /**
+        * @expectedException \BadMethodCallException
+        */
+       public function testNoContext() {
+               $context = stream_context_create(array());
+               stream_wrapper_register('iterator', '\Icewind\Streams\IteratorDirectory');
+               try {
+                       opendir('iterator://', $context);
+                       stream_wrapper_unregister('iterator');
+               } catch (\Exception $e) {
+                       stream_wrapper_unregister('iterator');
+                       throw $e;
+               }
+       }
+
+       /**
+        * @expectedException \BadMethodCallException
+        */
+       public function testInvalidSource() {
+               $context = stream_context_create(array(
+                       'dir' => array(
+                               'array' => 2
+                       )
+               ));
+               stream_wrapper_register('iterator', '\Icewind\Streams\IteratorDirectory');
+               try {
+                       opendir('iterator://', $context);
+                       stream_wrapper_unregister('iterator');
+               } catch (\Exception $e) {
+                       stream_wrapper_unregister('iterator');
+                       throw $e;
+               }
+       }
+
+       /**
+        * @expectedException \BadMethodCallException
+        */
+       public function testWrapInvalidSource() {
+               $this->wrapSource(2);
+       }
+
+       public function fileListProvider() {
+               $longList = array_fill(0, 500, 'foo');
+               return array(
+                       array(
+                               array(
+                                       'foo',
+                                       'bar',
+                                       'qwerty'
+                               )
+                       ),
+                       array(
+                               array(
+                                       'with spaces',
+                                       'under_scores',
+                                       '日本語',
+                                       'character %$_',
+                                       '.',
+                                       '0',
+                                       'double "quotes"',
+                                       "single 'quotes'"
+                               )
+                       ),
+                       array(
+                               array(
+                                       'single item'
+                               )
+                       ),
+                       array(
+                               $longList
+                       ),
+                       array(
+                               array()
+                       )
+               );
+       }
+
+       protected function basicTest($fileList, $dh) {
+               $result = array();
+
+               while (($file = readdir($dh)) !== false) {
+                       $result[] = $file;
+               }
+
+               $this->assertEquals($fileList, $result);
+
+               rewinddir($dh);
+               if (count($fileList)) {
+                       $this->assertEquals($fileList[0], readdir($dh));
+               } else {
+                       $this->assertFalse(readdir($dh));
+               }
+       }
+
+       /**
+        * @dataProvider fileListProvider
+        */
+       public function testBasicIterator($fileList) {
+               $iterator = new \ArrayIterator($fileList);
+               $dh = $this->wrapSource($iterator);
+               $this->basicTest($fileList, $dh);
+       }
+
+       /**
+        * @dataProvider fileListProvider
+        */
+       public function testBasicArray($fileList) {
+               $dh = $this->wrapSource($fileList);
+               $this->basicTest($fileList, $dh);
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/tests/NullWrapper.php b/apps/files_external/3rdparty/icewind/streams/tests/NullWrapper.php
new file mode 100644 (file)
index 0000000..ba42b4d
--- /dev/null
@@ -0,0 +1,59 @@
+<?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\Tests;
+
+class NullWrapper extends Wrapper {
+
+       /**
+        * @param resource $source
+        * @return resource
+        */
+       protected function wrapSource($source) {
+               return \Icewind\Streams\NullWrapper::wrap($source);
+       }
+
+       /**
+        * @expectedException \BadMethodCallException
+        */
+       public function testNoContext() {
+               stream_wrapper_register('null', '\Icewind\Streams\NullWrapper');
+               $context = stream_context_create(array());
+               try {
+                       fopen('null://', 'r+', false, $context);
+                       stream_wrapper_unregister('null');
+               } catch (\Exception $e) {
+                       stream_wrapper_unregister('null');
+                       throw $e;
+               }
+       }
+
+       /**
+        * @expectedException \BadMethodCallException
+        */
+       public function testNoSource() {
+               stream_wrapper_register('null', '\Icewind\Streams\NullWrapper');
+               $context = stream_context_create(array(
+                       'null' => array(
+                               'source' => 'bar'
+                       )
+               ));
+               try {
+                       fopen('null://', 'r+', false, $context);
+               } catch (\Exception $e) {
+                       stream_wrapper_unregister('null');
+                       throw $e;
+               }
+       }
+
+       /**
+        * @expectedException \BadMethodCallException
+        */
+       public function testWrapInvalidSource() {
+               $this->wrapSource('foo');
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/tests/Wrapper.php b/apps/files_external/3rdparty/icewind/streams/tests/Wrapper.php
new file mode 100644 (file)
index 0000000..6bb644d
--- /dev/null
@@ -0,0 +1,105 @@
+<?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\Tests;
+
+abstract class Wrapper extends \PHPUnit_Framework_TestCase {
+       /**
+        * @param resource $source
+        * @return resource
+        */
+       abstract protected function wrapSource($source);
+
+       public function testRead() {
+               $source = fopen('php://temp', 'r+');
+               fwrite($source, 'foobar');
+               rewind($source);
+
+               $wrapped = $this->wrapSource($source);
+               $this->assertEquals('foo', fread($wrapped, 3));
+               $this->assertEquals('bar', fread($wrapped, 3));
+               $this->assertEquals('', fread($wrapped, 3));
+       }
+
+       public function testWrite() {
+               $source = fopen('php://temp', 'r+');
+               rewind($source);
+
+               $wrapped = $this->wrapSource($source);
+
+               $this->assertEquals(6, fwrite($wrapped, 'foobar'));
+               rewind($source);
+               $this->assertEquals('foobar', stream_get_contents($source));
+       }
+
+       public function testClose() {
+               $source = fopen('php://temp', 'r+');
+               rewind($source);
+
+               $wrapped = $this->wrapSource($source);
+
+               fclose($wrapped);
+               $this->assertFalse(is_resource($source));
+       }
+
+       public function testSeekTell() {
+               $source = fopen('php://temp', 'r+');
+               fwrite($source, 'foobar');
+               rewind($source);
+
+               $wrapped = $this->wrapSource($source);
+
+               $this->assertEquals(0, ftell($wrapped));
+
+               fseek($wrapped, 2);
+               $this->assertEquals(2, ftell($source));
+               $this->assertEquals(2, ftell($wrapped));
+
+               fseek($wrapped, 2, SEEK_CUR);
+               $this->assertEquals(4, ftell($source));
+               $this->assertEquals(4, ftell($wrapped));
+
+               fseek($wrapped, -1, SEEK_END);
+               $this->assertEquals(5, ftell($source));
+               $this->assertEquals(5, ftell($wrapped));
+       }
+
+       public function testStat() {
+               $source = fopen(__FILE__, 'r+');
+               $wrapped = $this->wrapSource($source);
+               $this->assertEquals(stat(__FILE__), fstat($wrapped));
+       }
+
+       public function testTruncate() {
+               if (version_compare(phpversion(), '5.4.0', '<')) {
+                       $this->markTestSkipped('php <5.4 doesn\'t support truncate for stream wrappers');
+               }
+               $source = fopen('php://temp', 'r+');
+               fwrite($source, 'foobar');
+               rewind($source);
+               $wrapped = $this->wrapSource($source);
+
+               ftruncate($wrapped, 2);
+               $this->assertEquals('fo', fread($wrapped, 10));
+       }
+
+       public function testLock() {
+               $source = tmpfile();
+               $wrapped = $this->wrapSource($source);
+               if (!flock($wrapped, LOCK_EX)) {
+                       $this->fail('Unable to acquire lock');
+               }
+       }
+
+       public function testStreamOptions() {
+               $source = fopen('php://temp', 'r+');
+               $wrapped = $this->wrapSource($source);
+               stream_set_blocking($wrapped, 0);
+               stream_set_timeout($wrapped, 1, 0);
+               stream_set_write_buffer($wrapped, 0);
+       }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/tests/bootstrap.php b/apps/files_external/3rdparty/icewind/streams/tests/bootstrap.php
new file mode 100644 (file)
index 0000000..2c17fd5
--- /dev/null
@@ -0,0 +1,9 @@
+<?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
+ */
+
+date_default_timezone_set('UTC');
+require_once __DIR__ . '/../vendor/autoload.php';
diff --git a/apps/files_external/3rdparty/icewind/streams/tests/phpunit.xml b/apps/files_external/3rdparty/icewind/streams/tests/phpunit.xml
new file mode 100644 (file)
index 0000000..e3d9635
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<phpunit bootstrap="bootstrap.php">
+       <testsuite name='Stream'>
+               <directory suffix='.php'>./</directory>
+       </testsuite>
+</phpunit>
diff --git a/apps/files_external/3rdparty/smb4php/smb.php b/apps/files_external/3rdparty/smb4php/smb.php
deleted file mode 100644 (file)
index e325506..0000000
+++ /dev/null
@@ -1,516 +0,0 @@
-<?php
-###################################################################
-# smb.php
-# This class implements a SMB stream wrapper based on 'smbclient'
-#
-# Date: lun oct 22 10:35:35 CEST 2007
-#
-# Homepage: http://www.phpclasses.org/smb4php
-#
-# Copyright (c) 2007 Victor M. Varela <vmvarela@gmail.com>
-# Copyright (c) 2012 Frank Karlitschek <frank@owncloud.org>
-# Copyright (c) 2014 Robin McCorkell <rmccorkell@karoshi.org.uk>
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# On the official website http://www.phpclasses.org/smb4php the
-# license is listed as LGPL so we assume that this is
-# dual-licensed GPL/LGPL
-###################################################################
-
-define ('SMB4PHP_VERSION', '0.8');
-
-###################################################################
-# CONFIGURATION SECTION - Change for your needs
-###################################################################
-
-define ('SMB4PHP_SMBCLIENT', 'smbclient');
-define ('SMB4PHP_SMBOPTIONS', 'TCP_NODELAY IPTOS_LOWDELAY SO_KEEPALIVE SO_RCVBUF=8192 SO_SNDBUF=8192');
-define ('SMB4PHP_AUTHMODE', 'arg'); # set to 'env' to use USER enviroment variable
-
-###################################################################
-# SMB - commands that does not need an instance
-###################################################################
-
-$GLOBALS['__smb_cache'] = array ('stat' => array (), 'dir' => array ());
-
-class smb {
-
-       private static $regexp = array (
-               '^added interface ip=(.*) bcast=(.*) nmask=(.*)$' => 'skip',
-               'Anonymous login successful' => 'skip',
-               '^Domain=\[(.*)\] OS=\[(.*)\] Server=\[(.*)\]$' => 'skip',
-               '^\tSharename[ ]+Type[ ]+Comment$' => 'shares',
-               '^\t---------[ ]+----[ ]+-------$' => 'skip',
-               '^\tServer   [ ]+Comment$' => 'servers',
-               '^\t---------[ ]+-------$' => 'skip',
-               '^\tWorkgroup[ ]+Master$' => 'workg',
-               '^\t(.*)[ ]+(Disk|IPC)[ ]+IPC.*$' => 'skip',
-               '^\tIPC\\\$(.*)[ ]+IPC' => 'skip',
-               '^\t(.*)[ ]+(Disk)[ ]+(.*)$' => 'share',
-               '^\t(.*)[ ]+(Printer)[ ]+(.*)$' => 'skip',
-               '([0-9]+) blocks of size ([0-9]+)\. ([0-9]+) blocks available' => 'skip',
-               'Got a positive name query response from ' => 'skip',
-               '^(session setup failed): (.*)$' => 'error',
-               '^(.*): ERRSRV - ERRbadpw' => 'error',
-               '^Error returning browse list: (.*)$' => 'error',
-               '^tree connect failed: (.*)$' => 'error',
-               '^(Connection to .* failed)(.*)$' => 'error-connect',
-               '^NT_STATUS_(.*) ' => 'error',
-               '^NT_STATUS_(.*)\$' => 'error',
-               'ERRDOS - ERRbadpath \((.*).\)' => 'error',
-               'cd (.*): (.*)$' => 'error',
-               '^cd (.*): NT_STATUS_(.*)' => 'error',
-               '^\t(.*)$' => 'srvorwg',
-               '^([0-9]+)[ ]+([0-9]+)[ ]+(.*)$' => 'skip',
-               '^Job ([0-9]+) cancelled' => 'skip',
-               '^[ ]+(.*)[ ]+([0-9]+)[ ]+(Mon|Tue|Wed|Thu|Fri|Sat|Sun)[ ](Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[ ]+([0-9]+)[ ]+([0-9]{2}:[0-9]{2}:[0-9]{2})[ ]([0-9]{4})$' => 'files',
-               '^message start: ERRSRV - (ERRmsgoff)' => 'error'
-       );
-
-       function getRegexp() {
-               return self::$regexp;
-       }
-
-       function parse_url ($url) {
-               $pu = parse_url (trim($url));
-               foreach (array ('domain', 'user', 'pass', 'host', 'port', 'path') as $i) {
-                       if (! isset($pu[$i])) {
-                               $pu[$i] = '';
-                       }
-               }
-               if (count ($userdomain = explode (';', urldecode ($pu['user']))) > 1) {
-                       @list ($pu['domain'], $pu['user']) = $userdomain;
-               }
-               $path = preg_replace (array ('/^\//', '/\/$/'), '', urldecode ($pu['path']));
-               list ($pu['share'], $pu['path']) = (preg_match ('/^([^\/]+)\/(.*)/', $path, $regs))
-                       ? array ($regs[1], preg_replace ('/\//', '\\', $regs[2]))
-                       : array ($path, '');
-               $pu['type'] = $pu['path'] ? 'path' : ($pu['share'] ? 'share' : ($pu['host'] ? 'host' : '**error**'));
-               if (! ($pu['port'] = intval(@$pu['port']))) {
-                       $pu['port'] = 139;
-               }
-
-               // decode user and password
-               $pu['user'] = urldecode($pu['user']);
-               $pu['pass'] = urldecode($pu['pass']);
-               return $pu;
-       }
-
-
-       function look ($purl) {
-               return smb::client ('-L ' . escapeshellarg ($purl['host']), $purl);
-       }
-
-
-       function execute ($command, $purl, $regexp = NULL) {
-               return smb::client ('-d 0 '
-                               . escapeshellarg ('//' . $purl['host'] . '/' . $purl['share'])
-                               . ' -c ' . escapeshellarg ($command), $purl, $regexp
-               );
-       }
-
-       function client ($params, $purl, $regexp = NULL) {
-
-               if ($regexp === NULL) $regexp = smb::$regexp;
-
-               if (SMB4PHP_AUTHMODE == 'env') {
-                       putenv("USER={$purl['user']}%{$purl['pass']}");
-                       $auth = '';
-               } else {
-                       $auth = ($purl['user'] <> '' ? (' -U ' . escapeshellarg ($purl['user'] . '%' . $purl['pass'])) : '');
-               }
-               if ($purl['domain'] <> '') {
-                       $auth .= ' -W ' . escapeshellarg ($purl['domain']);
-               }
-               $port = ($purl['port'] <> 139 ? ' -p ' . escapeshellarg ($purl['port']) : '');
-               $options = '-O ' . escapeshellarg(SMB4PHP_SMBOPTIONS);
-
-               // this put env is necessary to read the output of smbclient correctly
-               $old_locale = getenv('LC_ALL');
-               putenv('LC_ALL=en_US.UTF-8');
-               $output = popen ('TZ=UTC '.SMB4PHP_SMBCLIENT." -N {$auth} {$options} {$port} {$options} {$params} 2>/dev/null", 'r');
-               $gotInfo = false;
-               $info = array ();
-               $info['info']= array ();
-               $mode = '';
-               while ($line = fgets ($output, 4096)) {
-                       list ($tag, $regs, $i) = array ('skip', array (), array ());
-                       reset ($regexp);
-                       foreach ($regexp as $r => $t) if (preg_match ('/'.$r.'/', $line, $regs)) {
-                               $tag = $t;
-                               break;
-                       }
-                       switch ($tag) {
-                               case 'skip':    continue;
-                               case 'shares':  $mode = 'shares';     break;
-                               case 'servers': $mode = 'servers';    break;
-                               case 'workg':   $mode = 'workgroups'; break;
-                               case 'share':
-                                       list($name, $type) = array (
-                                               trim(substr($line, 1, 15)),
-                                               trim(strtolower(substr($line, 17, 10)))
-                                       );
-                                       $i = ($type <> 'disk' && preg_match('/^(.*) Disk/', $line, $regs))
-                                               ? array(trim($regs[1]), 'disk')
-                                               : array($name, 'disk');
-                                       break;
-                               case 'srvorwg':
-                                       list ($name, $master) = array (
-                                               strtolower(trim(substr($line,1,21))),
-                                               strtolower(trim(substr($line, 22)))
-                                       );
-                                       $i = ($mode == 'servers') ? array ($name, "server") : array ($name, "workgroup", $master);
-                                       break;
-                               case 'files':
-                                       list ($attr, $name) = preg_match ("/^(.*)[ ]+([D|A|H|N|S|R]+)$/", trim ($regs[1]), $regs2)
-                                               ? array (trim ($regs2[2]), trim ($regs2[1]))
-                                               : array ('', trim ($regs[1]));
-                                       list ($his, $im) = array (
-                                               explode(':', $regs[6]), 1 + strpos("JanFebMarAprMayJunJulAugSepOctNovDec", $regs[4]) / 3);
-                                       $i = ($name <> '.' && $name <> '..')
-                                               ? array (
-                                                       $name,
-                                                       (strpos($attr,'D') === FALSE) ? 'file' : 'folder',
-                                                       'attr' => $attr,
-                                                       'size' => intval($regs[2]),
-                                                       'time' => mktime ($his[0], $his[1], $his[2], $im, $regs[5], $regs[7])
-                                               )
-                                               : array();
-                                       break;
-                               case 'error':
-                                       if(substr($regs[0],0,22)=='NT_STATUS_NO_SUCH_FILE'){
-                                               return false;
-                                       }elseif(substr($regs[0],0,31)=='NT_STATUS_OBJECT_NAME_COLLISION'){
-                                               return false;
-                                       }elseif(substr($regs[0],0,31)=='NT_STATUS_OBJECT_PATH_NOT_FOUND'){
-                                               return false;
-                                       }elseif(substr($regs[0],0,31)=='NT_STATUS_OBJECT_NAME_NOT_FOUND'){
-                                               return false;
-                                       }elseif(substr($regs[0],0,29)=='NT_STATUS_FILE_IS_A_DIRECTORY'){
-                                               return false;
-                                       }
-                                       trigger_error($regs[0].' params('.$params.')', E_USER_ERROR);
-                               case 'error-connect':
-                                       // connection error can happen after obtaining share list if
-                                       // NetBIOS is disabled/blocked on the target server,
-                                       // in which case we keep the info and continue
-                                       if (!$gotInfo) {
-                                               return false;
-                                       }
-                       }
-                       if ($i) switch ($i[1]) {
-                               case 'file':
-                               case 'folder':    $info['info'][$i[0]] = $i;
-                               case 'disk':
-                               case 'server':
-                               case 'workgroup': $info[$i[1]][] = $i[0];
-                               $gotInfo = true;
-                       }
-               }
-               pclose($output);
-
-
-               // restore previous locale
-               if ($old_locale===false) {
-                       putenv('LC_ALL');
-               } else {
-                       putenv('LC_ALL='.$old_locale);
-               }
-
-               return $info;
-       }
-
-
-       # stats
-
-       function url_stat ($url, $flags = STREAM_URL_STAT_LINK) {
-               if ($s = smb::getstatcache($url)) {
-                       return $s;
-               }
-               list ($stat, $pu) = array (false, smb::parse_url ($url));
-               switch ($pu['type']) {
-                       case 'host':
-                               if ($o = smb::look ($pu))
-                                       $stat = stat ("/tmp");
-                               else
-                                       trigger_error ("url_stat(): list failed for host '{$pu['host']}'", E_USER_WARNING);
-                               break;
-                       case 'share':
-                               if (smb::execute("ls", $pu))
-                                       $stat = stat ("/tmp");
-                               else
-                                       trigger_error ("url_stat(): disk resource '{$pu['share']}' not found in '{$pu['host']}'", E_USER_WARNING);
-                               break;
-                       case 'path':
-                               if ($o = smb::execute ('dir "'.$pu['path'].'"', $pu)) {
-                                       $p = explode('\\', $pu['path']);
-                                       $name = $p[count($p)-1];
-                                       if (isset ($o['info'][$name])) {
-                                               $stat = smb::addstatcache ($url, $o['info'][$name]);
-                                       } else {
-                                               trigger_error ("url_stat(): path '{$pu['path']}' not found", E_USER_WARNING);
-                                       }
-                               } else {
-                                       return false;
-//                                     trigger_error ("url_stat(): dir failed for path '{$pu['path']}'", E_USER_WARNING);
-                               }
-                               break;
-                       default: trigger_error ('error in URL', E_USER_ERROR);
-               }
-               return $stat;
-       }
-
-       function addstatcache ($url, $info) {
-               $url = str_replace('//', '/', $url);
-               $url = rtrim($url, '/');
-               global $__smb_cache;
-               $is_file = (strpos ($info['attr'],'D') === FALSE);
-               $s = ($is_file) ? stat ('/etc/passwd') : stat ('/tmp');
-               $s[7] = $s['size'] = $info['size'];
-               $s[8] = $s[9] = $s[10] = $s['atime'] = $s['mtime'] = $s['ctime'] = $info['time'];
-               return $__smb_cache['stat'][$url] = $s;
-       }
-
-       function getstatcache ($url) {
-               $url = str_replace('//', '/', $url);
-               $url = rtrim($url, '/');
-               global $__smb_cache;
-               return isset ($__smb_cache['stat'][$url]) ? $__smb_cache['stat'][$url] : FALSE;
-       }
-
-       function clearstatcache ($url='') {
-               $url = str_replace('//', '/', $url);
-               $url = rtrim($url, '/');
-               global $__smb_cache;
-               if ($url == '') $__smb_cache['stat'] = array (); else unset ($__smb_cache['stat'][$url]);
-       }
-
-
-       # commands
-
-       function unlink ($url) {
-               $pu = smb::parse_url($url);
-               if ($pu['type'] <> 'path') trigger_error('unlink(): error in URL', E_USER_ERROR);
-               smb::clearstatcache ($url);
-               smb_stream_wrapper::cleardircache (dirname($url));
-               return smb::execute ('del "'.$pu['path'].'"', $pu);
-       }
-
-       function rename ($url_from, $url_to) {
-               $replace = false;
-               list ($from, $to) = array (smb::parse_url($url_from), smb::parse_url($url_to));
-               if ($from['host'] <> $to['host'] ||
-                       $from['share'] <> $to['share'] ||
-                       $from['user'] <> $to['user'] ||
-                       $from['pass'] <> $to['pass'] ||
-                       $from['domain'] <> $to['domain']) {
-                       trigger_error('rename(): FROM & TO must be in same server-share-user-pass-domain', E_USER_ERROR);
-               }
-               if ($from['type'] <> 'path' || $to['type'] <> 'path') {
-                       trigger_error('rename(): error in URL', E_USER_ERROR);
-               }
-               smb::clearstatcache ($url_from);
-               $cmd = '';
-               // check if target file exists
-               if (smb::url_stat($url_to)) {
-                       // delete target file first
-                       $cmd = 'del "' . $to['path'] . '"; ';
-                       $replace = true;
-               }
-               $cmd .= 'rename "' . $from['path'] . '" "' . $to['path'] . '"';
-               $result = smb::execute($cmd, $to);
-               if ($replace) {
-                       // clear again, else the cache will return the info
-                       // from the old file
-                       smb::clearstatcache ($url_to);
-               }
-               return $result !== false;
-       }
-
-       function mkdir ($url, $mode, $options) {
-               $pu = smb::parse_url($url);
-               if ($pu['type'] <> 'path') trigger_error('mkdir(): error in URL', E_USER_ERROR);
-               return smb::execute ('mkdir "'.$pu['path'].'"', $pu)!==false;
-       }
-
-       function rmdir ($url) {
-               $pu = smb::parse_url($url);
-               if ($pu['type'] <> 'path') trigger_error('rmdir(): error in URL', E_USER_ERROR);
-               smb::clearstatcache ($url);
-               smb_stream_wrapper::cleardircache (dirname($url));
-               return smb::execute ('rmdir "'.$pu['path'].'"', $pu)!==false;
-       }
-
-}
-
-###################################################################
-# SMB_STREAM_WRAPPER - class to be registered for smb:// URLs
-###################################################################
-
-class smb_stream_wrapper extends smb {
-
-       # variables
-
-       private $stream, $url, $parsed_url = array (), $mode, $tmpfile;
-       private $need_flush = FALSE;
-       private $dir = array (), $dir_index = -1;
-
-
-       # directories
-
-       function dir_opendir ($url, $options) {
-               if ($d = $this->getdircache ($url)) {
-                       $this->dir = $d;
-                       $this->dir_index = 0;
-                       return TRUE;
-               }
-               $pu = smb::parse_url ($url);
-               switch ($pu['type']) {
-                       case 'host':
-                               if ($o = smb::look ($pu)) {
-                                       $this->dir = $o['disk'];
-                                       $this->dir_index = 0;
-                               } else {
-                                       trigger_error ("dir_opendir(): list failed for host '{$pu['host']}'", E_USER_WARNING);
-                                       return false;
-                               }
-                               break;
-                       case 'share':
-                       case 'path':
-                               if (is_array($o = smb::execute ('dir "'.$pu['path'].'\*"', $pu))) {
-                                       $this->dir = array_keys($o['info']);
-                                       $this->dir_index = 0;
-                                       $this->adddircache ($url, $this->dir);
-                                       if(substr($url,-1,1)=='/'){
-                                               $url=substr($url,0,-1);
-                                       }
-                                       foreach ($o['info'] as $name => $info) {
-                                               smb::addstatcache($url . '/' . $name, $info);
-                                       }
-                               } else {
-                                       trigger_error ("dir_opendir(): dir failed for path '".$pu['path']."'", E_USER_WARNING);
-                                       return false;
-                               }
-                               break;
-                       default:
-                               trigger_error ('dir_opendir(): error in URL', E_USER_ERROR);
-                               return false;
-               }
-               return TRUE;
-       }
-
-       function dir_readdir () {
-               return ($this->dir_index < count($this->dir)) ? $this->dir[$this->dir_index++] : FALSE;
-       }
-
-       function dir_rewinddir () { $this->dir_index = 0; }
-
-       function dir_closedir () { $this->dir = array(); $this->dir_index = -1; return TRUE; }
-
-
-       # cache
-
-       function adddircache ($url, $content) {
-               $url = str_replace('//', '/', $url);
-               $url = rtrim($url, '/');
-               global $__smb_cache;
-               return $__smb_cache['dir'][$url] = $content;
-       }
-
-       function getdircache ($url) {
-               $url = str_replace('//', '/', $url);
-               $url = rtrim($url, '/');
-               global $__smb_cache;
-               return isset ($__smb_cache['dir'][$url]) ? $__smb_cache['dir'][$url] : FALSE;
-       }
-
-       function cleardircache ($url='') {
-               $url = str_replace('//', '/', $url);
-               $url = rtrim($url, '/');
-               global $__smb_cache;
-               if ($url == ''){
-                       $__smb_cache['dir'] = array ();
-               }else{
-                       unset ($__smb_cache['dir'][$url]);
-               }
-       }
-
-
-       # streams
-
-       function stream_open ($url, $mode, $options, $opened_path) {
-               $this->url = $url;
-               $this->mode = $mode;
-               $this->parsed_url = $pu = smb::parse_url($url);
-               if ($pu['type'] <> 'path') trigger_error('stream_open(): error in URL', E_USER_ERROR);
-               switch ($mode) {
-                       case 'r':
-                       case 'r+':
-                       case 'rb':
-                       case 'a':
-                       case 'a+':  $this->tmpfile = tempnam('/tmp', 'smb.down.');
-                               $result = smb::execute ('get "'.$pu['path'].'" "'.$this->tmpfile.'"', $pu);
-                               if($result === false){
-                                       return $result;
-                               }
-                               break;
-                       case 'w':
-                       case 'w+':
-                       case 'wb':
-                       case 'x':
-                       case 'x+':  $this->cleardircache();
-                               $this->tmpfile = tempnam('/tmp', 'smb.up.');
-                               $this->need_flush=true;
-               }
-               $this->stream = fopen ($this->tmpfile, $mode);
-               return TRUE;
-       }
-
-       function stream_close () { return fclose($this->stream); }
-
-       function stream_read ($count) { return fread($this->stream, $count); }
-
-       function stream_write ($data) { $this->need_flush = TRUE; return fwrite($this->stream, $data); }
-
-       function stream_eof () { return feof($this->stream); }
-
-       function stream_tell () { return ftell($this->stream); }
-
-       // PATCH: the wrapper must return true when fseek succeeded by returning 0.
-       function stream_seek ($offset, $whence=null) { return fseek($this->stream, $offset, $whence) === 0; }
-
-       function stream_flush () {
-               if ($this->mode <> 'r' && $this->need_flush) {
-                       smb::clearstatcache ($this->url);
-                       smb::execute ('put "'.$this->tmpfile.'" "'.$this->parsed_url['path'].'"', $this->parsed_url);
-                       $this->need_flush = FALSE;
-               }
-       }
-
-       function stream_stat () { return smb::url_stat ($this->url); }
-
-       function __destruct () {
-               if ($this->tmpfile <> '') {
-                       if ($this->need_flush) $this->stream_flush ();
-                       unlink ($this->tmpfile);
-
-               }
-       }
-
-}
-
-###################################################################
-# Register 'smb' protocol !
-###################################################################
-
-stream_wrapper_register('smb', 'smb_stream_wrapper')
-       or die ('Failed to register protocol');
index 70f6b0159a6f75721ac106ab28ce327ba2ad5159..e74ce3594c19640f515bb9c2f251224556be18f6 100644 (file)
@@ -22,6 +22,8 @@ OC::$CLASSPATH['OC\Files\Storage\SFTP_Key'] = 'files_external/lib/sftp_key.php';
 OC::$CLASSPATH['OC_Mount_Config'] = 'files_external/lib/config.php';
 OC::$CLASSPATH['OCA\Files\External\Api'] = 'files_external/lib/api.php';
 
+require_once __DIR__ . '/../3rdparty/autoload.php';
+
 OCP\App::registerAdmin('files_external', 'settings');
 if (OCP\Config::getAppValue('files_external', 'allow_user_mounting', 'yes') == 'yes') {
        OCP\App::registerPersonal('files_external', 'personal');
index 3f0b0f45bfb0eef63858d7895f2440f262d99a05..571a265e983c5836b09f4d02360fbca263799888 100644 (file)
 
 namespace OC\Files\Storage;
 
-require_once __DIR__ . '/../3rdparty/smb4php/smb.php';
+use Icewind\SMB\Exception\Exception;
+use Icewind\SMB\Exception\NotFoundException;
+use Icewind\SMB\NativeServer;
+use Icewind\SMB\Server;
+use Icewind\Streams\CallbackWrapper;
+use Icewind\Streams\IteratorDirectory;
+use OC\Files\Filesystem;
 
-class SMB extends \OC\Files\Storage\StreamWrapper{
-       private $password;
-       private $user;
-       private $host;
-       private $root;
-       private $share;
+class SMB extends Common {
+       /**
+        * @var \Icewind\SMB\Server
+        */
+       protected $server;
+
+       /**
+        * @var \Icewind\SMB\Share
+        */
+       protected $share;
+
+       /**
+        * @var \Icewind\SMB\FileInfo[]
+        */
+       protected $statCache = array();
 
        public function __construct($params) {
                if (isset($params['host']) && isset($params['user']) && isset($params['password']) && isset($params['share'])) {
-                       $this->host=$params['host'];
-                       $this->user=$params['user'];
-                       $this->password=$params['password'];
-                       $this->share=$params['share'];
-                       $this->root=isset($params['root'])?$params['root']:'/';
-                       if ( ! $this->root || $this->root[0]!='/') {
-                               $this->root='/'.$this->root;
-                       }
-                       if (substr($this->root, -1, 1)!='/') {
-                               $this->root.='/';
+                       if (Server::NativeAvailable()) {
+                               $this->server = new NativeServer($params['host'], $params['user'], $params['password']);
+                       } else {
+                               $this->server = new Server($params['host'], $params['user'], $params['password']);
                        }
-                       if ( ! $this->share || $this->share[0]!='/') {
-                               $this->share='/'.$this->share;
-                       }
-                       if (substr($this->share, -1, 1)=='/') {
-                               $this->share = substr($this->share, 0, -1);
+                       $this->share = $this->server->getShare(trim($params['share'], '/'));
+
+                       $this->root = isset($params['root']) ? $params['root'] : '/';
+                       if (!$this->root || $this->root[0] != '/') {
+                               $this->root = '/' . $this->root;
                        }
                } else {
                        throw new \Exception('Invalid configuration');
                }
        }
 
-       public function getId(){
-               return 'smb::' . $this->user . '@' . $this->host . '/' . $this->share . '/' . $this->root;
+       /**
+        * @return string
+        */
+       public function getId() {
+               return 'smb::' . $this->server->getUser() . '@' . $this->server->getHost() . '/' . $this->share->getName() . '/' . $this->root;
        }
 
-       public function constructUrl($path) {
-               if (substr($path, -1)=='/') {
-                       $path = substr($path, 0, -1);
-               }
-               if (substr($path, 0, 1)=='/') {
-                       $path = substr($path, 1);
+       /**
+        * @param string $path
+        * @return string
+        */
+       protected function buildPath($path) {
+               return Filesystem::normalizePath($this->root . '/' . $path);
+       }
+
+       /**
+        * @param string $path
+        * @return \Icewind\SMB\IFileInfo
+        */
+       protected function getFileInfo($path) {
+               $path = $this->buildPath($path);
+               if (!isset($this->statCache[$path])) {
+                       $this->statCache[$path] = $this->share->stat($path);
                }
-               // remove trailing dots which some versions of samba don't seem to like
-               $path = rtrim($path, '.');
-               $path = urlencode($path);
-               $user = urlencode($this->user);
-               $pass = urlencode($this->password);
-               return 'smb://'.$user.':'.$pass.'@'.$this->host.$this->share.$this->root.$path;
+               return $this->statCache[$path];
        }
 
-       public function stat($path) {
-               if ( ! $path and $this->root=='/') {//mtime doesn't work for shares
-                       $stat=stat($this->constructUrl($path));
-                       if (empty($stat)) {
-                               return false;
-                       }
-                       $mtime=$this->shareMTime();
-                       $stat['mtime']=$mtime;
-                       return $stat;
-               } else {
-                       $stat = stat($this->constructUrl($path));
+       /**
+        * @param string $path
+        * @return \Icewind\SMB\IFileInfo[]
+        */
+       protected function getFolderContents($path) {
+               $path = $this->buildPath($path);
+               $files = $this->share->dir($path);
+               foreach ($files as $file) {
+                       $this->statCache[$path . '/' . $file->getName()] = $file;
+               }
+               return $files;
+       }
 
-                       // smb4php can return an empty array if the connection could not be established
-                       if (empty($stat)) {
-                               return false;
-                       }
+       /**
+        * @param \Icewind\SMB\IFileInfo $info
+        * @return array
+        */
+       protected function formatInfo($info) {
+               return array(
+                       'size' => $info->getSize(),
+                       'mtime' => $info->getMTime()
+               );
+       }
 
-                       return $stat;
-               }
+       /**
+        * @param string $path
+        * @return array
+        */
+       public function stat($path) {
+               return $this->formatInfo($this->getFileInfo($path));
        }
 
        /**
-        * Unlinks file or directory
         * @param string $path
+        * @return bool
         */
        public function unlink($path) {
                if ($this->is_dir($path)) {
-                       $this->rmdir($path);
-               }
-               else {
-                       $url = $this->constructUrl($path);
-                       unlink($url);
-                       clearstatcache(false, $url);
+                       return $this->rmdir($path);
+               } else {
+                       $path = $this->buildPath($path);
+                       unset($this->statCache[$path]);
+                       $this->share->del($path);
+                       return true;
                }
-               // smb4php still returns false even on success so
-               // check here whether file was really deleted
-               return !file_exists($path);
        }
 
        /**
         * check if a file or folder has been updated since $time
+        *
         * @param string $path
         * @param int $time
         * @return bool
         */
-       public function hasUpdated($path,$time) {
-               if(!$path and $this->root=='/') {
+       public function hasUpdated($path, $time) {
+               if (!$path and $this->root == '/') {
                        // mtime doesn't work for shares, but giving the nature of the backend,
                        // doing a full update is still just fast enough
                        return true;
                } else {
-                       $actualTime=$this->filemtime($path);
-                       return $actualTime>$time;
+                       $actualTime = $this->filemtime($path);
+                       return $actualTime > $time;
                }
        }
 
        /**
-        * get the best guess for the modification time of the share
+        * @param string $path
+        * @param string $mode
+        * @return resource
         */
-       private function shareMTime() {
-               $dh=$this->opendir('');
-               $lastCtime=0;
-               if(is_resource($dh)) {
-                       while (($file = readdir($dh)) !== false) {
-                               if ($file!='.' and $file!='..') {
-                                       $ctime=$this->filemtime($file);
-                                       if ($ctime>$lastCtime) {
-                                               $lastCtime=$ctime;
+       public function fopen($path, $mode) {
+               $fullPath = $this->buildPath($path);
+               try {
+                       switch ($mode) {
+                               case 'r':
+                               case 'rb':
+                                       if (!$this->file_exists($path)) {
+                                               return false;
+                                       }
+                                       return $this->share->read($fullPath);
+                               case 'w':
+                               case 'wb':
+                                       return $this->share->write($fullPath);
+                               case 'a':
+                               case 'ab':
+                               case 'r+':
+                               case 'w+':
+                               case 'wb+':
+                               case 'a+':
+                               case 'x':
+                               case 'x+':
+                               case 'c':
+                               case 'c+':
+                                       //emulate these
+                                       if (strrpos($path, '.') !== false) {
+                                               $ext = substr($path, strrpos($path, '.'));
+                                       } else {
+                                               $ext = '';
                                        }
+                                       if ($this->file_exists($path)) {
+                                               if (!$this->isUpdatable($path)) {
+                                                       return false;
+                                               }
+                                               $tmpFile = $this->getCachedFile($path);
+                                       } else {
+                                               if (!$this->isCreatable(dirname($path))) {
+                                                       return false;
+                                               }
+                                               $tmpFile = \OCP\Files::tmpFile($ext);
+                                       }
+                                       $source = fopen($tmpFile, $mode);
+                                       $share = $this->share;
+                                       return CallBackWrapper::wrap($source, null, null, function () use ($tmpFile, $fullPath, $share) {
+                                               $share->put($tmpFile, $fullPath);
+                                               unlink($tmpFile);
+                                       });
+                       }
+                       return false;
+               } catch (NotFoundException $e) {
+                       return false;
+               }
+       }
+
+       public function rmdir($path) {
+               try {
+                       $this->statCache = array();
+                       $content = $this->share->dir($this->buildPath($path));
+                       foreach ($content as $file) {
+                               if ($file->isDirectory()) {
+                                       $this->rmdir($path . '/' . $file->getName());
+                               } else {
+                                       $this->share->del($file->getPath());
                                }
                        }
+                       $this->share->rmdir($this->buildPath($path));
+                       return true;
+               } catch (NotFoundException $e) {
+                       return false;
+               }
+       }
+
+       public function touch($path, $time = null) {
+               if (!$this->file_exists($path)) {
+                       $fh = $this->share->write($this->buildPath($path));
+                       fclose($fh);
+                       return true;
+               }
+               return false;
+       }
+
+       public function opendir($path) {
+               $files = $this->getFolderContents($path);
+               $names = array_map(function ($info) {
+                       /** @var \Icewind\SMB\IFileInfo $info */
+                       return $info->getName();
+               }, $files);
+               return IteratorDirectory::wrap($names);
+       }
+
+       public function filetype($path) {
+               try {
+                       return $this->getFileInfo($path)->isDirectory() ? 'dir' : 'file';
+               } catch (NotFoundException $e) {
+                       return false;
+               }
+       }
+
+       public function mkdir($path) {
+               $path = $this->buildPath($path);
+               try {
+                       $this->share->mkdir($path);
+                       return true;
+               } catch (Exception $e) {
+                       return false;
+               }
+       }
+
+       public function file_exists($path) {
+               try {
+                       $this->getFileInfo($path);
+                       return true;
+               } catch (NotFoundException $e) {
+                       return false;
                }
-               return $lastCtime;
        }
 
        /**
         * check if smbclient is installed
         */
        public static function checkDependencies() {
-               $smbClientExists = (bool) \OC_Helper::findBinaryPath('smbclient');
-               return $smbClientExists ? true : array('smbclient');
+               if (function_exists('shell_exec')) {
+                       $output = shell_exec('command -v smbclient 2> /dev/null');
+                       if (!empty($output)) {
+                               return true;
+                       }
+               }
+               return array('smbclient');
        }
-
 }
index a7c93d97fd170e96cf674faa80af83e502e32748..245d1ed79b3e5835963f039e3be2b897da7e386c 100644 (file)
@@ -8,9 +8,12 @@
 
 namespace OC\Files\Storage;
 
-require_once __DIR__ . '/../3rdparty/smb4php/smb.php';
 
-class SMB_OC extends \OC\Files\Storage\SMB {
+use Icewind\SMB\Exception\AccessDeniedException;
+use Icewind\SMB\Exception\Exception;
+use Icewind\SMB\Server;
+
+class SMB_OC extends SMB {
        private $username_as_share;
 
        /**
@@ -19,18 +22,18 @@ class SMB_OC extends \OC\Files\Storage\SMB {
         */
        public function __construct($params) {
                if (isset($params['host']) && \OC::$server->getSession()->exists('smb-credentials')) {
-                       $host=$params['host'];
+                       $host = $params['host'];
                        $this->username_as_share = ($params['username_as_share'] === 'true');
 
                        $params_auth = json_decode(\OC::$server->getCrypto()->decrypt(\OC::$server->getSession()->get('smb-credentials')), true);
                        $user = \OC::$server->getSession()->get('loginname');
                        $password = $params_auth['password'];
 
-                       $root=isset($params['root'])?$params['root']:'/';
+                       $root = isset($params['root']) ? $params['root'] : '/';
                        $share = '';
 
                        if ($this->username_as_share) {
-                               $share = '/'.$user;
+                               $share = '/' . $user;
                        } elseif (isset($params['share'])) {
                                $share = $params['share'];
                        } else {
@@ -84,33 +87,15 @@ class SMB_OC extends \OC\Files\Storage\SMB {
                        }
                        return false;
                } else {
-                       $smb = new \smb();
-                       $pu = $smb->parse_url($this->constructUrl(''));
-
-                       // Attempt to connect anonymously
-                       $pu['user'] = '';
-                       $pu['pass'] = '';
-
-                       // Share cannot be checked if dynamic
-                       if ($this->username_as_share) {
-                               if ($smb->look($pu)) {
-                                       return true;
-                               } else {
-                                       return false;
-                               }
-                       }
-                       if (!$pu['share']) {
-                               return false;
-                       }
-
-                       // The following error messages are expected due to anonymous login
-                       $regexp = array(
-                               '(NT_STATUS_ACCESS_DENIED)' => 'skip'
-                       ) + $smb->getRegexp();
+                       $server = new Server($this->server->getHost(), '', '');
 
-                       if ($smb->client("-d 0 " . escapeshellarg('//' . $pu['host'] . '/' . $pu['share']) . " -c exit", $pu, $regexp)) {
+                       try {
+                               $server->listShares();
                                return true;
-                       } else {
+                       } catch (AccessDeniedException $e) {
+                               // expected due to anonymous login
+                               return true;
+                       } catch (Exception $e) {
                                return false;
                        }
                }
index 4b2f4425ebcef11c2291184b86b271062ea815e1..b66459c42adda8bf7ab67878b00a9fb48dea4d4e 100644 (file)
@@ -27,7 +27,7 @@ class SMB extends Storage {
 
        protected function tearDown() {
                if ($this->instance) {
-                       \OCP\Files::rmdirr($this->instance->constructUrl(''));
+                       $this->instance->rmdir('');
                }
 
                parent::tearDown();