Browse Source

update icewind/smb to 3.4.0

Signed-off-by: Robin Appelman <robin@icewind.nl>
tags/v22.0.0beta1
Robin Appelman 3 years ago
parent
commit
66781e74ad
No account linked to committer's email address
75 changed files with 1943 additions and 1206 deletions
  1. 3
    0
      apps/files_external/3rdparty/.gitignore
  2. 2
    2
      apps/files_external/3rdparty/composer.json
  3. 30
    20
      apps/files_external/3rdparty/composer.lock
  4. 37
    3
      apps/files_external/3rdparty/composer/ClassLoader.php
  5. 301
    0
      apps/files_external/3rdparty/composer/InstalledVersions.php
  6. 7
    1
      apps/files_external/3rdparty/composer/autoload_classmap.php
  7. 0
    1
      apps/files_external/3rdparty/composer/autoload_psr4.php
  8. 4
    2
      apps/files_external/3rdparty/composer/autoload_real.php
  9. 7
    6
      apps/files_external/3rdparty/composer/autoload_static.php
  10. 103
    87
      apps/files_external/3rdparty/composer/installed.json
  11. 42
    0
      apps/files_external/3rdparty/composer/installed.php
  12. 26
    0
      apps/files_external/3rdparty/composer/platform_check.php
  13. 1
    0
      apps/files_external/3rdparty/icewind/smb/.gitignore
  14. 15
    5
      apps/files_external/3rdparty/icewind/smb/README.md
  15. 35
    27
      apps/files_external/3rdparty/icewind/smb/composer.json
  16. 3
    0
      apps/files_external/3rdparty/icewind/smb/src/ACL.php
  17. 11
    19
      apps/files_external/3rdparty/icewind/smb/src/AbstractServer.php
  18. 10
    2
      apps/files_external/3rdparty/icewind/smb/src/AbstractShare.php
  19. 5
    5
      apps/files_external/3rdparty/icewind/smb/src/AnonymousAuth.php
  20. 7
    14
      apps/files_external/3rdparty/icewind/smb/src/BasicAuth.php
  21. 5
    16
      apps/files_external/3rdparty/icewind/smb/src/Change.php
  22. 21
    7
      apps/files_external/3rdparty/icewind/smb/src/Exception/Exception.php
  23. 2
    6
      apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidRequestException.php
  24. 1
    1
      apps/files_external/3rdparty/icewind/smb/src/Exception/RevisionMismatchException.php
  25. 5
    14
      apps/files_external/3rdparty/icewind/smb/src/IAuth.php
  26. 9
    36
      apps/files_external/3rdparty/icewind/smb/src/IFileInfo.php
  27. 4
    4
      apps/files_external/3rdparty/icewind/smb/src/INotifyHandler.php
  28. 16
    4
      apps/files_external/3rdparty/icewind/smb/src/IOptions.php
  29. 8
    31
      apps/files_external/3rdparty/icewind/smb/src/IServer.php
  30. 44
    39
      apps/files_external/3rdparty/icewind/smb/src/IShare.php
  31. 17
    17
      apps/files_external/3rdparty/icewind/smb/src/ISystem.php
  32. 1
    1
      apps/files_external/3rdparty/icewind/smb/src/ITimeZoneProvider.php
  33. 5
    5
      apps/files_external/3rdparty/icewind/smb/src/KerberosAuth.php
  34. 35
    69
      apps/files_external/3rdparty/icewind/smb/src/Native/NativeFileInfo.php
  35. 26
    33
      apps/files_external/3rdparty/icewind/smb/src/Native/NativeReadStream.php
  36. 14
    15
      apps/files_external/3rdparty/icewind/smb/src/Native/NativeServer.php
  37. 68
    65
      apps/files_external/3rdparty/icewind/smb/src/Native/NativeShare.php
  38. 85
    39
      apps/files_external/3rdparty/icewind/smb/src/Native/NativeState.php
  39. 36
    12
      apps/files_external/3rdparty/icewind/smb/src/Native/NativeStream.php
  40. 21
    29
      apps/files_external/3rdparty/icewind/smb/src/Native/NativeWriteStream.php
  41. 23
    2
      apps/files_external/3rdparty/icewind/smb/src/Options.php
  42. 3
    3
      apps/files_external/3rdparty/icewind/smb/src/ServerFactory.php
  43. 63
    0
      apps/files_external/3rdparty/icewind/smb/src/StringBuffer.php
  44. 10
    10
      apps/files_external/3rdparty/icewind/smb/src/System.php
  45. 1
    1
      apps/files_external/3rdparty/icewind/smb/src/TimeZoneProvider.php
  46. 30
    19
      apps/files_external/3rdparty/icewind/smb/src/Wrapped/Connection.php
  47. 17
    58
      apps/files_external/3rdparty/icewind/smb/src/Wrapped/FileInfo.php
  48. 17
    17
      apps/files_external/3rdparty/icewind/smb/src/Wrapped/NotifyHandler.php
  49. 103
    17
      apps/files_external/3rdparty/icewind/smb/src/Wrapped/Parser.php
  50. 54
    20
      apps/files_external/3rdparty/icewind/smb/src/Wrapped/RawConnection.php
  51. 22
    9
      apps/files_external/3rdparty/icewind/smb/src/Wrapped/Server.php
  52. 105
    121
      apps/files_external/3rdparty/icewind/smb/src/Wrapped/Share.php
  53. 3
    0
      apps/files_external/3rdparty/icewind/streams/.gitignore
  54. 0
    24
      apps/files_external/3rdparty/icewind/streams/.travis.yml
  55. 3
    4
      apps/files_external/3rdparty/icewind/streams/README.md
  56. 17
    12
      apps/files_external/3rdparty/icewind/streams/composer.json
  57. 22
    24
      apps/files_external/3rdparty/icewind/streams/src/CallbackWrapper.php
  58. 6
    9
      apps/files_external/3rdparty/icewind/streams/src/CountWrapper.php
  59. 1
    1
      apps/files_external/3rdparty/icewind/streams/src/Directory.php
  60. 7
    10
      apps/files_external/3rdparty/icewind/streams/src/DirectoryFilter.php
  61. 4
    45
      apps/files_external/3rdparty/icewind/streams/src/DirectoryWrapper.php
  62. 5
    5
      apps/files_external/3rdparty/icewind/streams/src/File.php
  63. 78
    0
      apps/files_external/3rdparty/icewind/streams/src/HashWrapper.php
  64. 16
    26
      apps/files_external/3rdparty/icewind/streams/src/IteratorDirectory.php
  65. 3
    15
      apps/files_external/3rdparty/icewind/streams/src/NullWrapper.php
  66. 2
    2
      apps/files_external/3rdparty/icewind/streams/src/Path.php
  67. 2
    4
      apps/files_external/3rdparty/icewind/streams/src/PathWrapper.php
  68. 40
    0
      apps/files_external/3rdparty/icewind/streams/src/ReadHashWrapper.php
  69. 3
    19
      apps/files_external/3rdparty/icewind/streams/src/RetryWrapper.php
  70. 8
    17
      apps/files_external/3rdparty/icewind/streams/src/SeekableWrapper.php
  71. 3
    3
      apps/files_external/3rdparty/icewind/streams/src/Url.php
  72. 37
    23
      apps/files_external/3rdparty/icewind/streams/src/UrlCallback.php
  73. 12
    49
      apps/files_external/3rdparty/icewind/streams/src/Wrapper.php
  74. 114
    0
      apps/files_external/3rdparty/icewind/streams/src/WrapperHandler.php
  75. 37
    0
      apps/files_external/3rdparty/icewind/streams/src/WriteHashWrapper.php

+ 3
- 0
apps/files_external/3rdparty/.gitignore View File

icewind/smb/.travis.yml icewind/smb/.travis.yml
icewind/smb/.scrutinizer.yml icewind/smb/.scrutinizer.yml
icewind/streams/tests icewind/streams/tests
.github
.php_cs*
psalm.xml

+ 2
- 2
apps/files_external/3rdparty/composer.json View File

"classmap-authoritative": true "classmap-authoritative": true
}, },
"require": { "require": {
"icewind/streams": "0.7.1",
"icewind/smb": "3.2.7"
"icewind/streams": "0.7.3",
"icewind/smb": "3.4.0"
} }
} }

+ 30
- 20
apps/files_external/3rdparty/composer.lock View File

"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "6181c23a5c03b00fbdc659d87c1ad67d",
"content-hash": "9905ed45527f669a4165a8b83b6e4141",
"packages": [ "packages": [
{ {
"name": "icewind/smb", "name": "icewind/smb",
"version": "v3.2.7",
"version": "v3.4.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/icewind1991/SMB.git", "url": "https://github.com/icewind1991/SMB.git",
"reference": "743a7bf35317f1b76cf8e8b804e54a6c5faacad6"
"reference": "b5c6921f2e91229c9f71556a4713b4fac91fd394"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/icewind1991/SMB/zipball/743a7bf35317f1b76cf8e8b804e54a6c5faacad6",
"reference": "743a7bf35317f1b76cf8e8b804e54a6c5faacad6",
"url": "https://api.github.com/repos/icewind1991/SMB/zipball/b5c6921f2e91229c9f71556a4713b4fac91fd394",
"reference": "b5c6921f2e91229c9f71556a4713b4fac91fd394",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"icewind/streams": ">=0.2.0",
"php": ">=7.1"
"icewind/streams": ">=0.7.3",
"php": ">=7.2"
}, },
"require-dev": { "require-dev": {
"friendsofphp/php-cs-fixer": "^2.13",
"phpunit/phpunit": "^7.0"
"friendsofphp/php-cs-fixer": "^2.16",
"phpstan/phpstan": "^0.12.57",
"phpunit/phpunit": "^8.5|^9.3.8",
"psalm/phar": "^4.3"
}, },
"type": "library", "type": "library",
"autoload": { "autoload": {
} }
], ],
"description": "php wrapper for smbclient and libsmbclient-php", "description": "php wrapper for smbclient and libsmbclient-php",
"time": "2020-09-03T13:00:22+00:00"
"support": {
"issues": "https://github.com/icewind1991/SMB/issues",
"source": "https://github.com/icewind1991/SMB/tree/v3.4.0"
},
"time": "2021-03-10T14:00:37+00:00"
}, },
{ {
"name": "icewind/streams", "name": "icewind/streams",
"version": "v0.7.1",
"version": "v0.7.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/icewind1991/Streams.git", "url": "https://github.com/icewind1991/Streams.git",
"reference": "4db3ed6c366e90b958d00e1d4c6360a9b39b2121"
"reference": "22ef9fc5b50d645dbc202206a656cc4dde28f95c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/icewind1991/Streams/zipball/4db3ed6c366e90b958d00e1d4c6360a9b39b2121",
"reference": "4db3ed6c366e90b958d00e1d4c6360a9b39b2121",
"url": "https://api.github.com/repos/icewind1991/Streams/zipball/22ef9fc5b50d645dbc202206a656cc4dde28f95c",
"reference": "22ef9fc5b50d645dbc202206a656cc4dde28f95c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=5.3"
"php": ">=7.1"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^4.8",
"satooshi/php-coveralls": "v1.0.0"
"friendsofphp/php-cs-fixer": "^2",
"phpstan/phpstan": "^0.12",
"phpunit/phpunit": "^9"
}, },
"type": "library", "type": "library",
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"Icewind\\Streams\\Tests\\": "tests/",
"Icewind\\Streams\\": "src/" "Icewind\\Streams\\": "src/"
} }
}, },
} }
], ],
"description": "A set of generic stream wrappers", "description": "A set of generic stream wrappers",
"time": "2019-02-15T12:57:29+00:00"
"support": {
"issues": "https://github.com/icewind1991/Streams/issues",
"source": "https://github.com/icewind1991/Streams/tree/v0.7.3"
},
"time": "2021-03-02T19:33:35+00:00"
} }
], ],
"packages-dev": [], "packages-dev": [],
"prefer-lowest": false, "prefer-lowest": false,
"platform": [], "platform": [],
"platform-dev": [], "platform-dev": [],
"plugin-api-version": "1.1.0"
"plugin-api-version": "2.0.0"
} }

+ 37
- 3
apps/files_external/3rdparty/composer/ClassLoader.php View File

* *
* @author Fabien Potencier <fabien@symfony.com> * @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be> * @author Jordi Boggiano <j.boggiano@seld.be>
* @see http://www.php-fig.org/psr/psr-0/
* @see http://www.php-fig.org/psr/psr-4/
* @see https://www.php-fig.org/psr/psr-0/
* @see https://www.php-fig.org/psr/psr-4/
*/ */
class ClassLoader class ClassLoader
{ {
private $vendorDir;

// PSR-4 // PSR-4
private $prefixLengthsPsr4 = array(); private $prefixLengthsPsr4 = array();
private $prefixDirsPsr4 = array(); private $prefixDirsPsr4 = array();
private $missingClasses = array(); private $missingClasses = array();
private $apcuPrefix; private $apcuPrefix;


private static $registeredLoaders = array();

public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
}

public function getPrefixes() public function getPrefixes()
{ {
if (!empty($this->prefixesPsr0)) { if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', $this->prefixesPsr0);
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
} }


return array(); return array();
public function register($prepend = false) public function register($prepend = false)
{ {
spl_autoload_register(array($this, 'loadClass'), true, $prepend); spl_autoload_register(array($this, 'loadClass'), true, $prepend);

if (null === $this->vendorDir) {
return;
}

if ($prepend) {
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
} else {
unset(self::$registeredLoaders[$this->vendorDir]);
self::$registeredLoaders[$this->vendorDir] = $this;
}
} }


/** /**
public function unregister() public function unregister()
{ {
spl_autoload_unregister(array($this, 'loadClass')); spl_autoload_unregister(array($this, 'loadClass'));

if (null !== $this->vendorDir) {
unset(self::$registeredLoaders[$this->vendorDir]);
}
} }


/** /**
return $file; return $file;
} }


/**
* Returns the currently registered loaders indexed by their corresponding vendor directories.
*
* @return self[]
*/
public static function getRegisteredLoaders()
{
return self::$registeredLoaders;
}

private function findFileWithExtension($class, $ext) private function findFileWithExtension($class, $ext)
{ {
// PSR-4 lookup // PSR-4 lookup

+ 301
- 0
apps/files_external/3rdparty/composer/InstalledVersions.php View File

<?php











namespace Composer;

use Composer\Autoload\ClassLoader;
use Composer\Semver\VersionParser;






class InstalledVersions
{
private static $installed = array (
'root' =>
array (
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'aliases' =>
array (
),
'reference' => '62929cc646134fbd409cfb4eacb7039d15763b96',
'name' => 'files_external/3rdparty',
),
'versions' =>
array (
'files_external/3rdparty' =>
array (
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'aliases' =>
array (
),
'reference' => '62929cc646134fbd409cfb4eacb7039d15763b96',
),
'icewind/smb' =>
array (
'pretty_version' => 'v3.4.0',
'version' => '3.4.0.0',
'aliases' =>
array (
),
'reference' => 'b5c6921f2e91229c9f71556a4713b4fac91fd394',
),
'icewind/streams' =>
array (
'pretty_version' => 'v0.7.3',
'version' => '0.7.3.0',
'aliases' =>
array (
),
'reference' => '22ef9fc5b50d645dbc202206a656cc4dde28f95c',
),
),
);
private static $canGetVendors;
private static $installedByVendor = array();







public static function getInstalledPackages()
{
$packages = array();
foreach (self::getInstalled() as $installed) {
$packages[] = array_keys($installed['versions']);
}


if (1 === \count($packages)) {
return $packages[0];
}

return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
}









public static function isInstalled($packageName)
{
foreach (self::getInstalled() as $installed) {
if (isset($installed['versions'][$packageName])) {
return true;
}
}

return false;
}














public static function satisfies(VersionParser $parser, $packageName, $constraint)
{
$constraint = $parser->parseConstraints($constraint);
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));

return $provided->matches($constraint);
}










public static function getVersionRanges($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}

$ranges = array();
if (isset($installed['versions'][$packageName]['pretty_version'])) {
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
}
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
}
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
}
if (array_key_exists('provided', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
}

return implode(' || ', $ranges);
}

throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}





public static function getVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}

if (!isset($installed['versions'][$packageName]['version'])) {
return null;
}

return $installed['versions'][$packageName]['version'];
}

throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}





public static function getPrettyVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}

if (!isset($installed['versions'][$packageName]['pretty_version'])) {
return null;
}

return $installed['versions'][$packageName]['pretty_version'];
}

throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}





public static function getReference($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}

if (!isset($installed['versions'][$packageName]['reference'])) {
return null;
}

return $installed['versions'][$packageName]['reference'];
}

throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}





public static function getRootPackage()
{
$installed = self::getInstalled();

return $installed[0]['root'];
}







public static function getRawData()
{
return self::$installed;
}



















public static function reload($data)
{
self::$installed = $data;
self::$installedByVendor = array();
}




private static function getInstalled()
{
if (null === self::$canGetVendors) {
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
}

$installed = array();

if (self::$canGetVendors) {
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) {
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
}
}
}

$installed[] = self::$installed;

return $installed;
}
}

+ 7
- 1
apps/files_external/3rdparty/composer/autoload_classmap.php View File

$baseDir = $vendorDir; $baseDir = $vendorDir;


return array( return array(
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
'Icewind\\SMB\\ACL' => $vendorDir . '/icewind/smb/src/ACL.php', 'Icewind\\SMB\\ACL' => $vendorDir . '/icewind/smb/src/ACL.php',
'Icewind\\SMB\\AbstractServer' => $vendorDir . '/icewind/smb/src/AbstractServer.php', 'Icewind\\SMB\\AbstractServer' => $vendorDir . '/icewind/smb/src/AbstractServer.php',
'Icewind\\SMB\\AbstractShare' => $vendorDir . '/icewind/smb/src/AbstractShare.php', 'Icewind\\SMB\\AbstractShare' => $vendorDir . '/icewind/smb/src/AbstractShare.php',
'Icewind\\SMB\\Native\\NativeWriteStream' => $vendorDir . '/icewind/smb/src/Native/NativeWriteStream.php', 'Icewind\\SMB\\Native\\NativeWriteStream' => $vendorDir . '/icewind/smb/src/Native/NativeWriteStream.php',
'Icewind\\SMB\\Options' => $vendorDir . '/icewind/smb/src/Options.php', 'Icewind\\SMB\\Options' => $vendorDir . '/icewind/smb/src/Options.php',
'Icewind\\SMB\\ServerFactory' => $vendorDir . '/icewind/smb/src/ServerFactory.php', 'Icewind\\SMB\\ServerFactory' => $vendorDir . '/icewind/smb/src/ServerFactory.php',
'Icewind\\SMB\\StringBuffer' => $vendorDir . '/icewind/smb/src/StringBuffer.php',
'Icewind\\SMB\\System' => $vendorDir . '/icewind/smb/src/System.php', 'Icewind\\SMB\\System' => $vendorDir . '/icewind/smb/src/System.php',
'Icewind\\SMB\\TimeZoneProvider' => $vendorDir . '/icewind/smb/src/TimeZoneProvider.php', 'Icewind\\SMB\\TimeZoneProvider' => $vendorDir . '/icewind/smb/src/TimeZoneProvider.php',
'Icewind\\SMB\\Wrapped\\Connection' => $vendorDir . '/icewind/smb/src/Wrapped/Connection.php', 'Icewind\\SMB\\Wrapped\\Connection' => $vendorDir . '/icewind/smb/src/Wrapped/Connection.php',
'Icewind\\Streams\\DirectoryFilter' => $vendorDir . '/icewind/streams/src/DirectoryFilter.php', 'Icewind\\Streams\\DirectoryFilter' => $vendorDir . '/icewind/streams/src/DirectoryFilter.php',
'Icewind\\Streams\\DirectoryWrapper' => $vendorDir . '/icewind/streams/src/DirectoryWrapper.php', 'Icewind\\Streams\\DirectoryWrapper' => $vendorDir . '/icewind/streams/src/DirectoryWrapper.php',
'Icewind\\Streams\\File' => $vendorDir . '/icewind/streams/src/File.php', 'Icewind\\Streams\\File' => $vendorDir . '/icewind/streams/src/File.php',
'Icewind\\Streams\\HashWrapper' => $vendorDir . '/icewind/streams/src/HashWrapper.php',
'Icewind\\Streams\\IteratorDirectory' => $vendorDir . '/icewind/streams/src/IteratorDirectory.php', 'Icewind\\Streams\\IteratorDirectory' => $vendorDir . '/icewind/streams/src/IteratorDirectory.php',
'Icewind\\Streams\\NullWrapper' => $vendorDir . '/icewind/streams/src/NullWrapper.php', 'Icewind\\Streams\\NullWrapper' => $vendorDir . '/icewind/streams/src/NullWrapper.php',
'Icewind\\Streams\\Path' => $vendorDir . '/icewind/streams/src/Path.php', 'Icewind\\Streams\\Path' => $vendorDir . '/icewind/streams/src/Path.php',
'Icewind\\Streams\\PathWrapper' => $vendorDir . '/icewind/streams/src/PathWrapper.php', 'Icewind\\Streams\\PathWrapper' => $vendorDir . '/icewind/streams/src/PathWrapper.php',
'Icewind\\Streams\\ReadHashWrapper' => $vendorDir . '/icewind/streams/src/ReadHashWrapper.php',
'Icewind\\Streams\\RetryWrapper' => $vendorDir . '/icewind/streams/src/RetryWrapper.php', 'Icewind\\Streams\\RetryWrapper' => $vendorDir . '/icewind/streams/src/RetryWrapper.php',
'Icewind\\Streams\\SeekableWrapper' => $vendorDir . '/icewind/streams/src/SeekableWrapper.php', 'Icewind\\Streams\\SeekableWrapper' => $vendorDir . '/icewind/streams/src/SeekableWrapper.php',
'Icewind\\Streams\\Url' => $vendorDir . '/icewind/streams/src/Url.php', 'Icewind\\Streams\\Url' => $vendorDir . '/icewind/streams/src/Url.php',
'Icewind\\Streams\\UrlCallback' => $vendorDir . '/icewind/streams/src/UrlCallBack.php',
'Icewind\\Streams\\UrlCallback' => $vendorDir . '/icewind/streams/src/UrlCallback.php',
'Icewind\\Streams\\Wrapper' => $vendorDir . '/icewind/streams/src/Wrapper.php', 'Icewind\\Streams\\Wrapper' => $vendorDir . '/icewind/streams/src/Wrapper.php',
'Icewind\\Streams\\WrapperHandler' => $vendorDir . '/icewind/streams/src/WrapperHandler.php',
'Icewind\\Streams\\WriteHashWrapper' => $vendorDir . '/icewind/streams/src/WriteHashWrapper.php',
); );

+ 0
- 1
apps/files_external/3rdparty/composer/autoload_psr4.php View File

$baseDir = $vendorDir; $baseDir = $vendorDir;


return array( return array(
'Icewind\\Streams\\Tests\\' => array($vendorDir . '/icewind/streams/tests'),
'Icewind\\Streams\\' => array($vendorDir . '/icewind/streams/src'), 'Icewind\\Streams\\' => array($vendorDir . '/icewind/streams/src'),
'Icewind\\SMB\\' => array($vendorDir . '/icewind/smb/src'), 'Icewind\\SMB\\' => array($vendorDir . '/icewind/smb/src'),
); );

+ 4
- 2
apps/files_external/3rdparty/composer/autoload_real.php View File

return self::$loader; return self::$loader;
} }


require __DIR__ . '/platform_check.php';

spl_autoload_register(array('ComposerAutoloaderInit98fe9b281934250b3a93f69a5ce843b3', 'loadClassLoader'), true, true); spl_autoload_register(array('ComposerAutoloaderInit98fe9b281934250b3a93f69a5ce843b3', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
spl_autoload_unregister(array('ComposerAutoloaderInit98fe9b281934250b3a93f69a5ce843b3', 'loadClassLoader')); spl_autoload_unregister(array('ComposerAutoloaderInit98fe9b281934250b3a93f69a5ce843b3', 'loadClassLoader'));


$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) { if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php';
require __DIR__ . '/autoload_static.php';


call_user_func(\Composer\Autoload\ComposerStaticInit98fe9b281934250b3a93f69a5ce843b3::getInitializer($loader)); call_user_func(\Composer\Autoload\ComposerStaticInit98fe9b281934250b3a93f69a5ce843b3::getInitializer($loader));
} else { } else {

+ 7
- 6
apps/files_external/3rdparty/composer/autoload_static.php View File

public static $prefixLengthsPsr4 = array ( public static $prefixLengthsPsr4 = array (
'I' => 'I' =>
array ( array (
'Icewind\\Streams\\Tests\\' => 22,
'Icewind\\Streams\\' => 16, 'Icewind\\Streams\\' => 16,
'Icewind\\SMB\\' => 12, 'Icewind\\SMB\\' => 12,
), ),
); );


public static $prefixDirsPsr4 = array ( public static $prefixDirsPsr4 = array (
'Icewind\\Streams\\Tests\\' =>
array (
0 => __DIR__ . '/..' . '/icewind/streams/tests',
),
'Icewind\\Streams\\' => 'Icewind\\Streams\\' =>
array ( array (
0 => __DIR__ . '/..' . '/icewind/streams/src', 0 => __DIR__ . '/..' . '/icewind/streams/src',
); );


public static $classMap = array ( public static $classMap = array (
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
'Icewind\\SMB\\ACL' => __DIR__ . '/..' . '/icewind/smb/src/ACL.php', 'Icewind\\SMB\\ACL' => __DIR__ . '/..' . '/icewind/smb/src/ACL.php',
'Icewind\\SMB\\AbstractServer' => __DIR__ . '/..' . '/icewind/smb/src/AbstractServer.php', 'Icewind\\SMB\\AbstractServer' => __DIR__ . '/..' . '/icewind/smb/src/AbstractServer.php',
'Icewind\\SMB\\AbstractShare' => __DIR__ . '/..' . '/icewind/smb/src/AbstractShare.php', 'Icewind\\SMB\\AbstractShare' => __DIR__ . '/..' . '/icewind/smb/src/AbstractShare.php',
'Icewind\\SMB\\Native\\NativeWriteStream' => __DIR__ . '/..' . '/icewind/smb/src/Native/NativeWriteStream.php', 'Icewind\\SMB\\Native\\NativeWriteStream' => __DIR__ . '/..' . '/icewind/smb/src/Native/NativeWriteStream.php',
'Icewind\\SMB\\Options' => __DIR__ . '/..' . '/icewind/smb/src/Options.php', 'Icewind\\SMB\\Options' => __DIR__ . '/..' . '/icewind/smb/src/Options.php',
'Icewind\\SMB\\ServerFactory' => __DIR__ . '/..' . '/icewind/smb/src/ServerFactory.php', 'Icewind\\SMB\\ServerFactory' => __DIR__ . '/..' . '/icewind/smb/src/ServerFactory.php',
'Icewind\\SMB\\StringBuffer' => __DIR__ . '/..' . '/icewind/smb/src/StringBuffer.php',
'Icewind\\SMB\\System' => __DIR__ . '/..' . '/icewind/smb/src/System.php', 'Icewind\\SMB\\System' => __DIR__ . '/..' . '/icewind/smb/src/System.php',
'Icewind\\SMB\\TimeZoneProvider' => __DIR__ . '/..' . '/icewind/smb/src/TimeZoneProvider.php', 'Icewind\\SMB\\TimeZoneProvider' => __DIR__ . '/..' . '/icewind/smb/src/TimeZoneProvider.php',
'Icewind\\SMB\\Wrapped\\Connection' => __DIR__ . '/..' . '/icewind/smb/src/Wrapped/Connection.php', 'Icewind\\SMB\\Wrapped\\Connection' => __DIR__ . '/..' . '/icewind/smb/src/Wrapped/Connection.php',
'Icewind\\Streams\\DirectoryFilter' => __DIR__ . '/..' . '/icewind/streams/src/DirectoryFilter.php', 'Icewind\\Streams\\DirectoryFilter' => __DIR__ . '/..' . '/icewind/streams/src/DirectoryFilter.php',
'Icewind\\Streams\\DirectoryWrapper' => __DIR__ . '/..' . '/icewind/streams/src/DirectoryWrapper.php', 'Icewind\\Streams\\DirectoryWrapper' => __DIR__ . '/..' . '/icewind/streams/src/DirectoryWrapper.php',
'Icewind\\Streams\\File' => __DIR__ . '/..' . '/icewind/streams/src/File.php', 'Icewind\\Streams\\File' => __DIR__ . '/..' . '/icewind/streams/src/File.php',
'Icewind\\Streams\\HashWrapper' => __DIR__ . '/..' . '/icewind/streams/src/HashWrapper.php',
'Icewind\\Streams\\IteratorDirectory' => __DIR__ . '/..' . '/icewind/streams/src/IteratorDirectory.php', 'Icewind\\Streams\\IteratorDirectory' => __DIR__ . '/..' . '/icewind/streams/src/IteratorDirectory.php',
'Icewind\\Streams\\NullWrapper' => __DIR__ . '/..' . '/icewind/streams/src/NullWrapper.php', 'Icewind\\Streams\\NullWrapper' => __DIR__ . '/..' . '/icewind/streams/src/NullWrapper.php',
'Icewind\\Streams\\Path' => __DIR__ . '/..' . '/icewind/streams/src/Path.php', 'Icewind\\Streams\\Path' => __DIR__ . '/..' . '/icewind/streams/src/Path.php',
'Icewind\\Streams\\PathWrapper' => __DIR__ . '/..' . '/icewind/streams/src/PathWrapper.php', 'Icewind\\Streams\\PathWrapper' => __DIR__ . '/..' . '/icewind/streams/src/PathWrapper.php',
'Icewind\\Streams\\ReadHashWrapper' => __DIR__ . '/..' . '/icewind/streams/src/ReadHashWrapper.php',
'Icewind\\Streams\\RetryWrapper' => __DIR__ . '/..' . '/icewind/streams/src/RetryWrapper.php', 'Icewind\\Streams\\RetryWrapper' => __DIR__ . '/..' . '/icewind/streams/src/RetryWrapper.php',
'Icewind\\Streams\\SeekableWrapper' => __DIR__ . '/..' . '/icewind/streams/src/SeekableWrapper.php', 'Icewind\\Streams\\SeekableWrapper' => __DIR__ . '/..' . '/icewind/streams/src/SeekableWrapper.php',
'Icewind\\Streams\\Url' => __DIR__ . '/..' . '/icewind/streams/src/Url.php', 'Icewind\\Streams\\Url' => __DIR__ . '/..' . '/icewind/streams/src/Url.php',
'Icewind\\Streams\\UrlCallback' => __DIR__ . '/..' . '/icewind/streams/src/UrlCallBack.php',
'Icewind\\Streams\\UrlCallback' => __DIR__ . '/..' . '/icewind/streams/src/UrlCallback.php',
'Icewind\\Streams\\Wrapper' => __DIR__ . '/..' . '/icewind/streams/src/Wrapper.php', 'Icewind\\Streams\\Wrapper' => __DIR__ . '/..' . '/icewind/streams/src/Wrapper.php',
'Icewind\\Streams\\WrapperHandler' => __DIR__ . '/..' . '/icewind/streams/src/WrapperHandler.php',
'Icewind\\Streams\\WriteHashWrapper' => __DIR__ . '/..' . '/icewind/streams/src/WriteHashWrapper.php',
); );


public static function getInitializer(ClassLoader $loader) public static function getInitializer(ClassLoader $loader)

+ 103
- 87
apps/files_external/3rdparty/composer/installed.json View File

[
{
"name": "icewind/smb",
"version": "v3.2.7",
"version_normalized": "3.2.7.0",
"source": {
"type": "git",
"url": "https://github.com/icewind1991/SMB.git",
"reference": "743a7bf35317f1b76cf8e8b804e54a6c5faacad6"
{
"packages": [
{
"name": "icewind/smb",
"version": "v3.4.0",
"version_normalized": "3.4.0.0",
"source": {
"type": "git",
"url": "https://github.com/icewind1991/SMB.git",
"reference": "b5c6921f2e91229c9f71556a4713b4fac91fd394"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/icewind1991/SMB/zipball/b5c6921f2e91229c9f71556a4713b4fac91fd394",
"reference": "b5c6921f2e91229c9f71556a4713b4fac91fd394",
"shasum": ""
},
"require": {
"icewind/streams": ">=0.7.3",
"php": ">=7.2"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.16",
"phpstan/phpstan": "^0.12.57",
"phpunit/phpunit": "^8.5|^9.3.8",
"psalm/phar": "^4.3"
},
"time": "2021-03-10T14:00:37+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Icewind\\SMB\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Robin Appelman",
"email": "icewind@owncloud.com"
}
],
"description": "php wrapper for smbclient and libsmbclient-php",
"support": {
"issues": "https://github.com/icewind1991/SMB/issues",
"source": "https://github.com/icewind1991/SMB/tree/v3.4.0"
},
"install-path": "../icewind/smb"
}, },
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/icewind1991/SMB/zipball/743a7bf35317f1b76cf8e8b804e54a6c5faacad6",
"reference": "743a7bf35317f1b76cf8e8b804e54a6c5faacad6",
"shasum": ""
},
"require": {
"icewind/streams": ">=0.2.0",
"php": ">=7.1"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.13",
"phpunit/phpunit": "^7.0"
},
"time": "2020-09-03T13:00:22+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Icewind\\SMB\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Robin Appelman",
"email": "icewind@owncloud.com"
}
],
"description": "php wrapper for smbclient and libsmbclient-php"
},
{
"name": "icewind/streams",
"version": "v0.7.1",
"version_normalized": "0.7.1.0",
"source": {
"type": "git",
"url": "https://github.com/icewind1991/Streams.git",
"reference": "4db3ed6c366e90b958d00e1d4c6360a9b39b2121"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/icewind1991/Streams/zipball/4db3ed6c366e90b958d00e1d4c6360a9b39b2121",
"reference": "4db3ed6c366e90b958d00e1d4c6360a9b39b2121",
"shasum": ""
},
"require": {
"php": ">=5.3"
},
"require-dev": {
"phpunit/phpunit": "^4.8",
"satooshi/php-coveralls": "v1.0.0"
},
"time": "2019-02-15T12:57:29+00:00",
"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/streams",
"version": "v0.7.3",
"version_normalized": "0.7.3.0",
"source": {
"type": "git",
"url": "https://github.com/icewind1991/Streams.git",
"reference": "22ef9fc5b50d645dbc202206a656cc4dde28f95c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/icewind1991/Streams/zipball/22ef9fc5b50d645dbc202206a656cc4dde28f95c",
"reference": "22ef9fc5b50d645dbc202206a656cc4dde28f95c",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2",
"phpstan/phpstan": "^0.12",
"phpunit/phpunit": "^9"
},
"time": "2021-03-02T19:33:35+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"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",
"support": {
"issues": "https://github.com/icewind1991/Streams/issues",
"source": "https://github.com/icewind1991/Streams/tree/v0.7.3"
},
"install-path": "../icewind/streams"
}
],
"dev": true,
"dev-package-names": []
}

+ 42
- 0
apps/files_external/3rdparty/composer/installed.php View File

<?php return array (
'root' =>
array (
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'aliases' =>
array (
),
'reference' => '62929cc646134fbd409cfb4eacb7039d15763b96',
'name' => 'files_external/3rdparty',
),
'versions' =>
array (
'files_external/3rdparty' =>
array (
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'aliases' =>
array (
),
'reference' => '62929cc646134fbd409cfb4eacb7039d15763b96',
),
'icewind/smb' =>
array (
'pretty_version' => 'v3.4.0',
'version' => '3.4.0.0',
'aliases' =>
array (
),
'reference' => 'b5c6921f2e91229c9f71556a4713b4fac91fd394',
),
'icewind/streams' =>
array (
'pretty_version' => 'v0.7.3',
'version' => '0.7.3.0',
'aliases' =>
array (
),
'reference' => '22ef9fc5b50d645dbc202206a656cc4dde28f95c',
),
),
);

+ 26
- 0
apps/files_external/3rdparty/composer/platform_check.php View File

<?php

// platform_check.php @generated by Composer

$issues = array();

if (!(PHP_VERSION_ID >= 70200)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.0". You are running ' . PHP_VERSION . '.';
}

if ($issues) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
} elseif (!headers_sent()) {
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
}
}
trigger_error(
'Composer detected issues in your platform: ' . implode(' ', $issues),
E_USER_ERROR
);
}

+ 1
- 0
apps/files_external/3rdparty/icewind/smb/.gitignore View File

.php_cs.cache .php_cs.cache
listen.php listen.php
test.php test.php
*.cache

+ 15
- 5
apps/files_external/3rdparty/icewind/smb/README.md View File

SMB SMB
=== ===


[![Code Coverage](https://scrutinizer-ci.com/g/icewind1991/SMB/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/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)
[![CI](https://github.com/icewind1991/SMB/actions/workflows/ci.yaml/badge.svg)](https://github.com/icewind1991/SMB/actions/workflows/ci.yaml)
[![codecov](https://codecov.io/gh/icewind1991/SMB/branch/master/graph/badge.svg?token=eTg0P466k6)](https://codecov.io/gh/icewind1991/SMB)


PHP wrapper for `smbclient` and [`libsmbclient-php`](https://github.com/eduardok/libsmbclient-php) PHP wrapper for `smbclient` and [`libsmbclient-php`](https://github.com/eduardok/libsmbclient-php)


``` ```


**Note**: write() will truncate your file to 0bytes. You may open a writeable stream with append() which will point **Note**: write() will truncate your file to 0bytes. You may open a writeable stream with append() which will point
the cursor to the end of the file or create it if it does not exists yet. (append() is only compatible with libsmbclient-php)
the cursor to the end of the file or create it if it does not exist yet. (append() is only compatible with libsmbclient-php)
```php ```php
$fh = $share->append('test.txt'); $fh = $share->append('test.txt');
fwrite($fh, 'bar'); fwrite($fh, 'bar');
$serverFactory = new ServerFactory($options); $serverFactory = new ServerFactory($options);
``` ```


### Setting protocol version

```php
$options = new Options();
$options->setMinProtocol(IOptions::PROTOCOL_SMB2);
$options->setMaxProtocol(IOptions::PROTOCOL_SMB3);
$serverFactory = new ServerFactory($options);
```

Note, setting the protocol version is not supported with php-smbclient version 1.0.1 or lower.

### Customizing system integration ### Customizing system integration


The `smbclient` backend needs to get various information about the system it's running on to function The `smbclient` backend needs to get various information about the system it's running on to function
such as the paths of various binaries or the system timezone. such as the paths of various binaries or the system timezone.
While the default logic for getting this information should work on most systems, it possible to customize this behaviour.
While the default logic for getting this information should work on most systems, it is possible to customize this behaviour.


In order to customize the integration you provide a custom implementation of `ITimezoneProvider` and/or `ISystem` and pass them as arguments to the `ServerFactory`. In order to customize the integration you provide a custom implementation of `ITimezoneProvider` and/or `ISystem` and pass them as arguments to the `ServerFactory`.



+ 35
- 27
apps/files_external/3rdparty/icewind/smb/composer.json View File

{ {
"name" : "icewind/smb",
"description" : "php wrapper for smbclient and libsmbclient-php",
"license" : "MIT",
"authors" : [
{
"name" : "Robin Appelman",
"email": "icewind@owncloud.com"
}
],
"require" : {
"php": ">=7.1",
"icewind/streams": ">=0.2.0"
},
"require-dev": {
"phpunit/phpunit": "^7.0",
"friendsofphp/php-cs-fixer": "^2.13"
},
"autoload" : {
"psr-4": {
"Icewind\\SMB\\": "src/"
}
},
"autoload-dev" : {
"psr-4": {
"Icewind\\SMB\\Test\\": "tests/"
}
}
"name": "icewind/smb",
"description": "php wrapper for smbclient and libsmbclient-php",
"license": "MIT",
"authors": [
{
"name": "Robin Appelman",
"email": "icewind@owncloud.com"
}
],
"require": {
"php": ">=7.2",
"icewind/streams": ">=0.7.3"
},
"require-dev": {
"phpunit/phpunit": "^8.5|^9.3.8",
"friendsofphp/php-cs-fixer": "^2.16",
"phpstan/phpstan": "^0.12.57",
"psalm/phar": "^4.3"
},
"autoload": {
"psr-4": {
"Icewind\\SMB\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Icewind\\SMB\\Test\\": "tests/"
}
},
"scripts": {
"lint": "parallel-lint --exclude src --exclude vendor --exclude target --exclude build .",
"cs:check": "php-cs-fixer fix --dry-run --diff",
"cs:fix": "php-cs-fixer fix",
"psalm": "psalm.phar"
}
} }

+ 3
- 0
apps/files_external/3rdparty/icewind/smb/src/ACL.php View File

const FLAG_OBJECT_INHERIT = 0x1; const FLAG_OBJECT_INHERIT = 0x1;
const FLAG_CONTAINER_INHERIT = 0x2; const FLAG_CONTAINER_INHERIT = 0x2;


/** @var int */
private $type; private $type;
/** @var int */
private $flags; private $flags;
/** @var int */
private $mask; private $mask;


public function __construct(int $type, int $flags, int $mask) { public function __construct(int $type, int $flags, int $mask) {

+ 11
- 19
apps/files_external/3rdparty/icewind/smb/src/AbstractServer.php View File

abstract class AbstractServer implements IServer { abstract class AbstractServer implements IServer {
const LOCALE = 'en_US.UTF-8'; const LOCALE = 'en_US.UTF-8';


/**
* @var string $host
*/
/** @var string */
protected $host; protected $host;


/**
* @var IAuth $user
*/
/** @var IAuth */
protected $auth; protected $auth;


/**
* @var ISystem
*/
/** @var ISystem */
protected $system; protected $system;


/**
* @var TimeZoneProvider
*/
/** @var ITimeZoneProvider */
protected $timezoneProvider; protected $timezoneProvider;


/** @var IOptions */ /** @var IOptions */
* @param string $host * @param string $host
* @param IAuth $auth * @param IAuth $auth
* @param ISystem $system * @param ISystem $system
* @param TimeZoneProvider $timeZoneProvider
* @param ITimeZoneProvider $timeZoneProvider
* @param IOptions $options * @param IOptions $options
*/ */
public function __construct($host, IAuth $auth, ISystem $system, TimeZoneProvider $timeZoneProvider, IOptions $options) {
public function __construct(string $host, IAuth $auth, ISystem $system, ITimeZoneProvider $timeZoneProvider, IOptions $options) {
$this->host = $host; $this->host = $host;
$this->auth = $auth; $this->auth = $auth;
$this->system = $system; $this->system = $system;
$this->options = $options; $this->options = $options;
} }


public function getAuth() {
public function getAuth(): IAuth {
return $this->auth; return $this->auth;
} }


public function getHost() {
public function getHost(): string {
return $this->host; return $this->host;
} }


public function getTimeZone() {
public function getTimeZone(): string {
return $this->timezoneProvider->get($this->host); return $this->timezoneProvider->get($this->host);
} }


public function getSystem() {
public function getSystem(): ISystem {
return $this->system; return $this->system;
} }


public function getOptions() {
public function getOptions(): IOptions {
return $this->options; return $this->options;
} }
} }

+ 10
- 2
apps/files_external/3rdparty/icewind/smb/src/AbstractShare.php View File

use Icewind\SMB\Exception\InvalidPathException; use Icewind\SMB\Exception\InvalidPathException;


abstract class AbstractShare implements IShare { abstract class AbstractShare implements IShare {
/** @var string[] */
private $forbiddenCharacters; private $forbiddenCharacters;


public function __construct() { public function __construct() {
$this->forbiddenCharacters = ['?', '<', '>', ':', '*', '|', '"', chr(0), "\n", "\r"]; $this->forbiddenCharacters = ['?', '<', '>', ':', '*', '|', '"', chr(0), "\n", "\r"];
} }


protected function verifyPath($path) {
/**
* @param string $path
* @throws InvalidPathException
*/
protected function verifyPath(string $path): void {
foreach ($this->forbiddenCharacters as $char) { foreach ($this->forbiddenCharacters as $char) {
if (strpos($path, $char) !== false) { if (strpos($path, $char) !== false) {
throw new InvalidPathException('Invalid path, "' . $char . '" is not allowed'); throw new InvalidPathException('Invalid path, "' . $char . '" is not allowed');
} }
} }


public function setForbiddenChars(array $charList) {
/**
* @param string[] $charList
*/
public function setForbiddenChars(array $charList): void {
$this->forbiddenCharacters = $charList; $this->forbiddenCharacters = $charList;
} }
} }

+ 5
- 5
apps/files_external/3rdparty/icewind/smb/src/AnonymousAuth.php View File

namespace Icewind\SMB; namespace Icewind\SMB;


class AnonymousAuth implements IAuth { class AnonymousAuth implements IAuth {
public function getUsername() {
public function getUsername(): ?string {
return null; return null;
} }


public function getWorkgroup() {
public function getWorkgroup(): ?string {
return 'dummy'; return 'dummy';
} }


public function getPassword() {
public function getPassword(): ?string {
return null; return null;
} }


public function getExtraCommandLineArguments() {
public function getExtraCommandLineArguments(): string {
return '-N'; return '-N';
} }


public function setExtraSmbClientOptions($smbClientState) {
public function setExtraSmbClientOptions($smbClientState): void {
smbclient_option_set($smbClientState, SMBCLIENT_OPT_AUTO_ANONYMOUS_LOGIN, true); smbclient_option_set($smbClientState, SMBCLIENT_OPT_AUTO_ANONYMOUS_LOGIN, true);
} }
} }

+ 7
- 14
apps/files_external/3rdparty/icewind/smb/src/BasicAuth.php View File

class BasicAuth implements IAuth { class BasicAuth implements IAuth {
/** @var string */ /** @var string */
private $username; private $username;
/** @var string */
/** @var string|null */
private $workgroup; private $workgroup;
/** @var string */ /** @var string */
private $password; private $password;


/**
* BasicAuth constructor.
*
* @param string $username
* @param string $workgroup
* @param string $password
*/
public function __construct($username, $workgroup, $password) {
public function __construct(string $username, ?string $workgroup, string $password) {
$this->username = $username; $this->username = $username;
$this->workgroup = $workgroup; $this->workgroup = $workgroup;
$this->password = $password; $this->password = $password;
} }


public function getUsername() {
public function getUsername(): ?string {
return $this->username; return $this->username;
} }


public function getWorkgroup() {
public function getWorkgroup(): ?string {
return $this->workgroup; return $this->workgroup;
} }


public function getPassword() {
public function getPassword(): ?string {
return $this->password; return $this->password;
} }


public function getExtraCommandLineArguments() {
public function getExtraCommandLineArguments(): string {
return ($this->workgroup) ? '-W ' . escapeshellarg($this->workgroup) : ''; return ($this->workgroup) ? '-W ' . escapeshellarg($this->workgroup) : '';
} }


public function setExtraSmbClientOptions($smbClientState) {
public function setExtraSmbClientOptions($smbClientState): void {
// noop // noop
} }
} }

+ 5
- 16
apps/files_external/3rdparty/icewind/smb/src/Change.php View File

namespace Icewind\SMB; namespace Icewind\SMB;


class Change { class Change {
/** @var int */
private $code; private $code;
/** @var string */
private $path; private $path;


/**
* Change constructor.
*
* @param $code
* @param $path
*/
public function __construct($code, $path) {
public function __construct(int $code, string $path) {
$this->code = $code; $this->code = $code;
$this->path = $path; $this->path = $path;
} }


/**
* @return integer
*/
public function getCode() {
public function getCode(): int {
return $this->code; return $this->code;
} }


/**
* @return string
*/
public function getPath() {
public function getPath(): string {
return $this->path; return $this->path;
} }
} }

+ 21
- 7
apps/files_external/3rdparty/icewind/smb/src/Exception/Exception.php View File



namespace Icewind\SMB\Exception; namespace Icewind\SMB\Exception;


use Throwable;

/**
* @psalm-consistent-constructor
*/
class Exception extends \Exception { class Exception extends \Exception {
public static function unknown($path, $error) {
$message = 'Unknown error (' . $error . ')';
public function __construct(string $message = "", int $code = 0, Throwable $previous = null) {
parent::__construct($message, $code, $previous);
}

/**
* @param string|null $path
* @param string|int|null $error
* @return Exception
*/
public static function unknown(?string $path, $error): Exception {
$message = 'Unknown error (' . (string)$error . ')';
if ($path) { if ($path) {
$message .= ' for ' . $path; $message .= ' for ' . $path;
} }


return new Exception($message, is_string($error) ? 0 : $error);
return new Exception($message, is_int($error) ? $error : 0);
} }


/** /**
* @param array $exceptionMap
* @param mixed $error
* @param string $path
* @param array<int|string, class-string<Exception>> $exceptionMap
* @param string|int|null $error
* @param string|null $path
* @return Exception * @return Exception
*/ */
public static function fromMap(array $exceptionMap, $error, $path) {
public static function fromMap(array $exceptionMap, $error, ?string $path): Exception {
if (isset($exceptionMap[$error])) { if (isset($exceptionMap[$error])) {
$exceptionClass = $exceptionMap[$error]; $exceptionClass = $exceptionMap[$error];
if (is_numeric($error)) { if (is_numeric($error)) {

+ 2
- 6
apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidRequestException.php View File

*/ */
protected $path; protected $path;


/**
* @param string $path
* @param int $code
*/
public function __construct($path, $code = 0) {
public function __construct(string $path = "", int $code = 0, \Throwable $previous = null) {
$class = get_class($this); $class = get_class($this);
$parts = explode('\\', $class); $parts = explode('\\', $class);
$baseName = array_pop($parts); $baseName = array_pop($parts);
parent::__construct('Invalid request for ' . $path . ' (' . $baseName . ')', $code);
parent::__construct('Invalid request for ' . $path . ' (' . $baseName . ')', $code, $previous);
$this->path = $path; $this->path = $path;
} }



+ 1
- 1
apps/files_external/3rdparty/icewind/smb/src/Exception/RevisionMismatchException.php View File

use Throwable; use Throwable;


class RevisionMismatchException extends Exception { class RevisionMismatchException extends Exception {
public function __construct($message = 'Protocol version mismatch', $code = 0, Throwable $previous = null) {
public function __construct(string $message = 'Protocol version mismatch', int $code = 0, Throwable $previous = null) {
parent::__construct($message, $code, $previous); parent::__construct($message, $code, $previous);
} }
} }

+ 5
- 14
apps/files_external/3rdparty/icewind/smb/src/IAuth.php View File

namespace Icewind\SMB; namespace Icewind\SMB;


interface IAuth { interface IAuth {
/**
* @return string|null
*/
public function getUsername();
public function getUsername(): ?string;


/**
* @return string|null
*/
public function getWorkgroup();
public function getWorkgroup(): ?string;


/**
* @return string|null
*/
public function getPassword();
public function getPassword(): ?string;


/** /**
* Any extra command line option for smbclient that are required * Any extra command line option for smbclient that are required
* *
* @return string * @return string
*/ */
public function getExtraCommandLineArguments();
public function getExtraCommandLineArguments(): string;


/** /**
* Set any extra options for libsmbclient that are required * Set any extra options for libsmbclient that are required
* *
* @param resource $smbClientState * @param resource $smbClientState
*/ */
public function setExtraSmbClientOptions($smbClientState);
public function setExtraSmbClientOptions($smbClientState): void;
} }

+ 9
- 36
apps/files_external/3rdparty/icewind/smb/src/IFileInfo.php View File

const MODE_ARCHIVE = 0x20; const MODE_ARCHIVE = 0x20;
const MODE_NORMAL = 0x80; const MODE_NORMAL = 0x80;


/**
* @return string
*/
public function getPath();
public function getPath(): string;


/**
* @return string
*/
public function getName();
public function getName(): string;


/**
* @return int
*/
public function getSize();
public function getSize(): int;


/**
* @return int
*/
public function getMTime();
public function getMTime(): int;


/**
* @return bool
*/
public function isDirectory();
public function isDirectory(): bool;


/**
* @return bool
*/
public function isReadOnly();
public function isReadOnly(): bool;


/**
* @return bool
*/
public function isHidden();
public function isHidden(): bool;


/**
* @return bool
*/
public function isSystem();
public function isSystem(): bool;


/**
* @return bool
*/
public function isArchived();
public function isArchived(): bool;


/** /**
* @return ACL[] * @return ACL[]

+ 4
- 4
apps/files_external/3rdparty/icewind/smb/src/INotifyHandler.php View File

* *
* @return Change[] * @return Change[]
*/ */
public function getChanges();
public function getChanges(): array;


/** /**
* Listen actively to all incoming changes * Listen actively to all incoming changes
* *
* Note that this is a blocking process and will cause the process to block forever if not explicitly terminated * Note that this is a blocking process and will cause the process to block forever if not explicitly terminated
* *
* @param callable $callback
* @param callable(Change):?bool $callback
*/ */
public function listen($callback);
public function listen(callable $callback): void;


/** /**
* Stop listening for changes * Stop listening for changes
* *
* Note that any pending changes will be discarded * Note that any pending changes will be discarded
*/ */
public function stop();
public function stop(): void;
} }

+ 16
- 4
apps/files_external/3rdparty/icewind/smb/src/IOptions.php View File

namespace Icewind\SMB; namespace Icewind\SMB;


interface IOptions { interface IOptions {
/**
* @return int
*/
public function getTimeout();
const PROTOCOL_NT1 = 'NT1';
const PROTOCOL_SMB2 = 'SMB2';
const PROTOCOL_SMB2_02 = 'SMB2_02';
const PROTOCOL_SMB2_22 = 'SMB2_22';
const PROTOCOL_SMB2_24 = 'SMB2_24';
const PROTOCOL_SMB3 = 'SMB3';
const PROTOCOL_SMB3_00 = 'SMB3_00';
const PROTOCOL_SMB3_02 = 'SMB3_02';
const PROTOCOL_SMB3_10 = 'SMB3_10';
const PROTOCOL_SMB3_11 = 'SMB3_11';

public function getTimeout(): int;

public function getMinProtocol(): ?string;

public function getMaxProtocol(): ?string;
} }

+ 8
- 31
apps/files_external/3rdparty/icewind/smb/src/IServer.php View File

namespace Icewind\SMB; namespace Icewind\SMB;


interface IServer { interface IServer {
/**
* @return IAuth
*/
public function getAuth();
public function getAuth(): IAuth;


/**
* @return string
*/
public function getHost();
public function getHost(): string;


/** /**
* @return \Icewind\SMB\IShare[] * @return \Icewind\SMB\IShare[]
* @throws \Icewind\SMB\Exception\AuthenticationException * @throws \Icewind\SMB\Exception\AuthenticationException
* @throws \Icewind\SMB\Exception\InvalidHostException * @throws \Icewind\SMB\Exception\InvalidHostException
*/ */
public function listShares();
public function listShares(): array;


/**
* @param string $name
* @return \Icewind\SMB\IShare
*/
public function getShare($name);
public function getShare(string $name): IShare;


/**
* @return string
*/
public function getTimeZone();
public function getTimeZone(): string;


/**
* @return ISystem
*/
public function getSystem();
public function getSystem(): ISystem;


/**
* @return IOptions
*/
public function getOptions();
public function getOptions(): IOptions;


/**
* @param ISystem $system
* @return bool
*/
public static function available(ISystem $system);
public static function available(ISystem $system): bool;
} }

+ 44
- 39
apps/files_external/3rdparty/icewind/smb/src/IShare.php View File



namespace Icewind\SMB; namespace Icewind\SMB;


use Icewind\SMB\Exception\AlreadyExistsException;
use Icewind\SMB\Exception\InvalidRequestException;
use Icewind\SMB\Exception\InvalidTypeException;
use Icewind\SMB\Exception\NotFoundException;

interface IShare { interface IShare {
/** /**
* Get the name of the share * Get the name of the share
* *
* @return string * @return string
*/ */
public function getName();
public function getName(): string;


/** /**
* Download a remote file * Download a remote file
* @param string $target local file * @param string $target local file
* @return bool * @return bool
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\InvalidTypeException
* @throws NotFoundException
* @throws InvalidTypeException
*/ */
public function get($source, $target);
public function get(string $source, string $target): bool;


/** /**
* Upload a local file * Upload a local file
* @param string $target remove file * @param string $target remove file
* @return bool * @return bool
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\InvalidTypeException
* @throws NotFoundException
* @throws InvalidTypeException
*/ */
public function put($source, $target);
public function put(string $source, string $target): bool;


/** /**
* Open a readable stream top a remote file * Open a readable stream top a remote file
* @param string $source * @param string $source
* @return resource a read only stream with the contents of the remote file * @return resource a read only stream with the contents of the remote file
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\InvalidTypeException
* @throws NotFoundException
* @throws InvalidTypeException
*/ */
public function read($source);
public function read(string $source);


/** /**
* Open a writable stream to a remote file * Open a writable stream to a remote file
* @param string $target * @param string $target
* @return resource a write only stream to upload a remote file * @return resource a write only stream to upload a remote file
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\InvalidTypeException
* @throws NotFoundException
* @throws InvalidTypeException
*/ */
public function write($target);
public function write(string $target);


/** /**
* Open a writable stream to a remote file and set the cursor to the end of the file * Open a writable stream to a remote file and set the cursor to the end of the file
* @param string $target * @param string $target
* @return resource a write only stream to upload a remote file * @return resource a write only stream to upload a remote file
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\InvalidTypeException
* @throws \Icewind\SMB\Exception\InvalidRequestException
* @throws NotFoundException
* @throws InvalidTypeException
* @throws InvalidRequestException
*/ */
public function append($target);
public function append(string $target);


/** /**
* Rename a remote file * Rename a remote file
* @param string $to * @param string $to
* @return bool * @return bool
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\AlreadyExistsException
* @throws NotFoundException
* @throws AlreadyExistsException
*/ */
public function rename($from, $to);
public function rename(string $from, string $to): bool;


/** /**
* Delete a file on the share * Delete a file on the share
* @param string $path * @param string $path
* @return bool * @return bool
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\InvalidTypeException
* @throws NotFoundException
* @throws InvalidTypeException
*/ */
public function del($path);
public function del(string $path): bool;


/** /**
* List the content of a remote folder * List the content of a remote folder
* *
* @param $path
* @return \Icewind\SMB\IFileInfo[]
* @param string $path
* @return IFileInfo[]
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\InvalidTypeException
* @throws NotFoundException
* @throws InvalidTypeException
*/ */
public function dir($path);
public function dir(string $path): array;


/** /**
* @param string $path * @param string $path
* @return \Icewind\SMB\IFileInfo
* @return IFileInfo
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws NotFoundException
*/ */
public function stat($path);
public function stat(string $path): IFileInfo;


/** /**
* Create a folder on the share * Create a folder on the share
* @param string $path * @param string $path
* @return bool * @return bool
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\AlreadyExistsException
* @throws NotFoundException
* @throws AlreadyExistsException
*/ */
public function mkdir($path);
public function mkdir(string $path): bool;


/** /**
* Remove a folder on the share * Remove a folder on the share
* @param string $path * @param string $path
* @return bool * @return bool
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\InvalidTypeException
* @throws NotFoundException
* @throws InvalidTypeException
*/ */
public function rmdir($path);
public function rmdir(string $path): bool;


/** /**
* @param string $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 * @param int $mode a combination of FileInfo::MODE_READONLY, FileInfo::MODE_ARCHIVE, FileInfo::MODE_SYSTEM and FileInfo::MODE_HIDDEN, FileInfo::NORMAL
* @return mixed * @return mixed
*/ */
public function setMode($path, $mode);
public function setMode(string $path, int $mode);


/** /**
* @param string $path * @param string $path
* @return INotifyHandler * @return INotifyHandler
*/ */
public function notify($path);
public function notify(string $path);


/** /**
* Get the IServer instance for this share * Get the IServer instance for this share

+ 17
- 17
apps/files_external/3rdparty/icewind/smb/src/ISystem.php View File

* @param int $num the file descriptor id * @param int $num the file descriptor id
* @return string * @return string
*/ */
public function getFD($num);
public function getFD(int $num): string;


/** /**
* Get the full path to the `smbclient` binary of false if the binary is not available
* Get the full path to the `smbclient` binary of null if the binary is not available
* *
* @return string|bool
* @return string|null
*/ */
public function getSmbclientPath();
public function getSmbclientPath(): ?string;


/** /**
* Get the full path to the `net` binary of false if the binary is not available
* Get the full path to the `net` binary of null if the binary is not available
* *
* @return string|bool
* @return string|null
*/ */
public function getNetPath();
public function getNetPath(): ?string;


/** /**
* Get the full path to the `smbcacls` binary of false if the binary is not available
* Get the full path to the `smbcacls` binary of null if the binary is not available
* *
* @return string|bool
* @return string|null
*/ */
public function getSmbcAclsPath();
public function getSmbcAclsPath(): ?string;


/** /**
* Get the full path to the `stdbuf` binary of false if the binary is not available
* Get the full path to the `stdbuf` binary of null if the binary is not available
* *
* @return string|bool
* @return string|null
*/ */
public function getStdBufPath();
public function getStdBufPath(): ?string;


/** /**
* Get the full path to the `date` binary of false if the binary is not available
* Get the full path to the `date` binary of null if the binary is not available
* *
* @return string|bool
* @return string|null
*/ */
public function getDatePath();
public function getDatePath(): ?string;


/** /**
* Whether or not the smbclient php extension is enabled * Whether or not the smbclient php extension is enabled
* *
* @return bool * @return bool
*/ */
public function libSmbclientAvailable();
public function libSmbclientAvailable(): bool;
} }

+ 1
- 1
apps/files_external/3rdparty/icewind/smb/src/ITimeZoneProvider.php View File

* @param string $host * @param string $host
* @return string * @return string
*/ */
public function get($host);
public function get(string $host): string;
} }

+ 5
- 5
apps/files_external/3rdparty/icewind/smb/src/KerberosAuth.php View File

* Use existing kerberos ticket to authenticate * Use existing kerberos ticket to authenticate
*/ */
class KerberosAuth implements IAuth { class KerberosAuth implements IAuth {
public function getUsername() {
public function getUsername(): ?string {
return 'dummy'; return 'dummy';
} }


public function getWorkgroup() {
public function getWorkgroup(): ?string {
return 'dummy'; return 'dummy';
} }


public function getPassword() {
public function getPassword(): ?string {
return null; return null;
} }


public function getExtraCommandLineArguments() {
public function getExtraCommandLineArguments(): string {
return '-k'; return '-k';
} }


public function setExtraSmbClientOptions($smbClientState) {
public function setExtraSmbClientOptions($smbClientState): void {
smbclient_option_set($smbClientState, SMBCLIENT_OPT_USE_KERBEROS, true); smbclient_option_set($smbClientState, SMBCLIENT_OPT_USE_KERBEROS, true);
smbclient_option_set($smbClientState, SMBCLIENT_OPT_FALLBACK_AFTER_KERBEROS, false); smbclient_option_set($smbClientState, SMBCLIENT_OPT_FALLBACK_AFTER_KERBEROS, false);
} }

+ 35
- 69
apps/files_external/3rdparty/icewind/smb/src/Native/NativeFileInfo.php View File

namespace Icewind\SMB\Native; namespace Icewind\SMB\Native;


use Icewind\SMB\ACL; use Icewind\SMB\ACL;
use Icewind\SMB\Exception\Exception;
use Icewind\SMB\IFileInfo; use Icewind\SMB\IFileInfo;


class NativeFileInfo implements IFileInfo { class NativeFileInfo implements IFileInfo {
/**
* @var string
*/
/** @var string */
protected $path; protected $path;

/**
* @var string
*/
/** @var string */
protected $name; protected $name;

/**
* @var NativeShare
*/
/** @var NativeShare */
protected $share; protected $share;

/**
* @var array|null
*/
/** @var array{"mode": int, "size": int, "write_time": int}|null */
protected $attributeCache = null; protected $attributeCache = null;


/**
* @param NativeShare $share
* @param string $path
* @param string $name
*/
public function __construct($share, $path, $name) {
public function __construct(NativeShare $share, string $path, string $name) {
$this->share = $share; $this->share = $share;
$this->path = $path; $this->path = $path;
$this->name = $name; $this->name = $name;
} }


/**
* @return string
*/
public function getPath() {
public function getPath(): string {
return $this->path; return $this->path;
} }


/**
* @return string
*/
public function getName() {
public function getName(): string {
return $this->name; return $this->name;
} }


/** /**
* @return array
* @return array{"mode": int, "size": int, "write_time": int}
*/ */
protected function stat() {
protected function stat(): array {
if (is_null($this->attributeCache)) { if (is_null($this->attributeCache)) {
$rawAttributes = explode(',', $this->share->getAttribute($this->path, 'system.dos_attr.*')); $rawAttributes = explode(',', $this->share->getAttribute($this->path, 'system.dos_attr.*'));
$this->attributeCache = [];
$attributes = [];
foreach ($rawAttributes as $rawAttribute) { foreach ($rawAttributes as $rawAttribute) {
list($name, $value) = explode(':', $rawAttribute); list($name, $value) = explode(':', $rawAttribute);
$name = strtolower($name); $name = strtolower($name);
if ($name == 'mode') { if ($name == 'mode') {
$this->attributeCache[$name] = (int)hexdec(substr($value, 2));
$attributes[$name] = (int)hexdec(substr($value, 2));
} else { } else {
$this->attributeCache[$name] = (int)$value;
$attributes[$name] = (int)$value;
} }
} }
if (!isset($attributes['mode'])) {
throw new Exception("Invalid attribute response");
}
if (!isset($attributes['size'])) {
throw new Exception("Invalid attribute response");
}
if (!isset($attributes['write_time'])) {
throw new Exception("Invalid attribute response");
}
$this->attributeCache = $attributes;
} }
return $this->attributeCache; return $this->attributeCache;
} }


/**
* @return int
*/
public function getSize() {
public function getSize(): int {
$stat = $this->stat(); $stat = $this->stat();
return $stat['size']; return $stat['size'];
} }


/**
* @return int
*/
public function getMTime() {
public function getMTime(): int {
$stat = $this->stat(); $stat = $this->stat();
return $stat['change_time'];
return $stat['write_time'];
} }


/** /**
* as false (except for `hidden` where we use the unix dotfile convention) * as false (except for `hidden` where we use the unix dotfile convention)
*/ */


/**
* @return int
*/
protected function getMode() {
protected function getMode(): int {
$mode = $this->stat()['mode']; $mode = $this->stat()['mode'];


// Let us ignore the ATTR_NOT_CONTENT_INDEXED for now // Let us ignore the ATTR_NOT_CONTENT_INDEXED for now
$mode &= ~0x00002000; $mode &= ~0x00002000;
return $mode; return $mode;
} }


/**
* @return bool
*/
public function isDirectory() {
public function isDirectory(): bool {
$mode = $this->getMode(); $mode = $this->getMode();
if ($mode > 0x1000) { if ($mode > 0x1000) {
return (bool)($mode & 0x4000); // 0x4000: unix directory flag return (bool)($mode & 0x4000); // 0x4000: unix directory flag
} }
} }


/**
* @return bool
*/
public function isReadOnly() {
public function isReadOnly(): bool {
$mode = $this->getMode(); $mode = $this->getMode();
if ($mode > 0x1000) { if ($mode > 0x1000) {
return !(bool)($mode & 0x80); // 0x80: owner write permissions return !(bool)($mode & 0x80); // 0x80: owner write permissions
} }
} }


/**
* @return bool
*/
public function isHidden() {
public function isHidden(): bool {
$mode = $this->getMode(); $mode = $this->getMode();
if ($mode > 0x1000) { if ($mode > 0x1000) {
return strlen($this->name) > 0 && $this->name[0] === '.'; return strlen($this->name) > 0 && $this->name[0] === '.';
} }
} }


/**
* @return bool
*/
public function isSystem() {
public function isSystem(): bool {
$mode = $this->getMode(); $mode = $this->getMode();
if ($mode > 0x1000) { if ($mode > 0x1000) {
return false; return false;
} }
} }


/**
* @return bool
*/
public function isArchived() {
public function isArchived(): bool {
$mode = $this->getMode(); $mode = $this->getMode();
if ($mode > 0x1000) { if ($mode > 0x1000) {
return false; return false;


foreach (explode(',', $attribute) as $acl) { foreach (explode(',', $attribute) as $acl) {
list($user, $permissions) = explode(':', $acl, 2); list($user, $permissions) = explode(':', $acl, 2);
$user = trim($user, '\\');
list($type, $flags, $mask) = explode('/', $permissions); list($type, $flags, $mask) = explode('/', $permissions);
$mask = hexdec($mask); $mask = hexdec($mask);


$acls[$user] = new ACL($type, $flags, $mask);
$acls[$user] = new ACL((int)$type, (int)$flags, (int)$mask);
} }


return $acls; return $acls;

+ 26
- 33
apps/files_external/3rdparty/icewind/smb/src/Native/NativeReadStream.php View File



namespace Icewind\SMB\Native; namespace Icewind\SMB\Native;


use Icewind\SMB\StringBuffer;

/** /**
* Stream optimized for read only usage * Stream optimized for read only usage
*/ */
class NativeReadStream extends NativeStream { class NativeReadStream extends NativeStream {
const CHUNK_SIZE = 1048576; // 1MB chunks const CHUNK_SIZE = 1048576; // 1MB chunks
/**
* @var resource
*/
private $readBuffer = null;


private $bufferSize = 0;
/** @var StringBuffer */
private $readBuffer;


public function __construct() {
$this->readBuffer = new StringBuffer();
}

/** @var int */
private $pos = 0; private $pos = 0;


public function stream_open($path, $mode, $options, &$opened_path) { public function stream_open($path, $mode, $options, &$opened_path) {
$this->readBuffer = fopen('php://memory', 'r+');

return parent::stream_open($path, $mode, $options, $opened_path); return parent::stream_open($path, $mode, $options, $opened_path);
} }


/** /**
* Wrap a stream from libsmbclient-php into a regular php stream * Wrap a stream from libsmbclient-php into a regular php stream
* *
* @param \Icewind\SMB\NativeState $state
* @param NativeState $state
* @param resource $smbStream * @param resource $smbStream
* @param string $mode * @param string $mode
* @param string $url * @param string $url
* @return resource * @return resource
*/ */
public static function wrap($state, $smbStream, $mode, $url) {
stream_wrapper_register('nativesmb', NativeReadStream::class);
$context = stream_context_create([
'nativesmb' => [
'state' => $state,
'handle' => $smbStream,
'url' => $url
]
]);
$fh = fopen('nativesmb://', $mode, false, $context);
stream_wrapper_unregister('nativesmb');
return $fh;
public static function wrap(NativeState $state, $smbStream, string $mode, string $url) {
return parent::wrapClass($state, $smbStream, $mode, $url, NativeReadStream::class);
} }


public function stream_read($count) { public function stream_read($count) {
// php reads 8192 bytes at once // php reads 8192 bytes at once
// however due to network latency etc, it's faster to read in larger chunks // however due to network latency etc, it's faster to read in larger chunks
// and buffer the result // and buffer the result
if (!parent::stream_eof() && $this->bufferSize < $count) {
$remaining = $this->readBuffer;
$this->readBuffer = fopen('php://memory', 'r+');
$this->bufferSize = 0;
stream_copy_to_stream($remaining, $this->readBuffer);
$this->bufferSize += fwrite($this->readBuffer, parent::stream_read(self::CHUNK_SIZE));
fseek($this->readBuffer, 0);
if (!parent::stream_eof() && $this->readBuffer->remaining() < $count) {
$chunk = parent::stream_read(self::CHUNK_SIZE);
if ($chunk === false) {
return false;
}
$this->readBuffer->push($chunk);
} }


$result = fread($this->readBuffer, $count);
$this->bufferSize -= $count;
$result = $this->readBuffer->read($count);


$read = strlen($result); $read = strlen($result);
$this->pos += $read; $this->pos += $read;
public function stream_seek($offset, $whence = SEEK_SET) { public function stream_seek($offset, $whence = SEEK_SET) {
$result = parent::stream_seek($offset, $whence); $result = parent::stream_seek($offset, $whence);
if ($result) { if ($result) {
$this->readBuffer = fopen('php://memory', 'r+');
$this->bufferSize = 0;
$this->pos = parent::stream_tell();
$this->readBuffer->clear();
$pos = parent::stream_tell();
if ($pos === false) {
return false;
}
$this->pos = $pos;
} }
return $result; return $result;
} }


public function stream_eof() { public function stream_eof() {
return $this->bufferSize <= 0 && parent::stream_eof();
return $this->readBuffer->remaining() <= 0 && parent::stream_eof();
} }


public function stream_tell() { public function stream_tell() {

+ 14
- 15
apps/files_external/3rdparty/icewind/smb/src/Native/NativeServer.php View File

namespace Icewind\SMB\Native; namespace Icewind\SMB\Native;


use Icewind\SMB\AbstractServer; use Icewind\SMB\AbstractServer;
use Icewind\SMB\Exception\AuthenticationException;
use Icewind\SMB\Exception\InvalidHostException;
use Icewind\SMB\IAuth; use Icewind\SMB\IAuth;
use Icewind\SMB\IOptions; use Icewind\SMB\IOptions;
use Icewind\SMB\IShare;
use Icewind\SMB\ISystem; use Icewind\SMB\ISystem;
use Icewind\SMB\TimeZoneProvider;
use Icewind\SMB\ITimeZoneProvider;


class NativeServer extends AbstractServer { class NativeServer extends AbstractServer {
/** /**
*/ */
protected $state; protected $state;


public function __construct($host, IAuth $auth, ISystem $system, TimeZoneProvider $timeZoneProvider, IOptions $options) {
public function __construct(string $host, IAuth $auth, ISystem $system, ITimeZoneProvider $timeZoneProvider, IOptions $options) {
parent::__construct($host, $auth, $system, $timeZoneProvider, $options); parent::__construct($host, $auth, $system, $timeZoneProvider, $options);
$this->state = new NativeState(); $this->state = new NativeState();
} }


protected function connect() {
protected function connect(): void {
$this->state->init($this->getAuth(), $this->getOptions()); $this->state->init($this->getAuth(), $this->getOptions());
} }


/** /**
* @return \Icewind\SMB\IShare[]
* @throws \Icewind\SMB\Exception\AuthenticationException
* @throws \Icewind\SMB\Exception\InvalidHostException
* @return IShare[]
* @throws AuthenticationException
* @throws InvalidHostException
*/ */
public function listShares() {
public function listShares(): array {
$this->connect(); $this->connect();
$shares = []; $shares = [];
$dh = $this->state->opendir('smb://' . $this->getHost()); $dh = $this->state->opendir('smb://' . $this->getHost());
while ($share = $this->state->readdir($dh)) {
while ($share = $this->state->readdir($dh, '')) {
if ($share['type'] === 'file share') { if ($share['type'] === 'file share') {
$shares[] = $this->getShare($share['name']); $shares[] = $this->getShare($share['name']);
} }
} }
$this->state->closedir($dh);
$this->state->closedir($dh, '');
return $shares; return $shares;
} }


/**
* @param string $name
* @return \Icewind\SMB\IShare
*/
public function getShare($name) {
public function getShare(string $name): IShare {
return new NativeShare($this, $name); return new NativeShare($this, $name);
} }


* @param ISystem $system * @param ISystem $system
* @return bool * @return bool
*/ */
public static function available(ISystem $system) {
public static function available(ISystem $system): bool {
return $system->libSmbclientAvailable(); return $system->libSmbclientAvailable();
} }
} }

+ 68
- 65
apps/files_external/3rdparty/icewind/smb/src/Native/NativeShare.php View File

namespace Icewind\SMB\Native; namespace Icewind\SMB\Native;


use Icewind\SMB\AbstractShare; use Icewind\SMB\AbstractShare;
use Icewind\SMB\Exception\AlreadyExistsException;
use Icewind\SMB\Exception\AuthenticationException;
use Icewind\SMB\Exception\ConnectionException;
use Icewind\SMB\Exception\DependencyException; use Icewind\SMB\Exception\DependencyException;
use Icewind\SMB\Exception\InvalidHostException;
use Icewind\SMB\Exception\InvalidPathException; use Icewind\SMB\Exception\InvalidPathException;
use Icewind\SMB\Exception\InvalidResourceException; use Icewind\SMB\Exception\InvalidResourceException;
use Icewind\SMB\Exception\InvalidTypeException;
use Icewind\SMB\Exception\NotFoundException;
use Icewind\SMB\IFileInfo;
use Icewind\SMB\INotifyHandler; use Icewind\SMB\INotifyHandler;
use Icewind\SMB\IServer; use Icewind\SMB\IServer;
use Icewind\SMB\Wrapped\Server; use Icewind\SMB\Wrapped\Server;
*/ */
private $name; private $name;


/**
* @var NativeState $state
*/
private $state;
/** @var NativeState|null $state */
private $state = null;


/**
* @param IServer $server
* @param string $name
*/
public function __construct($server, $name) {
public function __construct(IServer $server, string $name) {
parent::__construct(); parent::__construct();
$this->server = $server; $this->server = $server;
$this->name = $name; $this->name = $name;
} }


/** /**
* @throws \Icewind\SMB\Exception\ConnectionException
* @throws \Icewind\SMB\Exception\AuthenticationException
* @throws \Icewind\SMB\Exception\InvalidHostException
* @throws ConnectionException
* @throws AuthenticationException
* @throws InvalidHostException
*/ */
protected function getState() {
if ($this->state and $this->state instanceof NativeState) {
protected function getState(): NativeState {
if ($this->state) {
return $this->state; return $this->state;
} }


* *
* @return string * @return string
*/ */
public function getName() {
public function getName(): string {
return $this->name; return $this->name;
} }


private function buildUrl($path) {
private function buildUrl(string $path): string {
$this->verifyPath($path); $this->verifyPath($path);
$url = sprintf('smb://%s/%s', $this->server->getHost(), $this->name); $url = sprintf('smb://%s/%s', $this->server->getHost(), $this->name);
if ($path) { if ($path) {
* List the content of a remote folder * List the content of a remote folder
* *
* @param string $path * @param string $path
* @return \Icewind\SMB\IFileInfo[]
* @return IFileInfo[]
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\InvalidTypeException
* @throws NotFoundException
* @throws InvalidTypeException
*/ */
public function dir($path) {
public function dir(string $path): array {
$files = []; $files = [];


$dh = $this->getState()->opendir($this->buildUrl($path)); $dh = $this->getState()->opendir($this->buildUrl($path));
while ($file = $this->getState()->readdir($dh)) {
while ($file = $this->getState()->readdir($dh, $path)) {
$name = $file['name']; $name = $file['name'];
if ($name !== '.' and $name !== '..') { if ($name !== '.' and $name !== '..') {
$fullPath = $path . '/' . $name; $fullPath = $path . '/' . $name;
} }
} }


$this->getState()->closedir($dh);
$this->getState()->closedir($dh, $path);
return $files; return $files;
} }


/** /**
* @param string $path * @param string $path
* @return \Icewind\SMB\IFileInfo
* @return IFileInfo
*/ */
public function stat($path) {
public function stat(string $path): IFileInfo {
$info = new NativeFileInfo($this, $path, self::mb_basename($path)); $info = new NativeFileInfo($this, $path, self::mb_basename($path));


// trigger attribute loading // trigger attribute loading
* Multibyte unicode safe version of basename() * Multibyte unicode safe version of basename()
* *
* @param string $path * @param string $path
* @link https://www.php.net/manual/en/function.basename.php#121405
* @link http://php.net/manual/en/function.basename.php#121405
* @return string * @return string
*/ */
protected static function mb_basename($path) {
protected static function mb_basename(string $path): string {
if (preg_match('@^.*[\\\\/]([^\\\\/]+)$@s', $path, $matches)) { if (preg_match('@^.*[\\\\/]([^\\\\/]+)$@s', $path, $matches)) {
return $matches[1]; return $matches[1];
} elseif (preg_match('@^([^\\\\/]+)$@s', $path, $matches)) { } elseif (preg_match('@^([^\\\\/]+)$@s', $path, $matches)) {
* @param string $path * @param string $path
* @return bool * @return bool
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\AlreadyExistsException
* @throws NotFoundException
* @throws AlreadyExistsException
*/ */
public function mkdir($path) {
public function mkdir(string $path): bool {
return $this->getState()->mkdir($this->buildUrl($path)); return $this->getState()->mkdir($this->buildUrl($path));
} }


* @param string $path * @param string $path
* @return bool * @return bool
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\InvalidTypeException
* @throws NotFoundException
* @throws InvalidTypeException
*/ */
public function rmdir($path) {
public function rmdir(string $path): bool {
return $this->getState()->rmdir($this->buildUrl($path)); return $this->getState()->rmdir($this->buildUrl($path));
} }


* @param string $path * @param string $path
* @return bool * @return bool
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\InvalidTypeException
* @throws NotFoundException
* @throws InvalidTypeException
*/ */
public function del($path) {
public function del(string $path): bool {
return $this->getState()->unlink($this->buildUrl($path)); return $this->getState()->unlink($this->buildUrl($path));
} }


* @param string $to * @param string $to
* @return bool * @return bool
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\AlreadyExistsException
* @throws NotFoundException
* @throws AlreadyExistsException
*/ */
public function rename($from, $to) {
public function rename(string $from, string $to): bool {
return $this->getState()->rename($this->buildUrl($from), $this->buildUrl($to)); return $this->getState()->rename($this->buildUrl($from), $this->buildUrl($to));
} }


* @param string $target remove file * @param string $target remove file
* @return bool * @return bool
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\InvalidTypeException
* @throws NotFoundException
* @throws InvalidTypeException
*/ */
public function put($source, $target) {
public function put(string $source, string $target): bool {
$sourceHandle = fopen($source, 'rb'); $sourceHandle = fopen($source, 'rb');
$targetUrl = $this->buildUrl($target); $targetUrl = $this->buildUrl($target);


* @param string $target local file * @param string $target local file
* @return bool * @return bool
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\InvalidTypeException
* @throws \Icewind\SMB\Exception\InvalidPathException
* @throws \Icewind\SMB\Exception\InvalidResourceException
* @throws AuthenticationException
* @throws ConnectionException
* @throws InvalidHostException
* @throws InvalidPathException
* @throws InvalidResourceException
*/ */
public function get($source, $target) {
public function get(string $source, string $target): bool {
if (!$target) { if (!$target) {
throw new InvalidPathException('Invalid target path: Filename cannot be empty'); throw new InvalidPathException('Invalid target path: Filename cannot be empty');
} }


$sourceHandle = $this->getState()->open($this->buildUrl($source), 'r'); $sourceHandle = $this->getState()->open($this->buildUrl($source), 'r');
if (!$sourceHandle) {
throw new InvalidResourceException('Failed opening remote file "' . $source . '" for reading');
}


$targetHandle = @fopen($target, 'wb'); $targetHandle = @fopen($target, 'wb');
if (!$targetHandle) { if (!$targetHandle) {
throw new InvalidResourceException('Failed opening local file "' . $target . '" for writing: ' . $reason); throw new InvalidResourceException('Failed opening local file "' . $target . '" for writing: ' . $reason);
} }


while ($data = $this->getState()->read($sourceHandle, NativeReadStream::CHUNK_SIZE)) {
while ($data = $this->getState()->read($sourceHandle, NativeReadStream::CHUNK_SIZE, $source)) {
fwrite($targetHandle, $data); fwrite($targetHandle, $data);
} }
$this->getState()->close($sourceHandle, $this->buildUrl($source)); $this->getState()->close($sourceHandle, $this->buildUrl($source));
* @param string $source * @param string $source
* @return resource a read only stream with the contents of the remote file * @return resource a read only stream with the contents of the remote file
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\InvalidTypeException
* @throws NotFoundException
* @throws InvalidTypeException
*/ */
public function read($source) {
public function read(string $source) {
$url = $this->buildUrl($source); $url = $this->buildUrl($source);
$handle = $this->getState()->open($url, 'r'); $handle = $this->getState()->open($url, 'r');
return NativeReadStream::wrap($this->getState(), $handle, 'r', $url); return NativeReadStream::wrap($this->getState(), $handle, 'r', $url);
* @param string $source * @param string $source
* @return resource a writeable stream * @return resource a writeable stream
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\InvalidTypeException
* @throws NotFoundException
* @throws InvalidTypeException
*/ */
public function write($source) {
public function write(string $source) {
$url = $this->buildUrl($source); $url = $this->buildUrl($source);
$handle = $this->getState()->create($url); $handle = $this->getState()->create($url);
return NativeWriteStream::wrap($this->getState(), $handle, 'w', $url); return NativeWriteStream::wrap($this->getState(), $handle, 'w', $url);
* @param string $source * @param string $source
* @return resource a writeable stream * @return resource a writeable stream
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\InvalidTypeException
* @throws NotFoundException
* @throws InvalidTypeException
*/ */
public function append($source) {
public function append(string $source) {
$url = $this->buildUrl($source); $url = $this->buildUrl($source);
$handle = $this->getState()->open($url, "a+"); $handle = $this->getState()->open($url, "a+");
return NativeWriteStream::wrap($this->getState(), $handle, "a", $url); return NativeWriteStream::wrap($this->getState(), $handle, "a", $url);
* @param string $attribute attribute to get the info * @param string $attribute attribute to get the info
* @return string the attribute value * @return string the attribute value
*/ */
public function getAttribute($path, $attribute) {
public function getAttribute(string $path, string $attribute): string {
return $this->getState()->getxattr($this->buildUrl($path), $attribute); return $this->getState()->getxattr($this->buildUrl($path), $attribute);
} }


* @param string|int $value * @param string|int $value
* @return mixed the attribute value * @return mixed the attribute value
*/ */
public function setAttribute($path, $attribute, $value) {
if ($attribute === 'system.dos_attr.mode' and is_int($value)) {
$value = '0x' . dechex($value);
public function setAttribute(string $path, string $attribute, $value) {
if (is_int($value)) {
if ($attribute === 'system.dos_attr.mode') {
$value = '0x' . dechex($value);
} else {
throw new \InvalidArgumentException("Invalid value for attribute");
}
} }


return $this->getState()->setxattr($this->buildUrl($path), $attribute, $value); return $this->getState()->setxattr($this->buildUrl($path), $attribute, $value);
* @param int $mode a combination of FileInfo::MODE_READONLY, FileInfo::MODE_ARCHIVE, FileInfo::MODE_SYSTEM and FileInfo::MODE_HIDDEN, FileInfo::NORMAL * @param int $mode a combination of FileInfo::MODE_READONLY, FileInfo::MODE_ARCHIVE, FileInfo::MODE_SYSTEM and FileInfo::MODE_HIDDEN, FileInfo::NORMAL
* @return mixed * @return mixed
*/ */
public function setMode($path, $mode) {
public function setMode(string $path, int $mode) {
return $this->setAttribute($path, 'system.dos_attr.mode', $mode); return $this->setAttribute($path, 'system.dos_attr.mode', $mode);
} }


* @param string $path * @param string $path
* @return INotifyHandler * @return INotifyHandler
*/ */
public function notify($path) {
public function notify(string $path): INotifyHandler {
// php-smbclient does not support notify (https://github.com/eduardok/libsmbclient-php/issues/29) // php-smbclient does not support notify (https://github.com/eduardok/libsmbclient-php/issues/29)
// so we use the smbclient based backend for this // so we use the smbclient based backend for this
if (!Server::available($this->server->getSystem())) { if (!Server::available($this->server->getSystem())) {

+ 85
- 39
apps/files_external/3rdparty/icewind/smb/src/Native/NativeState.php View File

* Low level wrapper for libsmbclient-php with error handling * Low level wrapper for libsmbclient-php with error handling
*/ */
class NativeState { class NativeState {
/**
* @var resource
*/
protected $state;
/** @var resource|null */
protected $state = null;


/** @var bool */
protected $handlerSet = false; protected $handlerSet = false;


/** @var bool */
protected $connected = false; protected $connected = false;


// see error.h // see error.h
113 => NoRouteToHostException::class 113 => NoRouteToHostException::class
]; ];


protected function handleError($path) {
protected function handleError(?string $path): void {
/** @var int $error */
$error = smbclient_state_errno($this->state); $error = smbclient_state_errno($this->state);
if ($error === 0) { if ($error === 0) {
return; return;
throw Exception::fromMap(self::EXCEPTION_MAP, $error, $path); throw Exception::fromMap(self::EXCEPTION_MAP, $error, $path);
} }


protected function testResult($result, $uri) {
/**
* @param mixed $result
* @param string|null $uri
* @throws Exception
*/
protected function testResult($result, ?string $uri): void {
if ($result === false or $result === null) { if ($result === false or $result === null) {
// smb://host/share/path // smb://host/share/path
if (is_string($uri) && count(explode('/', $uri, 5)) > 4) { if (is_string($uri) && count(explode('/', $uri, 5)) > 4) {
list(, , , , $path) = explode('/', $uri, 5); list(, , , , $path) = explode('/', $uri, 5);
$path = '/' . $path; $path = '/' . $path;
} else { } else {
$path = null;
$path = $uri;
} }
$this->handleError($path); $this->handleError($path);
} }
if ($this->connected) { if ($this->connected) {
return true; return true;
} }
$this->state = smbclient_state_new();
/** @var resource $state */
$state = smbclient_state_new();
$this->state = $state;
smbclient_option_set($this->state, SMBCLIENT_OPT_AUTO_ANONYMOUS_LOGIN, false); smbclient_option_set($this->state, SMBCLIENT_OPT_AUTO_ANONYMOUS_LOGIN, false);
smbclient_option_set($this->state, SMBCLIENT_OPT_TIMEOUT, $options->getTimeout() * 1000); smbclient_option_set($this->state, SMBCLIENT_OPT_TIMEOUT, $options->getTimeout() * 1000);

if (function_exists('smbclient_client_protocols')) {
$maxProtocol = $options->getMaxProtocol();
$minProtocol = $options->getMinProtocol();

smbclient_client_protocols($this->state, $minProtocol, $maxProtocol);
}

$auth->setExtraSmbClientOptions($this->state); $auth->setExtraSmbClientOptions($this->state);
/** @var bool $result */
$result = @smbclient_state_init($this->state, $auth->getWorkgroup(), $auth->getUsername(), $auth->getPassword()); $result = @smbclient_state_init($this->state, $auth->getWorkgroup(), $auth->getUsername(), $auth->getPassword());


$this->testResult($result, ''); $this->testResult($result, '');
* @param string $uri * @param string $uri
* @return resource * @return resource
*/ */
public function opendir($uri) {
public function opendir(string $uri) {
/** @var resource $result */
$result = @smbclient_opendir($this->state, $uri); $result = @smbclient_opendir($this->state, $uri);


$this->testResult($result, $uri); $this->testResult($result, $uri);


/** /**
* @param resource $dir * @param resource $dir
* @return array
* @param string $path
* @return array{"type": string, "comment": string, "name": string}|false
*/ */
public function readdir($dir) {
public function readdir($dir, string $path) {
/** @var array{"type": string, "comment": string, "name": string}|false $result */
$result = @smbclient_readdir($this->state, $dir); $result = @smbclient_readdir($this->state, $dir);


$this->testResult($result, $dir);
$this->testResult($result, $path);
return $result; return $result;
} }


/** /**
* @param $dir
* @param resource $dir
* @param string $path
* @return bool * @return bool
*/ */
public function closedir($dir) {
public function closedir($dir, string $path): bool {
/** @var bool $result */
$result = smbclient_closedir($this->state, $dir); $result = smbclient_closedir($this->state, $dir);


$this->testResult($result, $dir);
$this->testResult($result, $path);
return $result; return $result;
} }


* @param string $new * @param string $new
* @return bool * @return bool
*/ */
public function rename($old, $new) {
public function rename(string $old, string $new): bool {
/** @var bool $result */
$result = @smbclient_rename($this->state, $old, $this->state, $new); $result = @smbclient_rename($this->state, $old, $this->state, $new);


$this->testResult($result, $new); $this->testResult($result, $new);
* @param string $uri * @param string $uri
* @return bool * @return bool
*/ */
public function unlink($uri) {
public function unlink(string $uri): bool {
/** @var bool $result */
$result = @smbclient_unlink($this->state, $uri); $result = @smbclient_unlink($this->state, $uri);


$this->testResult($result, $uri); $this->testResult($result, $uri);
* @param int $mask * @param int $mask
* @return bool * @return bool
*/ */
public function mkdir($uri, $mask = 0777) {
public function mkdir(string $uri, int $mask = 0777): bool {
/** @var bool $result */
$result = @smbclient_mkdir($this->state, $uri, $mask); $result = @smbclient_mkdir($this->state, $uri, $mask);


$this->testResult($result, $uri); $this->testResult($result, $uri);
* @param string $uri * @param string $uri
* @return bool * @return bool
*/ */
public function rmdir($uri) {
public function rmdir(string $uri): bool {
/** @var bool $result */
$result = @smbclient_rmdir($this->state, $uri); $result = @smbclient_rmdir($this->state, $uri);


$this->testResult($result, $uri); $this->testResult($result, $uri);


/** /**
* @param string $uri * @param string $uri
* @return array
* @return array{"mtime": int, "size": int, "mode": int}
*/ */
public function stat($uri) {
public function stat(string $uri): array {
/** @var array{"mtime": int, "size": int, "mode": int} $result */
$result = @smbclient_stat($this->state, $uri); $result = @smbclient_stat($this->state, $uri);


$this->testResult($result, $uri); $this->testResult($result, $uri);


/** /**
* @param resource $file * @param resource $file
* @return array
* @param string $path
* @return array{"mtime": int, "size": int, "mode": int}
*/ */
public function fstat($file) {
public function fstat($file, string $path): array {
/** @var array{"mtime": int, "size": int, "mode": int} $result */
$result = @smbclient_fstat($this->state, $file); $result = @smbclient_fstat($this->state, $file);


$this->testResult($result, $file);
$this->testResult($result, $path);
return $result; return $result;
} }


* @param int $mask * @param int $mask
* @return resource * @return resource
*/ */
public function open($uri, $mode, $mask = 0666) {
public function open(string $uri, string $mode, int $mask = 0666) {
/** @var resource $result */
$result = @smbclient_open($this->state, $uri, $mode, $mask); $result = @smbclient_open($this->state, $uri, $mode, $mask);


$this->testResult($result, $uri); $this->testResult($result, $uri);
* @param int $mask * @param int $mask
* @return resource * @return resource
*/ */
public function create($uri, $mask = 0666) {
public function create(string $uri, int $mask = 0666) {
/** @var resource $result */
$result = @smbclient_creat($this->state, $uri, $mask); $result = @smbclient_creat($this->state, $uri, $mask);


$this->testResult($result, $uri); $this->testResult($result, $uri);
/** /**
* @param resource $file * @param resource $file
* @param int $bytes * @param int $bytes
* @param string $path
* @return string * @return string
*/ */
public function read($file, $bytes) {
public function read($file, int $bytes, string $path): string {
/** @var string $result */
$result = @smbclient_read($this->state, $file, $bytes); $result = @smbclient_read($this->state, $file, $bytes);


$this->testResult($result, $file);
$this->testResult($result, $path);
return $result; return $result;
} }


* @param resource $file * @param resource $file
* @param string $data * @param string $data
* @param string $path * @param string $path
* @param int $length
* @param int|null $length
* @return int * @return int
*/ */
public function write($file, $data, $path, $length = null) {
public function write($file, string $data, string $path, ?int $length = null): int {
/** @var int $result */
$result = @smbclient_write($this->state, $file, $data, $length); $result = @smbclient_write($this->state, $file, $data, $length);


$this->testResult($result, $path); $this->testResult($result, $path);
* @param resource $file * @param resource $file
* @param int $offset * @param int $offset
* @param int $whence SEEK_SET | SEEK_CUR | SEEK_END * @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.
* @param string|null $path
* @return int|false new file offset as measured from the start of the file on success.
*/ */
public function lseek($file, $offset, $whence = SEEK_SET) {
public function lseek($file, int $offset, int $whence = SEEK_SET, string $path = null) {
/** @var int|false $result */
$result = @smbclient_lseek($this->state, $file, $offset, $whence); $result = @smbclient_lseek($this->state, $file, $offset, $whence);


$this->testResult($result, $file);
$this->testResult($result, $path);
return $result; return $result;
} }


/** /**
* @param resource $file * @param resource $file
* @param int $size * @param int $size
* @param string $path
* @return bool * @return bool
*/ */
public function ftruncate($file, $size) {
public function ftruncate($file, int $size, string $path): bool {
/** @var bool $result */
$result = @smbclient_ftruncate($this->state, $file, $size); $result = @smbclient_ftruncate($this->state, $file, $size);


$this->testResult($result, $file);
$this->testResult($result, $path);
return $result; return $result;
} }


public function close($file, $path) {
/**
* @param resource $file
* @param string $path
* @return bool
*/
public function close($file, string $path): bool {
/** @var bool $result */
$result = @smbclient_close($this->state, $file); $result = @smbclient_close($this->state, $file);


$this->testResult($result, $path); $this->testResult($result, $path);
* @param string $key * @param string $key
* @return string * @return string
*/ */
public function getxattr($uri, $key) {
public function getxattr(string $uri, string $key) {
/** @var string $result */
$result = @smbclient_getxattr($this->state, $uri, $key); $result = @smbclient_getxattr($this->state, $uri, $key);


$this->testResult($result, $uri); $this->testResult($result, $uri);
* @param string $key * @param string $key
* @param string $value * @param string $value
* @param int $flags * @param int $flags
* @return mixed
* @return bool
*/ */
public function setxattr($uri, $key, $value, $flags = 0) {
public function setxattr(string $uri, string $key, string $value, int $flags = 0) {
/** @var bool $result */
$result = @smbclient_setxattr($this->state, $uri, $key, $value, $flags); $result = @smbclient_setxattr($this->state, $uri, $key, $value, $flags);


$this->testResult($result, $uri); $this->testResult($result, $uri);

+ 36
- 12
apps/files_external/3rdparty/icewind/smb/src/Native/NativeStream.php View File

use Icewind\SMB\Exception\Exception; use Icewind\SMB\Exception\Exception;
use Icewind\SMB\Exception\InvalidRequestException; use Icewind\SMB\Exception\InvalidRequestException;
use Icewind\Streams\File; use Icewind\Streams\File;
use InvalidArgumentException;


class NativeStream implements File {
abstract class NativeStream implements File {
/** /**
* @var resource * @var resource
* @psalm-suppress PropertyNotSetInConstructor
*/ */
public $context; public $context;


/** /**
* @var NativeState * @var NativeState
* @psalm-suppress PropertyNotSetInConstructor
*/ */
protected $state; protected $state;


/** /**
* @var resource * @var resource
* @psalm-suppress PropertyNotSetInConstructor
*/ */
protected $handle; protected $handle;


/** /**
* @var string * @var string
*/ */
protected $url;
protected $url = '';


/** /**
* Wrap a stream from libsmbclient-php into a regular php stream * Wrap a stream from libsmbclient-php into a regular php stream
* *
* @param \Icewind\SMB\NativeState $state
* @param NativeState $state
* @param resource $smbStream * @param resource $smbStream
* @param string $mode * @param string $mode
* @param string $url * @param string $url
* @param class-string<NativeStream> $class
* @return resource * @return resource
*/ */
public static function wrap($state, $smbStream, $mode, $url) {
stream_wrapper_register('nativesmb', NativeStream::class);
protected static function wrapClass(NativeState $state, $smbStream, string $mode, string $url, string $class) {
stream_wrapper_register('nativesmb', $class);
$context = stream_context_create([ $context = stream_context_create([
'nativesmb' => [ 'nativesmb' => [
'state' => $state, 'state' => $state,
} }


public function stream_flush() { public function stream_flush() {
return false;
} }




public function stream_open($path, $mode, $options, &$opened_path) { public function stream_open($path, $mode, $options, &$opened_path) {
$context = stream_context_get_options($this->context); $context = stream_context_get_options($this->context);
$this->state = $context['nativesmb']['state'];
$this->handle = $context['nativesmb']['handle'];
$this->url = $context['nativesmb']['url'];
if (!isset($context['nativesmb']) || !is_array($context['nativesmb'])) {
throw new InvalidArgumentException("context not set");
}
$state = $context['nativesmb']['state'];
if (!$state instanceof NativeState) {
throw new InvalidArgumentException("invalid context set");
}
$this->state = $state;
$handle = $context['nativesmb']['handle'];
if (!is_resource($handle)) {
throw new InvalidArgumentException("invalid context set");
}
$this->handle = $handle;
$url = $context['nativesmb']['url'];
if (!is_string($url)) {
throw new InvalidArgumentException("invalid context set");
}
$this->url = $url;
return true; return true;
} }


public function stream_read($count) { public function stream_read($count) {
$result = $this->state->read($this->handle, $count);
$result = $this->state->read($this->handle, $count, $this->url);
if (strlen($result) < $count) { if (strlen($result) < $count) {
$this->eof = true; $this->eof = true;
} }
public function stream_seek($offset, $whence = SEEK_SET) { public function stream_seek($offset, $whence = SEEK_SET) {
$this->eof = false; $this->eof = false;
try { try {
return $this->state->lseek($this->handle, $offset, $whence) !== false;
return $this->state->lseek($this->handle, $offset, $whence, $this->url) !== false;
} catch (InvalidRequestException $e) { } catch (InvalidRequestException $e) {
return false; return false;
} }
} }


/**
* @return array{"mtime": int, "size": int, "mode": int}|false
*/
public function stream_stat() { public function stream_stat() {
try { try {
return $this->state->stat($this->url); return $this->state->stat($this->url);
} }


public function stream_tell() { public function stream_tell() {
return $this->state->lseek($this->handle, 0, SEEK_CUR);
return $this->state->lseek($this->handle, 0, SEEK_CUR, $this->url);
} }


public function stream_write($data) { public function stream_write($data) {
} }


public function stream_truncate($size) { public function stream_truncate($size) {
return $this->state->ftruncate($this->handle, $size);
return $this->state->ftruncate($this->handle, $size, $this->url);
} }


public function stream_set_option($option, $arg1, $arg2) { public function stream_set_option($option, $arg1, $arg2) {

+ 21
- 29
apps/files_external/3rdparty/icewind/smb/src/Native/NativeWriteStream.php View File



namespace Icewind\SMB\Native; namespace Icewind\SMB\Native;


use Icewind\SMB\StringBuffer;

/** /**
* Stream optimized for write only usage * Stream optimized for write only usage
*/ */
class NativeWriteStream extends NativeStream { class NativeWriteStream extends NativeStream {
const CHUNK_SIZE = 1048576; // 1MB chunks const CHUNK_SIZE = 1048576; // 1MB chunks
/**
* @var resource
*/
private $writeBuffer = null;


private $bufferSize = 0;
/** @var StringBuffer */
private $writeBuffer;


/** @var int */
private $pos = 0; private $pos = 0;


public function stream_open($path, $mode, $options, &$opened_path) {
$this->writeBuffer = fopen('php://memory', 'r+');
public function __construct() {
$this->writeBuffer = new StringBuffer();
}


public function stream_open($path, $mode, $options, &$opened_path): bool {
return parent::stream_open($path, $mode, $options, $opened_path); return parent::stream_open($path, $mode, $options, $opened_path);
} }


/** /**
* Wrap a stream from libsmbclient-php into a regular php stream * Wrap a stream from libsmbclient-php into a regular php stream
* *
* @param \Icewind\SMB\NativeState $state
* @param NativeState $state
* @param resource $smbStream * @param resource $smbStream
* @param string $mode * @param string $mode
* @param string $url * @param string $url
* @return resource * @return resource
*/ */
public static function wrap($state, $smbStream, $mode, $url) {
stream_wrapper_register('nativesmb', NativeWriteStream::class);
$context = stream_context_create([
'nativesmb' => [
'state' => $state,
'handle' => $smbStream,
'url' => $url
]
]);
$fh = fopen('nativesmb://', $mode, false, $context);
stream_wrapper_unregister('nativesmb');
return $fh;
public static function wrap(NativeState $state, $smbStream, string $mode, string $url) {
return parent::wrapClass($state, $smbStream, $mode, $url, NativeWriteStream::class);
} }


public function stream_seek($offset, $whence = SEEK_SET) { public function stream_seek($offset, $whence = SEEK_SET) {
$this->flushWrite(); $this->flushWrite();
$result = parent::stream_seek($offset, $whence); $result = parent::stream_seek($offset, $whence);
if ($result) { if ($result) {
$this->pos = parent::stream_tell();
$pos = parent::stream_tell();
if ($pos === false) {
return false;
}
$this->pos = $pos;
} }
return $result; return $result;
} }


private function flushWrite() {
rewind($this->writeBuffer);
$this->state->write($this->handle, stream_get_contents($this->writeBuffer), $this->url);
$this->writeBuffer = fopen('php://memory', 'r+');
$this->bufferSize = 0;
private function flushWrite(): void {
parent::stream_write($this->writeBuffer->flush());
} }


public function stream_write($data) { public function stream_write($data) {
$written = fwrite($this->writeBuffer, $data);
$this->bufferSize += $written;
$written = $this->writeBuffer->push($data);
$this->pos += $written; $this->pos += $written;


if ($this->bufferSize >= self::CHUNK_SIZE) {
if ($this->writeBuffer->remaining() >= self::CHUNK_SIZE) {
$this->flushWrite(); $this->flushWrite();
} }



+ 23
- 2
apps/files_external/3rdparty/icewind/smb/src/Options.php View File

/** @var int */ /** @var int */
private $timeout = 20; private $timeout = 20;


public function getTimeout() {
/** @var string|null */
private $minProtocol;
/** @var string|null */
private $maxProtocol;

public function getTimeout(): int {
return $this->timeout; return $this->timeout;
} }


public function setTimeout($timeout) {
public function setTimeout(int $timeout): void {
$this->timeout = $timeout; $this->timeout = $timeout;
} }

public function getMinProtocol(): ?string {
return $this->minProtocol;
}

public function setMinProtocol(?string $minProtocol): void {
$this->minProtocol = $minProtocol;
}

public function getMaxProtocol(): ?string {
return $this->maxProtocol;
}

public function setMaxProtocol(?string $maxProtocol): void {
$this->maxProtocol = $maxProtocol;
}
} }

+ 3
- 3
apps/files_external/3rdparty/icewind/smb/src/ServerFactory.php View File

Server::class Server::class
]; ];


/** @var System */
/** @var ISystem */
private $system; private $system;


/** @var IOptions */ /** @var IOptions */




/** /**
* @param $host
* @param string $host
* @param IAuth $credentials * @param IAuth $credentials
* @return IServer * @return IServer
* @throws DependencyException * @throws DependencyException
*/ */
public function createServer($host, IAuth $credentials) {
public function createServer(string $host, IAuth $credentials): IServer {
foreach (self::BACKENDS as $backend) { foreach (self::BACKENDS as $backend) {
if (call_user_func("$backend::available", $this->system)) { if (call_user_func("$backend::available", $this->system)) {
return new $backend($host, $credentials, $this->system, $this->timeZoneProvider, $this->options); return new $backend($host, $credentials, $this->system, $this->timeZoneProvider, $this->options);

+ 63
- 0
apps/files_external/3rdparty/icewind/smb/src/StringBuffer.php View File

<?php

declare(strict_types=1);
/**
* @copyright Copyright (c) 2021 Robin Appelman <robin@icewind.nl>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

namespace Icewind\SMB;

class StringBuffer {
/** @var string */
private $buffer = "";
/** @var int */
private $pos = 0;

public function clear(): void {
$this->buffer = "";
$this->pos = 0;
}

public function push(string $data): int {
$this->buffer = $this->flush() . $data;
return strlen($data);
}

public function remaining(): int {
return strlen($this->buffer) - $this->pos;
}

public function read(int $count): string {
$chunk = substr($this->buffer, $this->pos, $this->pos + $count);
$this->pos += strlen($chunk);
return $chunk;
}

public function flush(): string {
if ($this->pos === 0) {
$remaining = $this->buffer;
} else {
$remaining = substr($this->buffer, $this->pos);
}

$this->clear();

return $remaining;
}
}

+ 10
- 10
apps/files_external/3rdparty/icewind/smb/src/System.php View File

use Icewind\SMB\Exception\Exception; use Icewind\SMB\Exception\Exception;


class System implements ISystem { class System implements ISystem {
/** @var (string|bool)[] */
/** @var (string|null)[] */
private $paths = []; private $paths = [];


/** /**
* @return string * @return string
* @throws Exception * @throws Exception
*/ */
public function getFD($num) {
public function getFD(int $num): string {
$folders = [ $folders = [
'/proc/self/fd', '/proc/self/fd',
'/dev/fd' '/dev/fd'
throw new Exception('Cant find file descriptor path'); throw new Exception('Cant find file descriptor path');
} }


public function getSmbclientPath() {
public function getSmbclientPath(): ?string {
return $this->getBinaryPath('smbclient'); return $this->getBinaryPath('smbclient');
} }


public function getNetPath() {
public function getNetPath(): ?string {
return $this->getBinaryPath('net'); return $this->getBinaryPath('net');
} }


public function getSmbcAclsPath() {
public function getSmbcAclsPath(): ?string {
return $this->getBinaryPath('smbcacls'); return $this->getBinaryPath('smbcacls');
} }


public function getStdBufPath() {
public function getStdBufPath(): ?string {
return $this->getBinaryPath('stdbuf'); return $this->getBinaryPath('stdbuf');
} }


public function getDatePath() {
public function getDatePath(): ?string {
return $this->getBinaryPath('date'); return $this->getBinaryPath('date');
} }


public function libSmbclientAvailable() {
public function libSmbclientAvailable(): bool {
return function_exists('smbclient_state_new'); return function_exists('smbclient_state_new');
} }


protected function getBinaryPath($binary) {
protected function getBinaryPath(string $binary): ?string {
if (!isset($this->paths[$binary])) { if (!isset($this->paths[$binary])) {
$result = null; $result = null;
$output = []; $output = [];
exec("which $binary 2>&1", $output, $result); exec("which $binary 2>&1", $output, $result);
$this->paths[$binary] = $result === 0 ? trim(implode('', $output)) : false;
$this->paths[$binary] = $result === 0 ? trim(implode('', $output)) : null;
} }
return $this->paths[$binary]; return $this->paths[$binary];
} }

+ 1
- 1
apps/files_external/3rdparty/icewind/smb/src/TimeZoneProvider.php View File

$this->system = $system; $this->system = $system;
} }


public function get($host) {
public function get(string $host): string {
if (!isset($this->timeZones[$host])) { if (!isset($this->timeZones[$host])) {
$timeZone = null; $timeZone = null;
$net = $this->system->getNetPath(); $net = $this->system->getNetPath();

+ 30
- 19
apps/files_external/3rdparty/icewind/smb/src/Wrapped/Connection.php View File



namespace Icewind\SMB\Wrapped; namespace Icewind\SMB\Wrapped;


use Icewind\SMB\Exception\AccessDeniedException;
use Icewind\SMB\Exception\AuthenticationException; use Icewind\SMB\Exception\AuthenticationException;
use Icewind\SMB\Exception\ConnectException; use Icewind\SMB\Exception\ConnectException;
use Icewind\SMB\Exception\ConnectionException; use Icewind\SMB\Exception\ConnectionException;
use Icewind\SMB\Exception\ConnectionRefusedException;
use Icewind\SMB\Exception\InvalidHostException; use Icewind\SMB\Exception\InvalidHostException;
use Icewind\SMB\Exception\NoLoginServerException; use Icewind\SMB\Exception\NoLoginServerException;


/** @var Parser */ /** @var Parser */
private $parser; private $parser;


public function __construct($command, Parser $parser, $env = []) {
/**
* @param string $command
* @param Parser $parser
* @param array<string, string> $env
*/
public function __construct(string $command, Parser $parser, array $env = []) {
parent::__construct($command, $env); parent::__construct($command, $env);
$this->parser = $parser; $this->parser = $parser;
} }
* *
* @param string $input * @param string $input
*/ */
public function write($input) {
parent::write($input . PHP_EOL);
public function write(string $input) {
return parent::write($input . PHP_EOL);
} }


/** /**
* @throws ConnectException * @throws ConnectException
*/ */
public function clearTillPrompt() {
public function clearTillPrompt(): void {
$this->write(''); $this->write('');
do { do {
$promptLine = $this->readLine(); $promptLine = $this->readLine();
if ($promptLine === false) {
break;
}
$this->parser->checkConnectionError($promptLine); $this->parser->checkConnectionError($promptLine);
} while (!$this->isPrompt($promptLine)); } while (!$this->isPrompt($promptLine));
$this->write('');
if ($this->write('') === false) {
throw new ConnectionRefusedException();
}
$this->readLine(); $this->readLine();
} }


/** /**
* get all unprocessed output from smbclient until the next prompt * get all unprocessed output from smbclient until the next prompt
* *
* @param callable $callback (optional) callback to call for every line read
* @param (callable(string):bool)|null $callback (optional) callback to call for every line read
* @return string[] * @return string[]
* @throws AuthenticationException * @throws AuthenticationException
* @throws ConnectException * @throws ConnectException
* @throws ConnectionException * @throws ConnectionException
* @throws InvalidHostException * @throws InvalidHostException
* @throws NoLoginServerException * @throws NoLoginServerException
* @throws AccessDeniedException
*/ */
public function read(callable $callback = null) {
public function read(callable $callback = null): array {
if (!$this->isValid()) { if (!$this->isValid()) {
throw new ConnectionException('Connection not valid'); throw new ConnectionException('Connection not valid');
} }
$promptLine = $this->readLine(); //first line is prompt $promptLine = $this->readLine(); //first line is prompt
if ($promptLine === false) {
$this->unknownError($promptLine);
}
$this->parser->checkConnectionError($promptLine); $this->parser->checkConnectionError($promptLine);


$output = []; $output = [];
if ($line === false) { if ($line === false) {
$this->unknownError($promptLine); $this->unknownError($promptLine);
} }
while (!$this->isPrompt($line)) { //next prompt functions as delimiter
while ($line !== false && !$this->isPrompt($line)) { //next prompt functions as delimiter
if (is_callable($callback)) { if (is_callable($callback)) {
$result = $callback($line); $result = $callback($line);
if ($result === false) { // allow the callback to close the connection for infinite running commands if ($result === false) { // allow the callback to close the connection for infinite running commands
break; break;
} }
} else { } else {
$output[] .= $line;
$output[] = $line;
} }
$line = $this->readLine(); $line = $this->readLine();
} }
return $output; return $output;
} }


/**
* Check
*
* @param $line
* @return bool
*/
private function isPrompt($line) {
return mb_substr($line, 0, self::DELIMITER_LENGTH) === self::DELIMITER || $line === false;
private function isPrompt(string $line): bool {
return mb_substr($line, 0, self::DELIMITER_LENGTH) === self::DELIMITER;
} }


/** /**
* @param string $promptLine (optional) prompt line that might contain some info about the error
* @param string|bool $promptLine (optional) prompt line that might contain some info about the error
* @throws ConnectException * @throws ConnectException
* @return no-return
*/ */
private function unknownError($promptLine = '') { private function unknownError($promptLine = '') {
if ($promptLine) { //maybe we have some error we missed on the previous line if ($promptLine) { //maybe we have some error we missed on the previous line
} }
} }


public function close($terminate = true) {
public function close(bool $terminate = true): void {
if (get_resource_type($this->getInputStream()) === 'stream') { if (get_resource_type($this->getInputStream()) === 'stream') {
// ignore any errors while trying to send the close command, the process might already be dead // ignore any errors while trying to send the close command, the process might already be dead
@$this->write('close' . PHP_EOL); @$this->write('close' . PHP_EOL);

+ 17
- 58
apps/files_external/3rdparty/icewind/smb/src/Wrapped/FileInfo.php View File

use Icewind\SMB\IFileInfo; use Icewind\SMB\IFileInfo;


class FileInfo implements IFileInfo { class FileInfo implements IFileInfo {
/**
* @var string
*/
/** @var string */
protected $path; protected $path;

/**
* @var string
*/
/** @var string */
protected $name; protected $name;

/**
* @var int
*/
/** @var int */
protected $size; protected $size;

/**
* @var int
*/
/** @var int */
protected $time; protected $time;

/**
* @var int
*/
/** @var int */
protected $mode; protected $mode;

/**
* @var callable
*/
/** @var callable(): ACL[] */
protected $aclCallback; protected $aclCallback;


/** /**
* @param int $size * @param int $size
* @param int $time * @param int $time
* @param int $mode * @param int $mode
* @param callable $aclCallback
* @param callable(): ACL[] $aclCallback
*/ */
public function __construct($path, $name, $size, $time, $mode, callable $aclCallback) {
public function __construct(string $path, string $name, int $size, int $time, int $mode, callable $aclCallback) {
$this->path = $path; $this->path = $path;
$this->name = $name; $this->name = $name;
$this->size = $size; $this->size = $size;
/** /**
* @return string * @return string
*/ */
public function getPath() {
public function getPath(): string {
return $this->path; return $this->path;
} }


/**
* @return string
*/
public function getName() {
public function getName(): string {
return $this->name; return $this->name;
} }


/**
* @return int
*/
public function getSize() {
public function getSize(): int {
return $this->size; return $this->size;
} }


/**
* @return int
*/
public function getMTime() {
public function getMTime(): int {
return $this->time; return $this->time;
} }


/**
* @return bool
*/
public function isDirectory() {
public function isDirectory(): bool {
return (bool)($this->mode & IFileInfo::MODE_DIRECTORY); return (bool)($this->mode & IFileInfo::MODE_DIRECTORY);
} }


/**
* @return bool
*/
public function isReadOnly() {
public function isReadOnly(): bool {
return (bool)($this->mode & IFileInfo::MODE_READONLY); return (bool)($this->mode & IFileInfo::MODE_READONLY);
} }


/**
* @return bool
*/
public function isHidden() {
public function isHidden(): bool {
return (bool)($this->mode & IFileInfo::MODE_HIDDEN); return (bool)($this->mode & IFileInfo::MODE_HIDDEN);
} }


/**
* @return bool
*/
public function isSystem() {
public function isSystem(): bool {
return (bool)($this->mode & IFileInfo::MODE_SYSTEM); return (bool)($this->mode & IFileInfo::MODE_SYSTEM);
} }


/**
* @return bool
*/
public function isArchived() {
public function isArchived(): bool {
return (bool)($this->mode & IFileInfo::MODE_ARCHIVE); return (bool)($this->mode & IFileInfo::MODE_ARCHIVE);
} }



+ 17
- 17
apps/files_external/3rdparty/icewind/smb/src/Wrapped/NotifyHandler.php View File

use Icewind\SMB\INotifyHandler; use Icewind\SMB\INotifyHandler;


class NotifyHandler implements INotifyHandler { class NotifyHandler implements INotifyHandler {
/**
* @var Connection
*/
/** @var Connection */
private $connection; private $connection;


/**
* @var string
*/
/** @var string */
private $path; private $path;


/** @var bool */
private $listening = true; private $listening = true;


// see error.h // see error.h
* @param Connection $connection * @param Connection $connection
* @param string $path * @param string $path
*/ */
public function __construct(Connection $connection, $path) {
public function __construct(Connection $connection, string $path) {
$this->connection = $connection; $this->connection = $connection;
$this->path = $path; $this->path = $path;
} }
* *
* @return Change[] * @return Change[]
*/ */
public function getChanges() {
public function getChanges(): array {
if (!$this->listening) { if (!$this->listening) {
return []; return [];
} }
stream_set_blocking($this->connection->getOutputStream(), 0);
stream_set_blocking($this->connection->getOutputStream(), false);
$lines = []; $lines = [];
while (($line = $this->connection->readLine())) { while (($line = $this->connection->readLine())) {
$this->checkForError($line); $this->checkForError($line);
$lines[] = $line; $lines[] = $line;
} }
stream_set_blocking($this->connection->getOutputStream(), 1);
stream_set_blocking($this->connection->getOutputStream(), true);
return array_values(array_filter(array_map([$this, 'parseChangeLine'], $lines))); return array_values(array_filter(array_map([$this, 'parseChangeLine'], $lines)));
} }


* *
* Note that this is a blocking process and will cause the process to block forever if not explicitly terminated * Note that this is a blocking process and will cause the process to block forever if not explicitly terminated
* *
* @param callable $callback
* @param callable(Change):?bool $callback
*/ */
public function listen($callback) {
public function listen(callable $callback): void {
if ($this->listening) { if ($this->listening) {
$this->connection->read(function ($line) use ($callback) {
$this->connection->read(function (string $line) use ($callback): bool {
$this->checkForError($line); $this->checkForError($line);
$change = $this->parseChangeLine($line); $change = $this->parseChangeLine($line);
if ($change) { if ($change) {
return $callback($change);
$result = $callback($change);
return $result === false ? false : true;
} else {
return true;
} }
}); });
} }
} }


private function parseChangeLine($line) {
private function parseChangeLine(string $line): ?Change {
$code = (int)substr($line, 0, 4); $code = (int)substr($line, 0, 4);
if ($code === 0) { if ($code === 0) {
return null; return null;
} }
} }


private function checkForError($line) {
private function checkForError(string $line): void {
if (substr($line, 0, 16) === 'notify returned ') { if (substr($line, 0, 16) === 'notify returned ') {
$error = substr($line, 16); $error = substr($line, 16);
throw Exception::fromMap(array_merge(self::EXCEPTION_MAP, Parser::EXCEPTION_MAP), $error, 'Notify is not supported with the used smb version'); throw Exception::fromMap(array_merge(self::EXCEPTION_MAP, Parser::EXCEPTION_MAP), $error, 'Notify is not supported with the used smb version');
} }
} }


public function stop() {
public function stop(): void {
$this->listening = false; $this->listening = false;
$this->connection->close(); $this->connection->close();
} }

+ 103
- 17
apps/files_external/3rdparty/icewind/smb/src/Wrapped/Parser.php View File



namespace Icewind\SMB\Wrapped; namespace Icewind\SMB\Wrapped;


use Icewind\SMB\ACL;
use Icewind\SMB\Exception\AccessDeniedException; use Icewind\SMB\Exception\AccessDeniedException;
use Icewind\SMB\Exception\AlreadyExistsException; use Icewind\SMB\Exception\AlreadyExistsException;
use Icewind\SMB\Exception\AuthenticationException; use Icewind\SMB\Exception\AuthenticationException;
*/ */
protected $timeZone; protected $timeZone;


/**
* @var string
*/
private $host;

// see error.h // see error.h
const EXCEPTION_MAP = [ const EXCEPTION_MAP = [
ErrorCodes::LogonFailure => AuthenticationException::class, ErrorCodes::LogonFailure => AuthenticationException::class,
/** /**
* @param string $timeZone * @param string $timeZone
*/ */
public function __construct($timeZone) {
public function __construct(string $timeZone) {
$this->timeZone = $timeZone; $this->timeZone = $timeZone;
} }


private function getErrorCode($line) {
private function getErrorCode(string $line): ?string {
$parts = explode(' ', $line); $parts = explode(' ', $line);
foreach ($parts as $part) { foreach ($parts as $part) {
if (substr($part, 0, 9) === 'NT_STATUS') { if (substr($part, 0, 9) === 'NT_STATUS') {
return $part; return $part;
} }
} }
return false;
return null;
} }


public function checkForError($output, $path) {
/**
* @param string[] $output
* @param string $path
* @return no-return
* @throws Exception
* @throws InvalidResourceException
* @throws NotFoundException
*/
public function checkForError(array $output, string $path): void {
if (strpos($output[0], 'does not exist')) { if (strpos($output[0], 'does not exist')) {
throw new NotFoundException($path); throw new NotFoundException($path);
} }
/** /**
* check if the first line holds a connection failure * check if the first line holds a connection failure
* *
* @param $line
* @param string $line
* @throws AuthenticationException * @throws AuthenticationException
* @throws InvalidHostException * @throws InvalidHostException
* @throws NoLoginServerException * @throws NoLoginServerException
* @throws AccessDeniedException * @throws AccessDeniedException
*/ */
public function checkConnectionError($line) {
public function checkConnectionError(string $line): void {
$line = rtrim($line, ')'); $line = rtrim($line, ')');
if (substr($line, -23) === ErrorCodes::LogonFailure) { if (substr($line, -23) === ErrorCodes::LogonFailure) {
throw new AuthenticationException('Invalid login'); throw new AuthenticationException('Invalid login');
} }
} }


public function parseMode($mode) {
public function parseMode(string $mode): int {
$result = 0; $result = 0;
foreach (self::MODE_STRINGS as $char => $val) { foreach (self::MODE_STRINGS as $char => $val) {
if (strpos($mode, $char) !== false) { if (strpos($mode, $char) !== false) {
return $result; return $result;
} }


public function parseStat($output) {
/**
* @param string[] $output
* @return array{"mtime": int, "mode": int, "size": int}
* @throws Exception
*/
public function parseStat(array $output): array {
$data = []; $data = [];
foreach ($output as $line) { foreach ($output as $line) {
// A line = explode statement may not fill all array elements // A line = explode statement may not fill all array elements
$data[$name] = $value; $data[$name] = $value;
} }
} }
$attributeStart = strpos($data['attributes'], '(');
if ($attributeStart === false) {
throw new Exception("Malformed state response from server");
}
return [ return [
'mtime' => strtotime($data['write_time']), 'mtime' => strtotime($data['write_time']),
'mode' => hexdec(substr($data['attributes'], strpos($data['attributes'], '(') + 1, -1)),
'mode' => hexdec(substr($data['attributes'], $attributeStart + 1, -1)),
'size' => isset($data['stream']) ? (int)(explode(' ', $data['stream'])[1]) : 0 'size' => isset($data['stream']) ? (int)(explode(' ', $data['stream'])[1]) : 0
]; ];
} }


public function parseDir($output, $basePath, callable $aclCallback) {
/**
* @param string[] $output
* @param string $basePath
* @param callable(string):ACL[] $aclCallback
* @return FileInfo[]
*/
public function parseDir(array $output, string $basePath, callable $aclCallback): array {
//last line is used space //last line is used space
array_pop($output); array_pop($output);
$regex = '/^\s*(.*?)\s\s\s\s+(?:([NDHARS]*)\s+)?([0-9]+)\s+(.*)$/'; $regex = '/^\s*(.*?)\s\s\s\s+(?:([NDHARS]*)\s+)?([0-9]+)\s+(.*)$/';
$mode = $this->parseMode($mode); $mode = $this->parseMode($mode);
$time = strtotime($time . ' ' . $this->timeZone); $time = strtotime($time . ' ' . $this->timeZone);
$path = $basePath . '/' . $name; $path = $basePath . '/' . $name;
$content[] = new FileInfo($path, $name, $size, $time, $mode, function () use ($aclCallback, $path) {
$content[] = new FileInfo($path, $name, (int)$size, $time, $mode, function () use ($aclCallback, $path): array {
return $aclCallback($path); return $aclCallback($path);
}); });
} }
return $content; return $content;
} }


public function parseListShares($output) {
/**
* @param string[] $output
* @return array<string, string>
*/
public function parseListShares(array $output): array {
$shareNames = []; $shareNames = [];
foreach ($output as $line) { foreach ($output as $line) {
if (strpos($line, '|')) { if (strpos($line, '|')) {
} }
return $shareNames; return $shareNames;
} }

/**
* @param string[] $rawAcls
* @return ACL[]
*/
public function parseACLs(array $rawAcls): array {
$acls = [];
foreach ($rawAcls as $acl) {
if (strpos($acl, ':') === false) {
continue;
}
[$type, $acl] = explode(':', $acl, 2);
if ($type !== 'ACL') {
continue;
}
[$user, $permissions] = explode(':', $acl, 2);
[$type, $flags, $mask] = explode('/', $permissions);

$type = $type === 'ALLOWED' ? ACL::TYPE_ALLOW : ACL::TYPE_DENY;

$flagsInt = 0;
foreach (explode('|', $flags) as $flagString) {
if ($flagString === 'OI') {
$flagsInt += ACL::FLAG_OBJECT_INHERIT;
} elseif ($flagString === 'CI') {
$flagsInt += ACL::FLAG_CONTAINER_INHERIT;
}
}

if (substr($mask, 0, 2) === '0x') {
$maskInt = hexdec($mask);
} else {
$maskInt = 0;
foreach (explode('|', $mask) as $maskString) {
if ($maskString === 'R') {
$maskInt += ACL::MASK_READ;
} elseif ($maskString === 'W') {
$maskInt += ACL::MASK_WRITE;
} elseif ($maskString === 'X') {
$maskInt += ACL::MASK_EXECUTE;
} elseif ($maskString === 'D') {
$maskInt += ACL::MASK_DELETE;
} elseif ($maskString === 'READ') {
$maskInt += ACL::MASK_READ + ACL::MASK_EXECUTE;
} elseif ($maskString === 'CHANGE') {
$maskInt += ACL::MASK_READ + ACL::MASK_EXECUTE + ACL::MASK_WRITE + ACL::MASK_DELETE;
} elseif ($maskString === 'FULL') {
$maskInt += ACL::MASK_READ + ACL::MASK_EXECUTE + ACL::MASK_WRITE + ACL::MASK_DELETE;
}
}
}

if (isset($acls[$user])) {
$existing = $acls[$user];
$maskInt += $existing->getMask();
}
$acls[$user] = new ACL($type, $flagsInt, $maskInt);
}

ksort($acls);

return $acls;
}
} }

+ 54
- 20
apps/files_external/3rdparty/icewind/smb/src/Wrapped/RawConnection.php View File

* $pipes[4] holds the stream for writing files * $pipes[4] holds the stream for writing files
* $pipes[5] holds the stream for reading files * $pipes[5] holds the stream for reading files
*/ */
private $pipes;
private $pipes = [];


/** /**
* @var resource $process
* @var resource|null $process
*/ */
private $process; private $process;


*/ */
private $authStream = null; private $authStream = null;


private $connected = false;

public function __construct($command, array $env = []) {
/**
* @param string $command
* @param array<string, string> $env
*/
public function __construct(string $command, array $env = []) {
$this->command = $command; $this->command = $command;
$this->env = $env; $this->env = $env;
} }


/** /**
* @throws ConnectException * @throws ConnectException
* @psalm-assert resource $this->process
*/ */
public function connect() {
public function connect(): void {
if (is_null($this->getAuthStream())) { if (is_null($this->getAuthStream())) {
throw new ConnectException('Authentication not set before connecting'); throw new ConnectException('Authentication not set before connecting');
} }
if (!$this->isValid()) { if (!$this->isValid()) {
throw new ConnectionException(); throw new ConnectionException();
} }
$this->connected = true;
} }


/** /**
* check if the connection is still active * check if the connection is still active
* *
* @return bool * @return bool
* @psalm-assert-if-true resource $this->process
*/ */
public function isValid() {
public function isValid(): bool {
if (is_resource($this->process)) { if (is_resource($this->process)) {
$status = proc_get_status($this->process); $status = proc_get_status($this->process);
return $status['running'];
return (bool)$status['running'];
} else { } else {
return false; return false;
} }
* send input to the process * send input to the process
* *
* @param string $input * @param string $input
* @return int|bool
*/ */
public function write($input) {
fwrite($this->getInputStream(), $input);
public function write(string $input) {
$result = @fwrite($this->getInputStream(), $input);
fflush($this->getInputStream()); fflush($this->getInputStream());
return $result;
} }


/** /**
/** /**
* read a line of output * read a line of output
* *
* @return string
* @return string|false
*/ */
public function readError() { public function readError() {
return trim(stream_get_line($this->getErrorStream(), 4086));
$line = stream_get_line($this->getErrorStream(), 4086);
return $line !== false ? trim($line) : false;
} }


/** /**
* get all output until the process closes * get all output until the process closes
* *
* @return array
* @return string[]
*/ */
public function readAll() {
public function readAll(): array {
$output = []; $output = [];
while ($line = $this->readLine()) { while ($line = $this->readLine()) {
$output[] = $line; $output[] = $line;
return $output; return $output;
} }


/**
* @return resource
*/
public function getInputStream() { public function getInputStream() {
return $this->pipes[0]; return $this->pipes[0];
} }


/**
* @return resource
*/
public function getOutputStream() { public function getOutputStream() {
return $this->pipes[1]; return $this->pipes[1];
} }


/**
* @return resource
*/
public function getErrorStream() { public function getErrorStream() {
return $this->pipes[2]; return $this->pipes[2];
} }


/**
* @return resource|null
*/
public function getAuthStream() { public function getAuthStream() {
return $this->authStream; return $this->authStream;
} }


/**
* @return resource
*/
public function getFileInputStream() { public function getFileInputStream() {
return $this->pipes[4]; return $this->pipes[4];
} }


/**
* @return resource
*/
public function getFileOutputStream() { public function getFileOutputStream() {
return $this->pipes[5]; return $this->pipes[5];
} }


public function writeAuthentication($user, $password) {
$auth = ($password === false)
/**
* @param string|null $user
* @param string|null $password
* @psalm-assert resource $this->authStream
*/
public function writeAuthentication(?string $user, ?string $password): void {
$auth = ($password === null)
? "username=$user" ? "username=$user"
: "username=$user\npassword=$password\n"; : "username=$user\npassword=$password\n";


$this->authStream = fopen('php://temp', 'w+'); $this->authStream = fopen('php://temp', 'w+');
fwrite($this->getAuthStream(), $auth);
fwrite($this->authStream, $auth);
} }


public function close($terminate = true) {
/**
* @param bool $terminate
* @psalm-assert null $this->process
*/
public function close(bool $terminate = true): void {
if (!is_resource($this->process)) { if (!is_resource($this->process)) {
return; return;
} }
proc_terminate($this->process); proc_terminate($this->process);
} }
proc_close($this->process); proc_close($this->process);
$this->process = null;
} }


public function reconnect() {
public function reconnect(): void {
$this->close(); $this->close();
$this->connect(); $this->connect();
} }

+ 22
- 9
apps/files_external/3rdparty/icewind/smb/src/Wrapped/Server.php View File

use Icewind\SMB\Exception\AuthenticationException; use Icewind\SMB\Exception\AuthenticationException;
use Icewind\SMB\Exception\ConnectException; use Icewind\SMB\Exception\ConnectException;
use Icewind\SMB\Exception\ConnectionException; use Icewind\SMB\Exception\ConnectionException;
use Icewind\SMB\Exception\ConnectionRefusedException;
use Icewind\SMB\Exception\Exception;
use Icewind\SMB\Exception\InvalidHostException; use Icewind\SMB\Exception\InvalidHostException;
use Icewind\SMB\IShare; use Icewind\SMB\IShare;
use Icewind\SMB\ISystem; use Icewind\SMB\ISystem;
* @param ISystem $system * @param ISystem $system
* @return bool * @return bool
*/ */
public static function available(ISystem $system) {
return $system->getSmbclientPath();
public static function available(ISystem $system): bool {
return $system->getSmbclientPath() !== null;
} }


private function getAuthFileArgument() {
private function getAuthFileArgument(): string {
if ($this->getAuth()->getUsername()) { if ($this->getAuth()->getUsername()) {
return '--authentication-file=' . $this->system->getFD(3); return '--authentication-file=' . $this->system->getFD(3);
} else { } else {
* @throws InvalidHostException * @throws InvalidHostException
* @throws ConnectException * @throws ConnectException
*/ */
public function listShares() {
public function listShares(): array {
$maxProtocol = $this->options->getMaxProtocol();
$minProtocol = $this->options->getMinProtocol();
$smbClient = $this->system->getSmbclientPath();
if ($smbClient === null) {
throw new Exception("Backend not available");
}
$command = sprintf( $command = sprintf(
'%s %s %s -L %s',
$this->system->getSmbclientPath(),
'%s %s %s %s %s -L %s',
$smbClient,
$this->getAuthFileArgument(), $this->getAuthFileArgument(),
$this->getAuth()->getExtraCommandLineArguments(), $this->getAuth()->getExtraCommandLineArguments(),
$maxProtocol ? "--option='client max protocol=" . $maxProtocol . "'" : "",
$minProtocol ? "--option='client min protocol=" . $minProtocol . "'" : "",
escapeshellarg('//' . $this->getHost()) escapeshellarg('//' . $this->getHost())
); );
$connection = new RawConnection($command); $connection = new RawConnection($command);
$connection->writeAuthentication($this->getAuth()->getUsername(), $this->getAuth()->getPassword()); $connection->writeAuthentication($this->getAuth()->getUsername(), $this->getAuth()->getPassword());
$connection->connect(); $connection->connect();
if (!$connection->isValid()) { if (!$connection->isValid()) {
throw new ConnectionException($connection->readLine());
throw new ConnectionException((string)$connection->readLine());
} }


$parser = new Parser($this->timezoneProvider);
$parser = new Parser($this->timezoneProvider->get($this->host));


$output = $connection->readAll(); $output = $connection->readAll();
if (isset($output[0])) { if (isset($output[0])) {
if (isset($output[0])) { if (isset($output[0])) {
$parser->checkConnectionError($output[0]); $parser->checkConnectionError($output[0]);
} }
if (count($output) === 0) {
throw new ConnectionRefusedException();
}


$shareNames = $parser->parseListShares($output); $shareNames = $parser->parseListShares($output);


* @param string $name * @param string $name
* @return IShare * @return IShare
*/ */
public function getShare($name) {
public function getShare(string $name): IShare {
return new Share($this, $name, $this->system); return new Share($this, $name, $this->system);
} }
} }

+ 105
- 121
apps/files_external/3rdparty/icewind/smb/src/Wrapped/Share.php View File



use Icewind\SMB\AbstractShare; use Icewind\SMB\AbstractShare;
use Icewind\SMB\ACL; use Icewind\SMB\ACL;
use Icewind\SMB\Exception\AlreadyExistsException;
use Icewind\SMB\Exception\AuthenticationException;
use Icewind\SMB\Exception\ConnectException;
use Icewind\SMB\Exception\ConnectionException; use Icewind\SMB\Exception\ConnectionException;
use Icewind\SMB\Exception\DependencyException; use Icewind\SMB\Exception\DependencyException;
use Icewind\SMB\Exception\Exception;
use Icewind\SMB\Exception\FileInUseException; use Icewind\SMB\Exception\FileInUseException;
use Icewind\SMB\Exception\InvalidHostException;
use Icewind\SMB\Exception\InvalidTypeException; use Icewind\SMB\Exception\InvalidTypeException;
use Icewind\SMB\Exception\NotFoundException; use Icewind\SMB\Exception\NotFoundException;
use Icewind\SMB\Exception\InvalidRequestException; use Icewind\SMB\Exception\InvalidRequestException;
private $name; private $name;


/** /**
* @var Connection $connection
* @var Connection|null $connection
*/ */
public $connection;
public $connection = null;


/** /**
* @var Parser * @var Parser
* @param string $name * @param string $name
* @param ISystem $system * @param ISystem $system
*/ */
public function __construct(IServer $server, $name, ISystem $system) {
public function __construct(IServer $server, string $name, ISystem $system) {
parent::__construct(); parent::__construct();
$this->server = $server; $this->server = $server;
$this->name = $name; $this->name = $name;
$this->parser = new Parser($server->getTimeZone()); $this->parser = new Parser($server->getTimeZone());
} }


private function getAuthFileArgument() {
private function getAuthFileArgument(): string {
if ($this->server->getAuth()->getUsername()) { if ($this->server->getAuth()->getUsername()) {
return '--authentication-file=' . $this->system->getFD(3); return '--authentication-file=' . $this->system->getFD(3);
} else { } else {
} }
} }


protected function getConnection() {
protected function getConnection(): Connection {
$maxProtocol = $this->server->getOptions()->getMaxProtocol();
$minProtocol = $this->server->getOptions()->getMinProtocol();
$smbClient = $this->system->getSmbclientPath();
$stdBuf = $this->system->getStdBufPath();
if ($smbClient === null) {
throw new Exception("Backend not available");
}
$command = sprintf( $command = sprintf(
'%s %s%s -t %s %s %s %s',
'%s %s%s -t %s %s %s %s %s %s',
self::EXEC_CMD, self::EXEC_CMD,
$this->system->getStdBufPath() ? $this->system->getStdBufPath() . ' -o0 ' : '',
$this->system->getSmbclientPath(),
$stdBuf ? $stdBuf . ' -o0 ' : '',
$smbClient,
$this->server->getOptions()->getTimeout(), $this->server->getOptions()->getTimeout(),
$this->getAuthFileArgument(), $this->getAuthFileArgument(),
$this->server->getAuth()->getExtraCommandLineArguments(), $this->server->getAuth()->getExtraCommandLineArguments(),
$maxProtocol ? "--option='client max protocol=" . $maxProtocol . "'" : "",
$minProtocol ? "--option='client min protocol=" . $minProtocol . "'" : "",
escapeshellarg('//' . $this->server->getHost() . '/' . $this->name) escapeshellarg('//' . $this->server->getHost() . '/' . $this->name)
); );
$connection = new Connection($command, $this->parser); $connection = new Connection($command, $this->parser);
$connection->writeAuthentication($this->server->getAuth()->getUsername(), $this->server->getAuth()->getPassword()); $connection->writeAuthentication($this->server->getAuth()->getUsername(), $this->server->getAuth()->getPassword());
$connection->connect(); $connection->connect();
if (!$connection->isValid()) { if (!$connection->isValid()) {
throw new ConnectionException($connection->readLine());
throw new ConnectionException((string)$connection->readLine());
} }
// some versions of smbclient add a help message in first of the first prompt // some versions of smbclient add a help message in first of the first prompt
$connection->clearTillPrompt(); $connection->clearTillPrompt();
} }


/** /**
* @throws \Icewind\SMB\Exception\ConnectionException
* @throws \Icewind\SMB\Exception\AuthenticationException
* @throws \Icewind\SMB\Exception\InvalidHostException
* @throws ConnectionException
* @throws AuthenticationException
* @throws InvalidHostException
* @psalm-assert Connection $this->connection
*/ */
protected function connect() {
protected function connect(): Connection {
if ($this->connection and $this->connection->isValid()) { if ($this->connection and $this->connection->isValid()) {
return;
return $this->connection;
} }
$this->connection = $this->getConnection(); $this->connection = $this->getConnection();
return $this->connection;
} }


protected function reconnect() {
$this->connection->reconnect();
if (!$this->connection->isValid()) {
throw new ConnectionException();
/**
* @throws ConnectionException
* @throws AuthenticationException
* @throws InvalidHostException
* @psalm-assert Connection $this->connection
*/
protected function reconnect(): void {
if ($this->connection === null) {
$this->connect();
} else {
$this->connection->reconnect();
if (!$this->connection->isValid()) {
throw new ConnectionException();
}
} }
} }


* *
* @return string * @return string
*/ */
public function getName() {
public function getName(): string {
return $this->name; return $this->name;
} }


protected function simpleCommand($command, $path) {
protected function simpleCommand(string $command, string $path): bool {
$escapedPath = $this->escapePath($path); $escapedPath = $this->escapePath($path);
$cmd = $command . ' ' . $escapedPath; $cmd = $command . ' ' . $escapedPath;
$output = $this->execute($cmd); $output = $this->execute($cmd);
/** /**
* List the content of a remote folder * List the content of a remote folder
* *
* @param $path
* @return \Icewind\SMB\IFileInfo[]
* @param string $path
* @return IFileInfo[]
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\InvalidTypeException
* @throws NotFoundException
* @throws InvalidTypeException
*/ */
public function dir($path) {
public function dir(string $path): array {
$escapedPath = $this->escapePath($path); $escapedPath = $this->escapePath($path);
$output = $this->execute('cd ' . $escapedPath); $output = $this->execute('cd ' . $escapedPath);
//check output for errors //check output for errors


$this->execute('cd /'); $this->execute('cd /');


return $this->parser->parseDir($output, $path, function ($path) {
return $this->parser->parseDir($output, $path, function (string $path) {
return $this->getAcls($path); return $this->getAcls($path);
}); });
} }


/** /**
* @param string $path * @param string $path
* @return \Icewind\SMB\IFileInfo
* @return IFileInfo
*/ */
public function stat($path) {
public function stat(string $path): IFileInfo {
// some windows server setups don't seem to like the allinfo command // some windows server setups don't seem to like the allinfo command
// use the dir command instead to get the file info where possible // use the dir command instead to get the file info where possible
if ($path !== "" && $path !== "/") { if ($path !== "" && $path !== "/") {
* @param string $path * @param string $path
* @return bool * @return bool
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\AlreadyExistsException
* @throws NotFoundException
* @throws AlreadyExistsException
*/ */
public function mkdir($path) {
public function mkdir(string $path): bool {
return $this->simpleCommand('mkdir', $path); return $this->simpleCommand('mkdir', $path);
} }


* @param string $path * @param string $path
* @return bool * @return bool
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\InvalidTypeException
* @throws NotFoundException
* @throws InvalidTypeException
*/ */
public function rmdir($path) {
public function rmdir(string $path): bool {
return $this->simpleCommand('rmdir', $path); return $this->simpleCommand('rmdir', $path);
} }


* @throws NotFoundException * @throws NotFoundException
* @throws \Exception * @throws \Exception
*/ */
public function del($path, $secondTry = false) {
public function del(string $path, bool $secondTry = false): bool {
//del return a file not found error when trying to delete a folder //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 //we catch it so we can check if $path doesn't exist or is of invalid type
try { try {
* @param string $to * @param string $to
* @return bool * @return bool
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\AlreadyExistsException
* @throws NotFoundException
* @throws AlreadyExistsException
*/ */
public function rename($from, $to) {
public function rename(string $from, string $to): bool {
$path1 = $this->escapePath($from); $path1 = $this->escapePath($from);
$path2 = $this->escapePath($to); $path2 = $this->escapePath($to);
$output = $this->execute('rename ' . $path1 . ' ' . $path2); $output = $this->execute('rename ' . $path1 . ' ' . $path2);
* @param string $target remove file * @param string $target remove file
* @return bool * @return bool
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\InvalidTypeException
* @throws NotFoundException
* @throws InvalidTypeException
*/ */
public function put($source, $target) {
public function put(string $source, string $target): bool {
$path1 = $this->escapeLocalPath($source); //first path is local, needs different escaping $path1 = $this->escapeLocalPath($source); //first path is local, needs different escaping
$path2 = $this->escapePath($target); $path2 = $this->escapePath($target);
$output = $this->execute('put ' . $path1 . ' ' . $path2); $output = $this->execute('put ' . $path1 . ' ' . $path2);
* @param string $target local file * @param string $target local file
* @return bool * @return bool
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\InvalidTypeException
* @throws NotFoundException
* @throws InvalidTypeException
*/ */
public function get($source, $target) {
public function get(string $source, string $target): bool {
$path1 = $this->escapePath($source); $path1 = $this->escapePath($source);
$path2 = $this->escapeLocalPath($target); //second path is local, needs different escaping $path2 = $this->escapeLocalPath($target); //second path is local, needs different escaping
$output = $this->execute('get ' . $path1 . ' ' . $path2); $output = $this->execute('get ' . $path1 . ' ' . $path2);
* @param string $source * @param string $source
* @return resource a read only stream with the contents of the remote file * @return resource a read only stream with the contents of the remote file
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\InvalidTypeException
* @throws NotFoundException
* @throws InvalidTypeException
*/ */
public function read($source) {
public function read(string $source) {
$source = $this->escapePath($source); $source = $this->escapePath($source);
// since returned stream is closed by the caller we need to create a new instance // 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 // since we can't re-use the same file descriptor over multiple calls
* @param string $target * @param string $target
* @return resource a write only stream to upload a remote file * @return resource a write only stream to upload a remote file
* *
* @throws \Icewind\SMB\Exception\NotFoundException
* @throws \Icewind\SMB\Exception\InvalidTypeException
* @throws NotFoundException
* @throws InvalidTypeException
*/ */
public function write($target) {
public function write(string $target) {
$target = $this->escapePath($target); $target = $this->escapePath($target);
// since returned stream is closed by the caller we need to create a new instance // 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 // since we can't re-use the same file descriptor over multiple calls


// use a close callback to ensure the upload is finished before continuing // use a close callback to ensure the upload is finished before continuing
// this also serves as a way to keep the connection in scope // this also serves as a way to keep the connection in scope
return CallbackWrapper::wrap($fh, null, null, function () use ($connection, $target) {
$stream = CallbackWrapper::wrap($fh, null, null, function () use ($connection) {
$connection->close(false); // dont terminate, give the upload some time $connection->close(false); // dont terminate, give the upload some time
}); });
if (is_resource($stream)) {
return $stream;
} else {
throw new InvalidRequestException($target);
}
} }


/** /**
* *
* @param string $target * @param string $target
* *
* @throws \Icewind\SMB\Exception\DependencyException
* @throws DependencyException
*/ */
public function append($target) {
public function append(string $target) {
throw new DependencyException('php-libsmbclient is required for append'); throw new DependencyException('php-libsmbclient is required for append');
} }


* @param int $mode a combination of FileInfo::MODE_READONLY, FileInfo::MODE_ARCHIVE, FileInfo::MODE_SYSTEM and FileInfo::MODE_HIDDEN, FileInfo::NORMAL * @param int $mode a combination of FileInfo::MODE_READONLY, FileInfo::MODE_ARCHIVE, FileInfo::MODE_SYSTEM and FileInfo::MODE_HIDDEN, FileInfo::NORMAL
* @return mixed * @return mixed
*/ */
public function setMode($path, $mode) {
public function setMode(string $path, int $mode) {
$modeString = ''; $modeString = '';
foreach (self::MODE_MAP as $modeByte => $string) { foreach (self::MODE_MAP as $modeByte => $string) {
if ($mode & $modeByte) { if ($mode & $modeByte) {
* @throws ConnectionException * @throws ConnectionException
* @throws DependencyException * @throws DependencyException
*/ */
public function notify($path) {
public function notify(string $path): INotifyHandler {
if (!$this->system->getStdBufPath()) { //stdbuf is required to disable smbclient's output buffering if (!$this->system->getStdBufPath()) { //stdbuf is required to disable smbclient's output buffering
throw new DependencyException('stdbuf is required for usage of the notify command'); throw new DependencyException('stdbuf is required for usage of the notify command');
} }


/** /**
* @param string $command * @param string $command
* @return array
* @return string[]
*/ */
protected function execute($command) {
$this->connect();
$this->connection->write($command . PHP_EOL);
return $this->connection->read();
protected function execute(string $command): array {
$this->connect()->write($command . PHP_EOL);
return $this->connect()->read();
} }


/** /**
* @param string $path * @param string $path
* *
* @return bool * @return bool
* @throws \Icewind\SMB\Exception\AlreadyExistsException
* @throws AlreadyExistsException
* @throws \Icewind\SMB\Exception\AccessDeniedException * @throws \Icewind\SMB\Exception\AccessDeniedException
* @throws \Icewind\SMB\Exception\NotEmptyException * @throws \Icewind\SMB\Exception\NotEmptyException
* @throws \Icewind\SMB\Exception\InvalidTypeException
* @throws InvalidTypeException
* @throws \Icewind\SMB\Exception\Exception * @throws \Icewind\SMB\Exception\Exception
* @throws NotFoundException * @throws NotFoundException
*/ */
protected function parseOutput($lines, $path = '') {
protected function parseOutput(array $lines, string $path = ''): bool {
if (count($lines) === 0) { if (count($lines) === 0) {
return true; return true;
} else { } else {
$this->parser->checkForError($lines, $path); $this->parser->checkForError($lines, $path);
return false;
} }
} }


* @param string $string * @param string $string
* @return string * @return string
*/ */
protected function escape($string) {
protected function escape(string $string): string {
return escapeshellarg($string); return escapeshellarg($string);
} }


* @param string $path * @param string $path
* @return string * @return string
*/ */
protected function escapePath($path) {
protected function escapePath(string $path): string {
$this->verifyPath($path); $this->verifyPath($path);
if ($path === '/') { if ($path === '/') {
$path = ''; $path = '';
* @param string $path * @param string $path
* @return string * @return string
*/ */
protected function escapeLocalPath($path) {
protected function escapeLocalPath(string $path): string {
$path = str_replace('"', '\"', $path); $path = str_replace('"', '\"', $path);
return '"' . $path . '"'; return '"' . $path . '"';
} }


protected function getAcls($path) {
/**
* @param string $path
* @return ACL[]
* @throws ConnectionException
* @throws ConnectException
*/
protected function getAcls(string $path): array {
$commandPath = $this->system->getSmbcAclsPath(); $commandPath = $this->system->getSmbcAclsPath();
if (!$commandPath) { if (!$commandPath) {
return []; return [];
$connection->writeAuthentication($this->server->getAuth()->getUsername(), $this->server->getAuth()->getPassword()); $connection->writeAuthentication($this->server->getAuth()->getUsername(), $this->server->getAuth()->getPassword());
$connection->connect(); $connection->connect();
if (!$connection->isValid()) { if (!$connection->isValid()) {
throw new ConnectionException($connection->readLine());
throw new ConnectionException((string)$connection->readLine());
} }


$rawAcls = $connection->readAll(); $rawAcls = $connection->readAll();

$acls = [];
foreach ($rawAcls as $acl) {
[$type, $acl] = explode(':', $acl, 2);
if ($type !== 'ACL') {
continue;
}
[$user, $permissions] = explode(':', $acl, 2);
[$type, $flags, $mask] = explode('/', $permissions);

$type = $type === 'ALLOWED' ? ACL::TYPE_ALLOW : ACL::TYPE_DENY;

$flagsInt = 0;
foreach (explode('|', $flags) as $flagString) {
if ($flagString === 'OI') {
$flagsInt += ACL::FLAG_OBJECT_INHERIT;
} elseif ($flagString === 'CI') {
$flagsInt += ACL::FLAG_CONTAINER_INHERIT;
}
}

if (substr($mask, 0, 2) === '0x') {
$maskInt = hexdec($mask);
} else {
$maskInt = 0;
foreach (explode('|', $mask) as $maskString) {
if ($maskString === 'R') {
$maskInt += ACL::MASK_READ;
} elseif ($maskString === 'W') {
$maskInt += ACL::MASK_WRITE;
} elseif ($maskString === 'X') {
$maskInt += ACL::MASK_EXECUTE;
} elseif ($maskString === 'D') {
$maskInt += ACL::MASK_DELETE;
} elseif ($maskString === 'READ') {
$maskInt += ACL::MASK_READ + ACL::MASK_EXECUTE;
} elseif ($maskString === 'CHANGE') {
$maskInt += ACL::MASK_READ + ACL::MASK_EXECUTE + ACL::MASK_WRITE + ACL::MASK_DELETE;
} elseif ($maskString === 'FULL') {
$maskInt += ACL::MASK_READ + ACL::MASK_EXECUTE + ACL::MASK_WRITE + ACL::MASK_DELETE;
}
}
}

if (isset($acls[$user])) {
$existing = $acls[$user];
$maskInt += $existing->getMask();
}
$acls[$user] = new ACL($type, $flagsInt, $maskInt);
}

return $acls;
return $this->parser->parseACLs($rawAcls);
} }


public function getServer(): IServer { public function getServer(): IServer {

+ 3
- 0
apps/files_external/3rdparty/icewind/streams/.gitignore View File

.idea .idea
vendor vendor
composer.lock composer.lock
build
example.php
*.cache

+ 0
- 24
apps/files_external/3rdparty/icewind/streams/.travis.yml View File

language: php
php:
- 5.4
- 5.5
- 5.6
- 7.0
- 7.1
- 7.2

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

+ 3
- 4
apps/files_external/3rdparty/icewind/streams/README.md View File

# Streams # # 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)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/icewind1991/Streams/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/icewind1991/Streams/?branch=master)
[![CI](https://github.com/icewind1991/Streams/actions/workflows/ci.yaml/badge.svg)](https://github.com/icewind1991/Streams/actions/workflows/ci.yaml)
[![codecov](https://codecov.io/gh/icewind1991/Streams/branch/master/graph/badge.svg?token=bfPcAdGAaq)](https://codecov.io/gh/icewind1991/Streams)


Generic stream wrappers for php. Generic stream wrappers for php.


The callbacks are passed in the stream context along with the source stream 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) and can be any valid [php callable](http://php.net/manual/en/language.types.callable.php)


###Example###
### Example ###
```php ```php
<?php <?php



+ 17
- 12
apps/files_external/3rdparty/icewind/streams/composer.json View File

{ {
"name" : "icewind/streams",
"description" : "A set of generic stream wrappers",
"license" : "MIT",
"authors" : [
"name": "icewind/streams",
"description": "A set of generic stream wrappers",
"license": "MIT",
"authors": [
{ {
"name" : "Robin Appelman",
"name": "Robin Appelman",
"email": "icewind@owncloud.com" "email": "icewind@owncloud.com"
} }
], ],
"require" : {
"php": ">=5.3"
"require": {
"php": ">=7.1"
}, },
"require-dev" : {
"satooshi/php-coveralls": "v1.0.0",
"phpunit/phpunit": "^4.8"
"require-dev": {
"phpunit/phpunit": "^9",
"friendsofphp/php-cs-fixer": "^2",
"phpstan/phpstan": "^0.12"
}, },
"autoload" : {
"autoload": {
"psr-4": { "psr-4": {
"Icewind\\Streams\\Tests\\": "tests/",
"Icewind\\Streams\\": "src/" "Icewind\\Streams\\": "src/"
} }
},
"autoload-dev": {
"psr-4": {
"Icewind\\Streams\\Tests\\": "tests/"
}
} }
} }

+ 22
- 24
apps/files_external/3rdparty/icewind/streams/src/CallbackWrapper.php View File

*/ */
class CallbackWrapper extends Wrapper { class CallbackWrapper extends Wrapper {
/** /**
* @var callable
* @var callable|null
*/ */
protected $readCallback; protected $readCallback;


/** /**
* @var callable
* @var callable|null
*/ */
protected $writeCallback; protected $writeCallback;


/** /**
* @var callable
* @var callable|null
*/ */
protected $closeCallback; protected $closeCallback;


/** /**
* @var callable
* @var callable|null
*/ */
protected $readDirCallBack; protected $readDirCallBack;


/** /**
* @var callable
* @var callable|null
*/ */
protected $preCloseCallback; protected $preCloseCallback;


* Wraps a stream with the provided callbacks * Wraps a stream with the provided callbacks
* *
* @param resource $source * @param resource $source
* @param callable $read (optional)
* @param callable $write (optional)
* @param callable $close (optional)
* @param callable $readDir (optional)
* @return resource
* @param callable|null $read (optional)
* @param callable|null $write (optional)
* @param callable|null $close (optional)
* @param callable|null $readDir (optional)
* @param callable|null $preClose (optional)
* @return resource|bool
* *
* @throws \BadMethodCallException
*/ */
public static function wrap($source, $read = null, $write = null, $close = null, $readDir = null, $preClose = null) { public static function wrap($source, $read = null, $write = null, $close = null, $readDir = null, $preClose = null) {
$context = stream_context_create(array(
'callback' => array(
'source' => $source,
'read' => $read,
'write' => $write,
'close' => $close,
'readDir' => $readDir,
'preClose' => $preClose,
)
));
return Wrapper::wrapSource($source, $context, 'callback', '\Icewind\Streams\CallbackWrapper');
$context = [
'source' => $source,
'read' => $read,
'write' => $write,
'close' => $close,
'readDir' => $readDir,
'preClose' => $preClose,
];
return self::wrapSource($source, $context);
} }


protected function open() { protected function open() {
$context = $this->loadContext('callback');
$context = $this->loadContext();


$this->readCallback = $context['read']; $this->readCallback = $context['read'];
$this->writeCallback = $context['write']; $this->writeCallback = $context['write'];


public function stream_close() { public function stream_close() {
if (is_callable($this->preCloseCallback)) { if (is_callable($this->preCloseCallback)) {
call_user_func($this->preCloseCallback, $this->loadContext('callback')['source']);
call_user_func($this->preCloseCallback, $this->source);
// prevent further calls by potential PHP 7 GC ghosts // prevent further calls by potential PHP 7 GC ghosts
$this->preCloseCallback = null; $this->preCloseCallback = null;
} }

+ 6
- 9
apps/files_external/3rdparty/icewind/streams/src/CountWrapper.php View File

* *
* @param resource $source * @param resource $source
* @param callable $callback * @param callable $callback
* @return resource
* @return resource|bool
* *
* @throws \BadMethodCallException * @throws \BadMethodCallException
*/ */
if (!is_callable($callback)) { if (!is_callable($callback)) {
throw new \InvalidArgumentException('Invalid or missing callback'); throw new \InvalidArgumentException('Invalid or missing callback');
} }
$context = stream_context_create(array(
'count' => array(
'source' => $source,
'callback' => $callback
)
));
return Wrapper::wrapSource($source, $context, 'callback', '\Icewind\Streams\CountWrapper');
return self::wrapSource($source, [
'source' => $source,
'callback' => $callback
]);
} }


protected function open() { protected function open() {
$context = $this->loadContext('count');
$context = $this->loadContext();
$this->callback = $context['callback']; $this->callback = $context['callback'];
return true; return true;
} }

+ 1
- 1
apps/files_external/3rdparty/icewind/streams/src/Directory.php View File

public function dir_opendir($path, $options); public function dir_opendir($path, $options);


/** /**
* @return string
* @return string|bool
*/ */
public function dir_readdir(); public function dir_readdir();



+ 7
- 10
apps/files_external/3rdparty/icewind/streams/src/DirectoryFilter.php View File

* @return bool * @return bool
*/ */
public function dir_opendir($path, $options) { public function dir_opendir($path, $options) {
$context = $this->loadContext('filter');
$context = $this->loadContext();
$this->filter = $context['filter']; $this->filter = $context['filter'];
return true; return true;
} }
public function dir_readdir() { public function dir_readdir() {
$file = readdir($this->source); $file = readdir($this->source);
$filter = $this->filter; $filter = $this->filter;
// keep reading untill we have an accepted entry or we're at the end of the folder
// keep reading until we have an accepted entry or we're at the end of the folder
while ($file !== false && $filter($file) === false) { while ($file !== false && $filter($file) === false) {
$file = readdir($this->source); $file = readdir($this->source);
} }
/** /**
* @param resource $source * @param resource $source
* @param callable $filter * @param callable $filter
* @return resource
* @return resource|bool
*/ */
public static function wrap($source, callable $filter) { public static function wrap($source, callable $filter) {
$options = array(
'filter' => array(
'source' => $source,
'filter' => $filter
)
);
return self::wrapWithOptions($options, '\Icewind\Streams\DirectoryFilter');
return self::wrapSource($source, [
'source' => $source,
'filter' => $filter
]);
} }
} }

+ 4
- 45
apps/files_external/3rdparty/icewind/streams/src/DirectoryWrapper.php View File



namespace Icewind\Streams; namespace Icewind\Streams;


class DirectoryWrapper implements Directory {
/**
* @var resource
*/
public $context;

/**
* @var resource
*/
protected $source;

/**
* Load the source from the stream context and return the context options
*
* @param string $name
* @return array
* @throws \Exception
*/
protected function loadContext($name) {
$context = stream_context_get_options($this->context);
if (isset($context[$name])) {
$context = $context[$name];
} else {
throw new \BadMethodCallException('Invalid context, "' . $name . '" options not set');
}
if (isset($context['source']) and is_resource($context['source'])) {
$this->source = $context['source'];
} else {
throw new \BadMethodCallException('Invalid context, source not set');
}
return $context;
class DirectoryWrapper extends Wrapper implements Directory {
public function stream_open($path, $mode, $options, &$opened_path) {
return false;
} }


/** /**
* @return bool * @return bool
*/ */
public function dir_opendir($path, $options) { public function dir_opendir($path, $options) {
$this->loadContext('dir');
$this->loadContext();
return true; return true;
} }


rewinddir($this->source); rewinddir($this->source);
return true; return true;
} }

/**
* @param array $options the options for the context to wrap the stream with
* @param string $class
* @return resource
*/
protected static function wrapWithOptions($options, $class) {
$context = stream_context_create($options);
stream_wrapper_register('dirwrapper', $class);
$wrapped = opendir('dirwrapper://', $context);
stream_wrapper_unregister('dirwrapper');
return $wrapped;
}
} }

+ 5
- 5
apps/files_external/3rdparty/icewind/streams/src/File.php View File

* @param string $path * @param string $path
* @param string $mode * @param string $mode
* @param int $options * @param int $options
* @param string &$opened_path
* @param string $opened_path
* @return bool * @return bool
*/ */
public function stream_open($path, $mode, $options, &$opened_path); public function stream_open($path, $mode, $options, &$opened_path);
public function stream_seek($offset, $whence = SEEK_SET); public function stream_seek($offset, $whence = SEEK_SET);


/** /**
* @return int
* @return int|false
*/ */
public function stream_tell(); public function stream_tell();


/** /**
* @param int $count * @param int $count
* @return string
* @return string|false
*/ */
public function stream_read($count); public function stream_read($count);


/** /**
* @param string $data * @param string $data
* @return int
* @return int|false
*/ */
public function stream_write($data); public function stream_write($data);


public function stream_truncate($size); public function stream_truncate($size);


/** /**
* @return array
* @return array|false
*/ */
public function stream_stat(); public function stream_stat();



+ 78
- 0
apps/files_external/3rdparty/icewind/streams/src/HashWrapper.php View File

<?php
/**
* @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
*
* @author Roeland Jago Douma <roeland@famdouma.nl>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

namespace Icewind\Streams;

abstract class HashWrapper extends Wrapper {

/**
* @var callable|null
*/
private $callback;

/**
* @var resource|\HashContext
*/
private $hashContext;

/**
* Wraps a stream to make it seekable
*
* @param resource $source
* @param string $hash
* @param callable $callback
* @return resource|bool
*
* @throws \BadMethodCallException
*/
public static function wrap($source, $hash, $callback) {
$context = [
'hash' => $hash,
'callback' => $callback,
];
return self::wrapSource($source, $context);
}

public function dir_opendir($path, $options) {
return false;
}

public function stream_open($path, $mode, $options, &$opened_path) {
$context = $this->loadContext();
$this->callback = $context['callback'];
$this->hashContext = hash_init($context['hash']);
return true;
}

protected function updateHash($data) {
hash_update($this->hashContext, $data);
}

public function stream_close() {
$hash = hash_final($this->hashContext);
if ($this->hashContext !== false && is_callable($this->callback)) {
call_user_func($this->callback, $hash);
}
return parent::stream_close();
}
}

+ 16
- 26
apps/files_external/3rdparty/icewind/streams/src/IteratorDirectory.php View File

* *
* Either 'array' or 'iterator' need to be set, if both are set, 'iterator' takes preference * Either 'array' or 'iterator' need to be set, if both are set, 'iterator' takes preference
*/ */
class IteratorDirectory implements Directory {
class IteratorDirectory extends WrapperHandler implements Directory {
/** /**
* @var resource * @var resource
*/ */
* *
* @param string $name * @param string $name
* @return array * @return array
* @throws \Exception
* @throws \BadMethodCallException
*/ */
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');
}
protected function loadContext($name = null) {
$context = parent::loadContext($name);
if (isset($context['iterator'])) { if (isset($context['iterator'])) {
$this->iterator = $context['iterator']; $this->iterator = $context['iterator'];
} else if (isset($context['array'])) {
} elseif (isset($context['array'])) {
$this->iterator = new \ArrayIterator($context['array']); $this->iterator = new \ArrayIterator($context['array']);
} else { } else {
throw new \BadMethodCallException('Invalid context, iterator or array not set'); throw new \BadMethodCallException('Invalid context, iterator or array not set');
* @return bool * @return bool
*/ */
public function dir_opendir($path, $options) { public function dir_opendir($path, $options) {
$this->loadContext('dir');
$this->loadContext();
return true; return true;
} }


/** /**
* @return string
* @return string|bool
*/ */
public function dir_readdir() { public function dir_readdir() {
if ($this->iterator->valid()) { if ($this->iterator->valid()) {
* Creates a directory handle from the provided array or iterator * Creates a directory handle from the provided array or iterator
* *
* @param \Iterator | array $source * @param \Iterator | array $source
* @return resource
* @return resource|bool
* *
* @throws \BadMethodCallException * @throws \BadMethodCallException
*/ */
public static function wrap($source) { public static function wrap($source) {
if ($source instanceof \Iterator) { 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)
));
$options = [
'iterator' => $source
];
} elseif (is_array($source)) {
$options = [
'array' => $source
];
} else { } else {
throw new \BadMethodCallException('$source should be an Iterator or array'); 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;
return self::wrapSource(self::NO_SOURCE_DIR, $options);
} }
} }

+ 3
- 15
apps/files_external/3rdparty/icewind/streams/src/NullWrapper.php View File

* Stream wrapper that does nothing, used for tests * Stream wrapper that does nothing, used for tests
*/ */
class NullWrapper extends Wrapper { class NullWrapper extends Wrapper {
/**
* Wraps a stream with the provided callbacks
*
* @param resource $source
* @return resource
*
* @throws \BadMethodCallException
*/
public static function wrap($source) { public static function wrap($source) {
$context = stream_context_create(array(
'null' => array(
'source' => $source)
));
return Wrapper::wrapSource($source, $context, 'null', '\Icewind\Streams\NullWrapper');
return self::wrapSource($source);
} }


public function stream_open($path, $mode, $options, &$opened_path) { public function stream_open($path, $mode, $options, &$opened_path) {
$this->loadContext('null');
$this->loadContext();
return true; return true;
} }


public function dir_opendir($path, $options) { public function dir_opendir($path, $options) {
$this->loadContext('null');
$this->loadContext();
return true; return true;
} }
} }

+ 2
- 2
apps/files_external/3rdparty/icewind/streams/src/Path.php View File

* @param string $class * @param string $class
* @param array $contextOptions * @param array $contextOptions
*/ */
public function __construct($class, $contextOptions = array()) {
public function __construct($class, $contextOptions = []) {
$this->class = $class; $this->class = $class;
$this->contextOptions = $contextOptions; $this->contextOptions = $contextOptions;
} }
*/ */
protected function appendDefaultContent($values) { protected function appendDefaultContent($values) {
if (!is_array(current($values))) { if (!is_array(current($values))) {
$values = array($this->getProtocol() => $values);
$values = [$this->getProtocol() => $values];
} }
$context = stream_context_get_default(); $context = stream_context_get_default();
$defaults = stream_context_get_options($context); $defaults = stream_context_get_options($context);

+ 2
- 4
apps/files_external/3rdparty/icewind/streams/src/PathWrapper.php View File

* @return Path|string * @return Path|string
*/ */
public static function getPath($source) { public static function getPath($source) {
return new Path(__CLASS__, [
'null' => [
'source' => $source
]
return new Path(NullWrapper::class, [
NullWrapper::getProtocol() => ['source' => $source]
]); ]);
} }
} }

+ 40
- 0
apps/files_external/3rdparty/icewind/streams/src/ReadHashWrapper.php View File

<?php
/**
* @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
*
* @author Roeland Jago Douma <roeland@famdouma.nl>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

namespace Icewind\Streams;

/**
* Wrapper that calculates the hash on the stream on read
*
* The stream and hash should be passed in when wrapping the stream.
* On close the callback will be called with the calculated checksum.
*
* For supported hashes see: http://php.net/manual/en/function.hash-algos.php
*/
class ReadHashWrapper extends HashWrapper {
public function stream_read($count) {
$data = parent::stream_read($count);
$this->updateHash($data);
return $data;
}
}

+ 3
- 19
apps/files_external/3rdparty/icewind/streams/src/RetryWrapper.php View File

* Wrapper that retries reads/writes to remote streams that dont deliver/recieve all requested data at once * Wrapper that retries reads/writes to remote streams that dont deliver/recieve all requested data at once
*/ */
class RetryWrapper extends Wrapper { class RetryWrapper extends Wrapper {

/**
* Wraps a stream with the provided callbacks
*
* @param resource $source
* @return resource
*/
public static function wrap($source) { public static function wrap($source) {
$context = stream_context_create(array(
'retry' => array(
'source' => $source
)
));
return Wrapper::wrapSource($source, $context, 'retry', '\Icewind\Streams\RetryWrapper');
}

protected function open() {
$this->loadContext('retry');
return true;
return self::wrapSource($source);
} }


public function dir_opendir($path, $options) { public function dir_opendir($path, $options) {
} }


public function stream_open($path, $mode, $options, &$opened_path) { public function stream_open($path, $mode, $options, &$opened_path) {
return $this->open();
$this->loadContext();
return true;
} }


public function stream_read($count) { public function stream_read($count) {

+ 8
- 17
apps/files_external/3rdparty/icewind/streams/src/SeekableWrapper.php View File

*/ */
protected $cache; protected $cache;


/**
* Wraps a stream to make it seekable
*
* @param resource $source
* @return resource
*
* @throws \BadMethodCallException
*/
public static function wrap($source) { public static function wrap($source) {
$context = stream_context_create(array(
'callback' => array(
'source' => $source
)
));
return Wrapper::wrapSource($source, $context, 'callback', '\Icewind\Streams\SeekableWrapper');
return self::wrapSource($source);
} }


public function dir_opendir($path, $options) { public function dir_opendir($path, $options) {
} }


public function stream_open($path, $mode, $options, &$opened_path) { public function stream_open($path, $mode, $options, &$opened_path) {
$this->loadContext('callback');
$this->cache = fopen('php://temp', 'w+');
$this->loadContext();
$cache = fopen('php://temp', 'w+');
if ($cache === false) {
return false;
}
$this->cache = $cache;
return true; return true;
} }


public function stream_seek($offset, $whence = SEEK_SET) { public function stream_seek($offset, $whence = SEEK_SET) {
if ($whence === SEEK_SET) { if ($whence === SEEK_SET) {
$target = $offset; $target = $offset;
} else if ($whence === SEEK_CUR) {
} elseif ($whence === SEEK_CUR) {
$current = ftell($this->cache); $current = ftell($this->cache);
$target = $current + $offset; $target = $current + $offset;
} else { } else {

+ 3
- 3
apps/files_external/3rdparty/icewind/streams/src/Url.php View File

* @param string $path * @param string $path
* @param string $mode * @param string $mode
* @param int $options * @param int $options
* @param string &$opened_path
* @param string $opened_path
* @return bool * @return bool
*/ */
public function stream_open($path, $mode, $options, &$opened_path); public function stream_open($path, $mode, $options, &$opened_path);
public function rmdir($path, $options); public function rmdir($path, $options);


/** /**
* @param string
* @param string $path
* @return bool * @return bool
*/ */
public function unlink($path); public function unlink($path);
/** /**
* @param string $path * @param string $path
* @param int $flags * @param int $flags
* @return array
* @return array|false
*/ */
public function url_stat($path, $flags); public function url_stat($path, $flags);
} }

apps/files_external/3rdparty/icewind/streams/src/UrlCallBack.php → apps/files_external/3rdparty/icewind/streams/src/UrlCallback.php View File

* @return \Icewind\Streams\Path * @return \Icewind\Streams\Path
* *
* @throws \BadMethodCallException * @throws \BadMethodCallException
* @throws \Exception
*/ */
public static function wrap($source, $fopen = null, $opendir = null, $mkdir = null, $rename = null, $rmdir = null,
$unlink = null, $stat = null) {
$options = array(
'source' => $source,
'fopen' => $fopen,
public static function wrap(
$source,
$fopen = null,
$opendir = null,
$mkdir = null,
$rename = null,
$rmdir = null,
$unlink = null,
$stat = null
) {
return new Path(static::class, [
'source' => $source,
'fopen' => $fopen,
'opendir' => $opendir, 'opendir' => $opendir,
'mkdir' => $mkdir,
'rename' => $rename,
'rmdir' => $rmdir,
'unlink' => $unlink,
'stat' => $stat
);
return new Path('\Icewind\Streams\UrlCallBack', $options);
'mkdir' => $mkdir,
'rename' => $rename,
'rmdir' => $rmdir,
'unlink' => $unlink,
'stat' => $stat
]);
} }


protected function loadContext($url) {
protected function loadUrlContext($url) {
list($protocol) = explode('://', $url); list($protocol) = explode('://', $url);
$options = stream_context_get_options($this->context); $options = stream_context_get_options($this->context);
return $options[$protocol]; return $options[$protocol];
} }


public function stream_open($path, $mode, $options, &$opened_path) { public function stream_open($path, $mode, $options, &$opened_path) {
$context = $this->loadContext($path);
$context = $this->loadUrlContext($path);
$this->callCallBack($context, 'fopen'); $this->callCallBack($context, 'fopen');
$this->setSourceStream(fopen($context['source'], $mode));
$source = fopen($context['source'], $mode);
if ($source === false) {
return false;
}
$this->setSourceStream($source);
return true; return true;
} }


public function dir_opendir($path, $options) { public function dir_opendir($path, $options) {
$context = $this->loadContext($path);
$context = $this->loadUrlContext($path);
$this->callCallBack($context, 'opendir'); $this->callCallBack($context, 'opendir');
$this->setSourceStream(opendir($context['source']));
$source = opendir($context['source']);
if ($source === false) {
return false;
}
$this->setSourceStream($source);
return true; return true;
} }


public function mkdir($path, $mode, $options) { public function mkdir($path, $mode, $options) {
$context = $this->loadContext($path);
$context = $this->loadUrlContext($path);
$this->callCallBack($context, 'mkdir'); $this->callCallBack($context, 'mkdir');
return mkdir($context['source'], $mode, $options & STREAM_MKDIR_RECURSIVE);
return mkdir($context['source'], $mode, ($options & STREAM_MKDIR_RECURSIVE) > 0);
} }


public function rmdir($path, $options) { public function rmdir($path, $options) {
$context = $this->loadContext($path);
$context = $this->loadUrlContext($path);
$this->callCallBack($context, 'rmdir'); $this->callCallBack($context, 'rmdir');
return rmdir($context['source']); return rmdir($context['source']);
} }


public function rename($source, $target) { public function rename($source, $target) {
$context = $this->loadContext($source);
$context = $this->loadUrlContext($source);
$this->callCallBack($context, 'rename'); $this->callCallBack($context, 'rename');
list(, $target) = explode('://', $target); list(, $target) = explode('://', $target);
return rename($context['source'], $target); return rename($context['source'], $target);
} }


public function unlink($path) { public function unlink($path) {
$context = $this->loadContext($path);
$context = $this->loadUrlContext($path);
$this->callCallBack($context, 'unlink'); $this->callCallBack($context, 'unlink');
return unlink($context['source']); return unlink($context['source']);
} }

+ 12
- 49
apps/files_external/3rdparty/icewind/streams/src/Wrapper.php View File

* *
* This wrapper itself doesn't implement any functionality but is just a base class for other wrappers to extend * This wrapper itself doesn't implement any functionality but is just a base class for other wrappers to extend
*/ */
abstract class Wrapper implements File, Directory {
abstract class Wrapper extends WrapperHandler implements File, Directory {
/** /**
* @var resource * @var resource
*/ */
*/ */
protected $source; protected $source;


protected static function wrapSource($source, $context, $protocol, $class) {
if (!is_resource($source)) {
throw new \BadMethodCallException();
}
try {
stream_wrapper_register($protocol, $class);
if (self::isDirectoryHandle($source)) {
$wrapped = opendir($protocol . '://', $context);
} else {
$wrapped = fopen($protocol . '://', 'r+', false, $context);
}
} catch (\BadMethodCallException $e) {
stream_wrapper_unregister($protocol);
throw $e;
}
stream_wrapper_unregister($protocol);
return $wrapped;
}

protected static function isDirectoryHandle($resource) {
$meta = stream_get_meta_data($resource);
return $meta['stream_type'] == 'dir';
}

/** /**
* Load the source from the stream context and return the context options
*
* @param string $name
* @return array
* @throws \Exception
* @param resource $source
*/ */
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');
}
protected function setSourceStream($source) {
$this->source = $source;
}

protected function loadContext($name = null) {
$context = parent::loadContext($name);
if (isset($context['source']) and is_resource($context['source'])) { if (isset($context['source']) and is_resource($context['source'])) {
$this->setSourceStream($context['source']); $this->setSourceStream($context['source']);
} else { } else {
return $context; return $context;
} }


/**
* @param resource $source
*/
protected function setSourceStream($source) {
$this->source = $source;
}

public function stream_seek($offset, $whence = SEEK_SET) { public function stream_seek($offset, $whence = SEEK_SET) {
$result = fseek($this->source, $offset, $whence); $result = fseek($this->source, $offset, $whence);
return $result == 0 ? true : false; return $result == 0 ? true : false;
public function stream_set_option($option, $arg1, $arg2) { public function stream_set_option($option, $arg1, $arg2) {
switch ($option) { switch ($option) {
case STREAM_OPTION_BLOCKING: case STREAM_OPTION_BLOCKING:
stream_set_blocking($this->source, $arg1);
break;
return stream_set_blocking($this->source, (bool)$arg1);
case STREAM_OPTION_READ_TIMEOUT: case STREAM_OPTION_READ_TIMEOUT:
stream_set_timeout($this->source, $arg1, $arg2);
break;
return stream_set_timeout($this->source, $arg1, $arg2);
case STREAM_OPTION_WRITE_BUFFER: case STREAM_OPTION_WRITE_BUFFER:
stream_set_write_buffer($this->source, $arg1);
return stream_set_write_buffer($this->source, $arg1) === 0;
} }
return false;
} }


public function stream_truncate($size) { public function stream_truncate($size) {

+ 114
- 0
apps/files_external/3rdparty/icewind/streams/src/WrapperHandler.php View File

<?php
/**
* @copyright Copyright (c) 2019 Robin Appelman <robin@icewind.nl>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

namespace Icewind\Streams;

class WrapperHandler {
/** @var resource $context */
protected $context;

const NO_SOURCE_DIR = 1;

/**
* get the protocol name that is generated for the class
* @param string|null $class
* @return string
*/
public static function getProtocol($class = null) {
if ($class === null) {
$class = static::class;
}

$parts = explode('\\', $class);
return strtolower(array_pop($parts));
}

private static function buildContext($protocol, $context, $source) {
if (is_array($context)) {
$context['source'] = $source;
return stream_context_create([$protocol => $context]);
} else {
return $context;
}
}

/**
* @param resource|int $source
* @param resource|array $context
* @param string|null $protocol deprecated, protocol is now automatically generated
* @param string|null $class deprecated, class is now automatically generated
* @return bool|resource
*/
protected static function wrapSource($source, $context = [], $protocol = null, $class = null) {
if ($class === null) {
$class = static::class;
}

if ($protocol === null) {
$protocol = self::getProtocol($class);
}

$context = self::buildContext($protocol, $context, $source);
try {
stream_wrapper_register($protocol, $class);
if (self::isDirectoryHandle($source)) {
return opendir($protocol . '://', $context);
} else {
return fopen($protocol . '://', 'r+', false, $context);
}
} finally {
stream_wrapper_unregister($protocol);
}
}

protected static function isDirectoryHandle($resource) {
if ($resource === self::NO_SOURCE_DIR) {
return true;
}
if (!is_resource($resource)) {
throw new \BadMethodCallException('Invalid stream source');
}
$meta = stream_get_meta_data($resource);
return $meta['stream_type'] === 'dir' || $meta['stream_type'] === 'user-space-dir';
}

/**
* Load the source from the stream context and return the context options
*
* @param string|null $name if not set, the generated protocol name is used
* @return array
* @throws \BadMethodCallException
*/
protected function loadContext($name = null) {
if ($name === null) {
$parts = explode('\\', static::class);
$name = strtolower(array_pop($parts));
}

$context = stream_context_get_options($this->context);
if (isset($context[$name])) {
$context = $context[$name];
} else {
throw new \BadMethodCallException('Invalid context, "' . $name . '" options not set');
}
return $context;
}
}

+ 37
- 0
apps/files_external/3rdparty/icewind/streams/src/WriteHashWrapper.php View File

<?php
/**
* @copyright Copyright (c) 2019 Robin Appelman <robin@icewind.nl>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

namespace Icewind\Streams;

/**
* Wrapper that calculates the hash on the stream on write
*
* The stream and hash should be passed in when wrapping the stream.
* On close the callback will be called with the calculated checksum.
*
* For supported hashes see: http://php.net/manual/en/function.hash-algos.php
*/
class WriteHashWrapper extends HashWrapper {
public function stream_write($data) {
$this->updateHash($data);
return parent::stream_write($data);
}
}

Loading…
Cancel
Save