summaryrefslogtreecommitdiffstats
path: root/apps/files_external/3rdparty/icewind/smb/src
diff options
context:
space:
mode:
authorRobin Appelman <robin@icewind.nl>2021-03-10 15:31:09 +0100
committerRobin Appelman <robin@icewind.nl>2021-03-10 15:31:09 +0100
commit66781e74ada3fd22bb5b246a59897ac146cda4dd (patch)
treeddb35b074eb6523c1aaffb68e78f58faf797ae23 /apps/files_external/3rdparty/icewind/smb/src
parent62929cc646134fbd409cfb4eacb7039d15763b96 (diff)
downloadnextcloud-server-66781e74ada3fd22bb5b246a59897ac146cda4dd.tar.gz
nextcloud-server-66781e74ada3fd22bb5b246a59897ac146cda4dd.zip
update icewind/smb to 3.4.0
Signed-off-by: Robin Appelman <robin@icewind.nl>
Diffstat (limited to 'apps/files_external/3rdparty/icewind/smb/src')
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/ACL.php3
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/AbstractServer.php30
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/AbstractShare.php12
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/AnonymousAuth.php10
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/BasicAuth.php21
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Change.php21
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Exception/Exception.php28
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidRequestException.php8
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Exception/RevisionMismatchException.php2
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/IAuth.php19
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/IFileInfo.php45
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/INotifyHandler.php8
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/IOptions.php20
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/IServer.php39
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/IShare.php83
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/ISystem.php34
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/ITimeZoneProvider.php2
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/KerberosAuth.php10
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Native/NativeFileInfo.php104
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Native/NativeReadStream.php59
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Native/NativeServer.php29
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Native/NativeShare.php133
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Native/NativeState.php124
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Native/NativeStream.php48
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Native/NativeWriteStream.php50
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Options.php25
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/ServerFactory.php6
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/StringBuffer.php63
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/System.php20
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/TimeZoneProvider.php2
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Wrapped/Connection.php49
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Wrapped/FileInfo.php75
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Wrapped/NotifyHandler.php34
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Wrapped/Parser.php120
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Wrapped/RawConnection.php74
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Wrapped/Server.php31
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Wrapped/Share.php226
37 files changed, 907 insertions, 760 deletions
diff --git a/apps/files_external/3rdparty/icewind/smb/src/ACL.php b/apps/files_external/3rdparty/icewind/smb/src/ACL.php
index bdb77257f17..0b5b05a86af 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/ACL.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/ACL.php
@@ -33,8 +33,11 @@ class ACL {
const FLAG_OBJECT_INHERIT = 0x1;
const FLAG_CONTAINER_INHERIT = 0x2;
+ /** @var int */
private $type;
+ /** @var int */
private $flags;
+ /** @var int */
private $mask;
public function __construct(int $type, int $flags, int $mask) {
diff --git a/apps/files_external/3rdparty/icewind/smb/src/AbstractServer.php b/apps/files_external/3rdparty/icewind/smb/src/AbstractServer.php
index aa2adfa67b3..810ca807d9b 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/AbstractServer.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/AbstractServer.php
@@ -24,24 +24,16 @@ namespace Icewind\SMB;
abstract class AbstractServer implements IServer {
const LOCALE = 'en_US.UTF-8';
- /**
- * @var string $host
- */
+ /** @var string */
protected $host;
- /**
- * @var IAuth $user
- */
+ /** @var IAuth */
protected $auth;
- /**
- * @var ISystem
- */
+ /** @var ISystem */
protected $system;
- /**
- * @var TimeZoneProvider
- */
+ /** @var ITimeZoneProvider */
protected $timezoneProvider;
/** @var IOptions */
@@ -51,10 +43,10 @@ abstract class AbstractServer implements IServer {
* @param string $host
* @param IAuth $auth
* @param ISystem $system
- * @param TimeZoneProvider $timeZoneProvider
+ * @param ITimeZoneProvider $timeZoneProvider
* @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->auth = $auth;
$this->system = $system;
@@ -62,23 +54,23 @@ abstract class AbstractServer implements IServer {
$this->options = $options;
}
- public function getAuth() {
+ public function getAuth(): IAuth {
return $this->auth;
}
- public function getHost() {
+ public function getHost(): string {
return $this->host;
}
- public function getTimeZone() {
+ public function getTimeZone(): string {
return $this->timezoneProvider->get($this->host);
}
- public function getSystem() {
+ public function getSystem(): ISystem {
return $this->system;
}
- public function getOptions() {
+ public function getOptions(): IOptions {
return $this->options;
}
}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/AbstractShare.php b/apps/files_external/3rdparty/icewind/smb/src/AbstractShare.php
index b53c253be08..454eb143e49 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/AbstractShare.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/AbstractShare.php
@@ -10,13 +10,18 @@ namespace Icewind\SMB;
use Icewind\SMB\Exception\InvalidPathException;
abstract class AbstractShare implements IShare {
+ /** @var string[] */
private $forbiddenCharacters;
public function __construct() {
$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) {
if (strpos($path, $char) !== false) {
throw new InvalidPathException('Invalid path, "' . $char . '" is not allowed');
@@ -24,7 +29,10 @@ abstract class AbstractShare implements IShare {
}
}
- public function setForbiddenChars(array $charList) {
+ /**
+ * @param string[] $charList
+ */
+ public function setForbiddenChars(array $charList): void {
$this->forbiddenCharacters = $charList;
}
}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/AnonymousAuth.php b/apps/files_external/3rdparty/icewind/smb/src/AnonymousAuth.php
index 737cc7c63f1..0f3524002be 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/AnonymousAuth.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/AnonymousAuth.php
@@ -22,23 +22,23 @@
namespace Icewind\SMB;
class AnonymousAuth implements IAuth {
- public function getUsername() {
+ public function getUsername(): ?string {
return null;
}
- public function getWorkgroup() {
+ public function getWorkgroup(): ?string {
return 'dummy';
}
- public function getPassword() {
+ public function getPassword(): ?string {
return null;
}
- public function getExtraCommandLineArguments() {
+ public function getExtraCommandLineArguments(): string {
return '-N';
}
- public function setExtraSmbClientOptions($smbClientState) {
+ public function setExtraSmbClientOptions($smbClientState): void {
smbclient_option_set($smbClientState, SMBCLIENT_OPT_AUTO_ANONYMOUS_LOGIN, true);
}
}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/BasicAuth.php b/apps/files_external/3rdparty/icewind/smb/src/BasicAuth.php
index 9d7f9b5d306..04004e6ebd8 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/BasicAuth.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/BasicAuth.php
@@ -24,41 +24,34 @@ namespace Icewind\SMB;
class BasicAuth implements IAuth {
/** @var string */
private $username;
- /** @var string */
+ /** @var string|null */
private $workgroup;
/** @var string */
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->workgroup = $workgroup;
$this->password = $password;
}
- public function getUsername() {
+ public function getUsername(): ?string {
return $this->username;
}
- public function getWorkgroup() {
+ public function getWorkgroup(): ?string {
return $this->workgroup;
}
- public function getPassword() {
+ public function getPassword(): ?string {
return $this->password;
}
- public function getExtraCommandLineArguments() {
+ public function getExtraCommandLineArguments(): string {
return ($this->workgroup) ? '-W ' . escapeshellarg($this->workgroup) : '';
}
- public function setExtraSmbClientOptions($smbClientState) {
+ public function setExtraSmbClientOptions($smbClientState): void {
// noop
}
}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Change.php b/apps/files_external/3rdparty/icewind/smb/src/Change.php
index 9dfd57b3973..4d6ab49d2bb 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/Change.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/Change.php
@@ -9,32 +9,21 @@
namespace Icewind\SMB;
class Change {
+ /** @var int */
private $code;
-
+ /** @var string */
private $path;
- /**
- * Change constructor.
- *
- * @param $code
- * @param $path
- */
- public function __construct($code, $path) {
+ public function __construct(int $code, string $path) {
$this->code = $code;
$this->path = $path;
}
- /**
- * @return integer
- */
- public function getCode() {
+ public function getCode(): int {
return $this->code;
}
- /**
- * @return string
- */
- public function getPath() {
+ public function getPath(): string {
return $this->path;
}
}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/Exception.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/Exception.php
index 4954518f980..e3e860b30d5 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/Exception/Exception.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/Exception.php
@@ -7,23 +7,37 @@
namespace Icewind\SMB\Exception;
+use Throwable;
+
+/**
+ * @psalm-consistent-constructor
+ */
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) {
$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
*/
- public static function fromMap(array $exceptionMap, $error, $path) {
+ public static function fromMap(array $exceptionMap, $error, ?string $path): Exception {
if (isset($exceptionMap[$error])) {
$exceptionClass = $exceptionMap[$error];
if (is_numeric($error)) {
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidRequestException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidRequestException.php
index 882bf1677bf..1494de9efcb 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidRequestException.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidRequestException.php
@@ -13,15 +13,11 @@ class InvalidRequestException extends Exception {
*/
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);
$parts = explode('\\', $class);
$baseName = array_pop($parts);
- parent::__construct('Invalid request for ' . $path . ' (' . $baseName . ')', $code);
+ parent::__construct('Invalid request for ' . $path . ' (' . $baseName . ')', $code, $previous);
$this->path = $path;
}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/RevisionMismatchException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/RevisionMismatchException.php
index e898b5a2347..3c7c180bf93 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/Exception/RevisionMismatchException.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/RevisionMismatchException.php
@@ -10,7 +10,7 @@ namespace Icewind\SMB\Exception;
use Throwable;
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);
}
}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/IAuth.php b/apps/files_external/3rdparty/icewind/smb/src/IAuth.php
index 731b315ebaa..9d4302dd4e8 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/IAuth.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/IAuth.php
@@ -22,32 +22,23 @@
namespace Icewind\SMB;
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
*
* @return string
*/
- public function getExtraCommandLineArguments();
+ public function getExtraCommandLineArguments(): string;
/**
* Set any extra options for libsmbclient that are required
*
* @param resource $smbClientState
*/
- public function setExtraSmbClientOptions($smbClientState);
+ public function setExtraSmbClientOptions($smbClientState): void;
}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/IFileInfo.php b/apps/files_external/3rdparty/icewind/smb/src/IFileInfo.php
index 3411d498d78..7e440c1420b 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/IFileInfo.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/IFileInfo.php
@@ -21,50 +21,23 @@ interface IFileInfo {
const MODE_ARCHIVE = 0x20;
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[]
diff --git a/apps/files_external/3rdparty/icewind/smb/src/INotifyHandler.php b/apps/files_external/3rdparty/icewind/smb/src/INotifyHandler.php
index c3ee3ffe8cf..e964a15fa37 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/INotifyHandler.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/INotifyHandler.php
@@ -25,21 +25,21 @@ interface INotifyHandler {
*
* @return Change[]
*/
- public function getChanges();
+ public function getChanges(): array;
/**
* 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
*
- * @param callable $callback
+ * @param callable(Change):?bool $callback
*/
- public function listen($callback);
+ public function listen(callable $callback): void;
/**
* Stop listening for changes
*
* Note that any pending changes will be discarded
*/
- public function stop();
+ public function stop(): void;
}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/IOptions.php b/apps/files_external/3rdparty/icewind/smb/src/IOptions.php
index c46d2c8b3dc..4ab7b26c660 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/IOptions.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/IOptions.php
@@ -22,8 +22,20 @@
namespace Icewind\SMB;
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;
}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/IServer.php b/apps/files_external/3rdparty/icewind/smb/src/IServer.php
index 0b832025aab..c2f5a504bcf 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/IServer.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/IServer.php
@@ -22,15 +22,9 @@
namespace Icewind\SMB;
interface IServer {
- /**
- * @return IAuth
- */
- public function getAuth();
+ public function getAuth(): IAuth;
- /**
- * @return string
- */
- public function getHost();
+ public function getHost(): string;
/**
* @return \Icewind\SMB\IShare[]
@@ -38,32 +32,15 @@ interface IServer {
* @throws \Icewind\SMB\Exception\AuthenticationException
* @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;
}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/IShare.php b/apps/files_external/3rdparty/icewind/smb/src/IShare.php
index d33d10bb3fb..6ac6e0d2d15 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/IShare.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/IShare.php
@@ -7,13 +7,18 @@
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 {
/**
* Get the name of the share
*
* @return string
*/
- public function getName();
+ public function getName(): string;
/**
* Download a remote file
@@ -22,10 +27,10 @@ interface IShare {
* @param string $target local file
* @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
@@ -34,10 +39,10 @@ interface IShare {
* @param string $target remove file
* @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
@@ -45,10 +50,10 @@ interface IShare {
* @param string $source
* @return resource a read only stream with the contents of the remote file
*
- * @throws \Icewind\SMB\Exception\NotFoundException
- * @throws \Icewind\SMB\Exception\InvalidTypeException
+ * @throws NotFoundException
+ * @throws InvalidTypeException
*/
- public function read($source);
+ public function read(string $source);
/**
* Open a writable stream to a remote file
@@ -57,10 +62,10 @@ interface IShare {
* @param string $target
* @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
@@ -68,11 +73,11 @@ interface IShare {
* @param string $target
* @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
@@ -81,10 +86,10 @@ interface IShare {
* @param string $to
* @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
@@ -92,29 +97,29 @@ interface IShare {
* @param string $path
* @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
*
- * @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
- * @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
@@ -122,10 +127,10 @@ interface IShare {
* @param string $path
* @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
@@ -133,23 +138,23 @@ interface IShare {
* @param string $path
* @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 int $mode a combination of FileInfo::MODE_READONLY, FileInfo::MODE_ARCHIVE, FileInfo::MODE_SYSTEM and FileInfo::MODE_HIDDEN, FileInfo::NORMAL
* @return mixed
*/
- public function setMode($path, $mode);
+ public function setMode(string $path, int $mode);
/**
* @param string $path
* @return INotifyHandler
*/
- public function notify($path);
+ public function notify(string $path);
/**
* Get the IServer instance for this share
diff --git a/apps/files_external/3rdparty/icewind/smb/src/ISystem.php b/apps/files_external/3rdparty/icewind/smb/src/ISystem.php
index 09994610716..6f06b8421c2 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/ISystem.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/ISystem.php
@@ -32,47 +32,47 @@ interface ISystem {
* @param int $num the file descriptor id
* @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
*
* @return bool
*/
- public function libSmbclientAvailable();
+ public function libSmbclientAvailable(): bool;
}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/ITimeZoneProvider.php b/apps/files_external/3rdparty/icewind/smb/src/ITimeZoneProvider.php
index 56e09ffb392..d624bcec854 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/ITimeZoneProvider.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/ITimeZoneProvider.php
@@ -28,5 +28,5 @@ interface ITimeZoneProvider {
* @param string $host
* @return string
*/
- public function get($host);
+ public function get(string $host): string;
}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/KerberosAuth.php b/apps/files_external/3rdparty/icewind/smb/src/KerberosAuth.php
index 0e91202cb76..7cd9258465a 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/KerberosAuth.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/KerberosAuth.php
@@ -25,23 +25,23 @@ namespace Icewind\SMB;
* Use existing kerberos ticket to authenticate
*/
class KerberosAuth implements IAuth {
- public function getUsername() {
+ public function getUsername(): ?string {
return 'dummy';
}
- public function getWorkgroup() {
+ public function getWorkgroup(): ?string {
return 'dummy';
}
- public function getPassword() {
+ public function getPassword(): ?string {
return null;
}
- public function getExtraCommandLineArguments() {
+ public function getExtraCommandLineArguments(): string {
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_FALLBACK_AFTER_KERBEROS, false);
}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeFileInfo.php b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeFileInfo.php
index d8be57c7311..539bb728426 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeFileInfo.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeFileInfo.php
@@ -8,88 +8,71 @@
namespace Icewind\SMB\Native;
use Icewind\SMB\ACL;
+use Icewind\SMB\Exception\Exception;
use Icewind\SMB\IFileInfo;
class NativeFileInfo implements IFileInfo {
- /**
- * @var string
- */
+ /** @var string */
protected $path;
-
- /**
- * @var string
- */
+ /** @var string */
protected $name;
-
- /**
- * @var NativeShare
- */
+ /** @var NativeShare */
protected $share;
-
- /**
- * @var array|null
- */
+ /** @var array{"mode": int, "size": int, "write_time": int}|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->path = $path;
$this->name = $name;
}
- /**
- * @return string
- */
- public function getPath() {
+ public function getPath(): string {
return $this->path;
}
- /**
- * @return string
- */
- public function getName() {
+ public function getName(): string {
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)) {
$rawAttributes = explode(',', $this->share->getAttribute($this->path, 'system.dos_attr.*'));
- $this->attributeCache = [];
+ $attributes = [];
foreach ($rawAttributes as $rawAttribute) {
list($name, $value) = explode(':', $rawAttribute);
$name = strtolower($name);
if ($name == 'mode') {
- $this->attributeCache[$name] = (int)hexdec(substr($value, 2));
+ $attributes[$name] = (int)hexdec(substr($value, 2));
} 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 int
- */
- public function getSize() {
+ public function getSize(): int {
$stat = $this->stat();
return $stat['size'];
}
- /**
- * @return int
- */
- public function getMTime() {
+ public function getMTime(): int {
$stat = $this->stat();
- return $stat['change_time'];
+ return $stat['write_time'];
}
/**
@@ -104,22 +87,16 @@ class NativeFileInfo implements IFileInfo {
* 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'];
// Let us ignore the ATTR_NOT_CONTENT_INDEXED for now
$mode &= ~0x00002000;
-
+
return $mode;
}
- /**
- * @return bool
- */
- public function isDirectory() {
+ public function isDirectory(): bool {
$mode = $this->getMode();
if ($mode > 0x1000) {
return (bool)($mode & 0x4000); // 0x4000: unix directory flag
@@ -128,10 +105,7 @@ class NativeFileInfo implements IFileInfo {
}
}
- /**
- * @return bool
- */
- public function isReadOnly() {
+ public function isReadOnly(): bool {
$mode = $this->getMode();
if ($mode > 0x1000) {
return !(bool)($mode & 0x80); // 0x80: owner write permissions
@@ -140,10 +114,7 @@ class NativeFileInfo implements IFileInfo {
}
}
- /**
- * @return bool
- */
- public function isHidden() {
+ public function isHidden(): bool {
$mode = $this->getMode();
if ($mode > 0x1000) {
return strlen($this->name) > 0 && $this->name[0] === '.';
@@ -152,10 +123,7 @@ class NativeFileInfo implements IFileInfo {
}
}
- /**
- * @return bool
- */
- public function isSystem() {
+ public function isSystem(): bool {
$mode = $this->getMode();
if ($mode > 0x1000) {
return false;
@@ -164,10 +132,7 @@ class NativeFileInfo implements IFileInfo {
}
}
- /**
- * @return bool
- */
- public function isArchived() {
+ public function isArchived(): bool {
$mode = $this->getMode();
if ($mode > 0x1000) {
return false;
@@ -185,10 +150,11 @@ class NativeFileInfo implements IFileInfo {
foreach (explode(',', $attribute) as $acl) {
list($user, $permissions) = explode(':', $acl, 2);
+ $user = trim($user, '\\');
list($type, $flags, $mask) = explode('/', $permissions);
$mask = hexdec($mask);
- $acls[$user] = new ACL($type, $flags, $mask);
+ $acls[$user] = new ACL((int)$type, (int)$flags, (int)$mask);
}
return $acls;
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeReadStream.php b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeReadStream.php
index fe0af760d3f..f39ec4db392 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeReadStream.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeReadStream.php
@@ -7,64 +7,54 @@
namespace Icewind\SMB\Native;
+use Icewind\SMB\StringBuffer;
+
/**
* Stream optimized for read only usage
*/
class NativeReadStream extends NativeStream {
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;
public function stream_open($path, $mode, $options, &$opened_path) {
- $this->readBuffer = fopen('php://memory', 'r+');
-
return parent::stream_open($path, $mode, $options, $opened_path);
}
/**
* Wrap a stream from libsmbclient-php into a regular php stream
*
- * @param \Icewind\SMB\NativeState $state
+ * @param NativeState $state
* @param resource $smbStream
* @param string $mode
* @param string $url
* @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) {
// php reads 8192 bytes at once
// however due to network latency etc, it's faster to read in larger chunks
// 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);
$this->pos += $read;
@@ -75,15 +65,18 @@ class NativeReadStream extends NativeStream {
public function stream_seek($offset, $whence = SEEK_SET) {
$result = parent::stream_seek($offset, $whence);
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;
}
public function stream_eof() {
- return $this->bufferSize <= 0 && parent::stream_eof();
+ return $this->readBuffer->remaining() <= 0 && parent::stream_eof();
}
public function stream_tell() {
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeServer.php b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeServer.php
index aadb05d0fea..68b6c46ca2f 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeServer.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeServer.php
@@ -8,10 +8,13 @@
namespace Icewind\SMB\Native;
use Icewind\SMB\AbstractServer;
+use Icewind\SMB\Exception\AuthenticationException;
+use Icewind\SMB\Exception\InvalidHostException;
use Icewind\SMB\IAuth;
use Icewind\SMB\IOptions;
+use Icewind\SMB\IShare;
use Icewind\SMB\ISystem;
-use Icewind\SMB\TimeZoneProvider;
+use Icewind\SMB\ITimeZoneProvider;
class NativeServer extends AbstractServer {
/**
@@ -19,38 +22,34 @@ class NativeServer extends AbstractServer {
*/
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);
$this->state = new NativeState();
}
- protected function connect() {
+ protected function connect(): void {
$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();
$shares = [];
$dh = $this->state->opendir('smb://' . $this->getHost());
- while ($share = $this->state->readdir($dh)) {
+ while ($share = $this->state->readdir($dh, '')) {
if ($share['type'] === 'file share') {
$shares[] = $this->getShare($share['name']);
}
}
- $this->state->closedir($dh);
+ $this->state->closedir($dh, '');
return $shares;
}
- /**
- * @param string $name
- * @return \Icewind\SMB\IShare
- */
- public function getShare($name) {
+ public function getShare(string $name): IShare {
return new NativeShare($this, $name);
}
@@ -60,7 +59,7 @@ class NativeServer extends AbstractServer {
* @param ISystem $system
* @return bool
*/
- public static function available(ISystem $system) {
+ public static function available(ISystem $system): bool {
return $system->libSmbclientAvailable();
}
}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeShare.php b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeShare.php
index 5368538edca..03ec501b830 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeShare.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeShare.php
@@ -8,9 +8,16 @@
namespace Icewind\SMB\Native;
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\InvalidHostException;
use Icewind\SMB\Exception\InvalidPathException;
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\IServer;
use Icewind\SMB\Wrapped\Server;
@@ -27,28 +34,22 @@ class NativeShare extends AbstractShare {
*/
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();
$this->server = $server;
$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;
}
@@ -62,11 +63,11 @@ class NativeShare extends AbstractShare {
*
* @return string
*/
- public function getName() {
+ public function getName(): string {
return $this->name;
}
- private function buildUrl($path) {
+ private function buildUrl(string $path): string {
$this->verifyPath($path);
$url = sprintf('smb://%s/%s', $this->server->getHost(), $this->name);
if ($path) {
@@ -81,16 +82,16 @@ class NativeShare extends AbstractShare {
* List the content of a remote folder
*
* @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 = [];
$dh = $this->getState()->opendir($this->buildUrl($path));
- while ($file = $this->getState()->readdir($dh)) {
+ while ($file = $this->getState()->readdir($dh, $path)) {
$name = $file['name'];
if ($name !== '.' and $name !== '..') {
$fullPath = $path . '/' . $name;
@@ -98,15 +99,15 @@ class NativeShare extends AbstractShare {
}
}
- $this->getState()->closedir($dh);
+ $this->getState()->closedir($dh, $path);
return $files;
}
/**
* @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));
// trigger attribute loading
@@ -119,10 +120,10 @@ class NativeShare extends AbstractShare {
* Multibyte unicode safe version of basename()
*
* @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
*/
- protected static function mb_basename($path) {
+ protected static function mb_basename(string $path): string {
if (preg_match('@^.*[\\\\/]([^\\\\/]+)$@s', $path, $matches)) {
return $matches[1];
} elseif (preg_match('@^([^\\\\/]+)$@s', $path, $matches)) {
@@ -138,10 +139,10 @@ class NativeShare extends AbstractShare {
* @param string $path
* @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));
}
@@ -151,10 +152,10 @@ class NativeShare extends AbstractShare {
* @param string $path
* @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));
}
@@ -164,10 +165,10 @@ class NativeShare extends AbstractShare {
* @param string $path
* @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));
}
@@ -178,10 +179,10 @@ class NativeShare extends AbstractShare {
* @param string $to
* @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));
}
@@ -192,10 +193,10 @@ class NativeShare extends AbstractShare {
* @param string $target remove file
* @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');
$targetUrl = $this->buildUrl($target);
@@ -215,20 +216,18 @@ class NativeShare extends AbstractShare {
* @param string $target local file
* @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) {
throw new InvalidPathException('Invalid target path: Filename cannot be empty');
}
$sourceHandle = $this->getState()->open($this->buildUrl($source), 'r');
- if (!$sourceHandle) {
- throw new InvalidResourceException('Failed opening remote file "' . $source . '" for reading');
- }
$targetHandle = @fopen($target, 'wb');
if (!$targetHandle) {
@@ -242,7 +241,7 @@ class NativeShare extends AbstractShare {
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);
}
$this->getState()->close($sourceHandle, $this->buildUrl($source));
@@ -255,10 +254,10 @@ class NativeShare extends AbstractShare {
* @param string $source
* @return resource a read only stream with the contents of the remote file
*
- * @throws \Icewind\SMB\Exception\NotFoundException
- * @throws \Icewind\SMB\Exception\InvalidTypeException
+ * @throws NotFoundException
+ * @throws InvalidTypeException
*/
- public function read($source) {
+ public function read(string $source) {
$url = $this->buildUrl($source);
$handle = $this->getState()->open($url, 'r');
return NativeReadStream::wrap($this->getState(), $handle, 'r', $url);
@@ -271,10 +270,10 @@ class NativeShare extends AbstractShare {
* @param string $source
* @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);
$handle = $this->getState()->create($url);
return NativeWriteStream::wrap($this->getState(), $handle, 'w', $url);
@@ -286,10 +285,10 @@ class NativeShare extends AbstractShare {
* @param string $source
* @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);
$handle = $this->getState()->open($url, "a+");
return NativeWriteStream::wrap($this->getState(), $handle, "a", $url);
@@ -302,7 +301,7 @@ class NativeShare extends AbstractShare {
* @param string $attribute attribute to get the info
* @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);
}
@@ -314,9 +313,13 @@ class NativeShare extends AbstractShare {
* @param string|int $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);
@@ -329,7 +332,7 @@ class NativeShare extends AbstractShare {
* @param int $mode a combination of FileInfo::MODE_READONLY, FileInfo::MODE_ARCHIVE, FileInfo::MODE_SYSTEM and FileInfo::MODE_HIDDEN, FileInfo::NORMAL
* @return mixed
*/
- public function setMode($path, $mode) {
+ public function setMode(string $path, int $mode) {
return $this->setAttribute($path, 'system.dos_attr.mode', $mode);
}
@@ -340,7 +343,7 @@ class NativeShare extends AbstractShare {
* @param string $path
* @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)
// so we use the smbclient based backend for this
if (!Server::available($this->server->getSystem())) {
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeState.php b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeState.php
index 3bfb1c3da24..10ba6ce0458 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeState.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeState.php
@@ -29,13 +29,13 @@ use Icewind\SMB\IOptions;
* Low level wrapper for libsmbclient-php with error handling
*/
class NativeState {
- /**
- * @var resource
- */
- protected $state;
+ /** @var resource|null */
+ protected $state = null;
+ /** @var bool */
protected $handlerSet = false;
+ /** @var bool */
protected $connected = false;
// see error.h
@@ -58,7 +58,8 @@ class NativeState {
113 => NoRouteToHostException::class
];
- protected function handleError($path) {
+ protected function handleError(?string $path): void {
+ /** @var int $error */
$error = smbclient_state_errno($this->state);
if ($error === 0) {
return;
@@ -66,14 +67,19 @@ class NativeState {
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) {
// smb://host/share/path
if (is_string($uri) && count(explode('/', $uri, 5)) > 4) {
list(, , , , $path) = explode('/', $uri, 5);
$path = '/' . $path;
} else {
- $path = null;
+ $path = $uri;
}
$this->handleError($path);
}
@@ -88,10 +94,21 @@ class NativeState {
if ($this->connected) {
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_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);
+ /** @var bool $result */
$result = @smbclient_state_init($this->state, $auth->getWorkgroup(), $auth->getUsername(), $auth->getPassword());
$this->testResult($result, '');
@@ -103,7 +120,8 @@ class NativeState {
* @param string $uri
* @return resource
*/
- public function opendir($uri) {
+ public function opendir(string $uri) {
+ /** @var resource $result */
$result = @smbclient_opendir($this->state, $uri);
$this->testResult($result, $uri);
@@ -112,23 +130,27 @@ class NativeState {
/**
* @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);
- $this->testResult($result, $dir);
+ $this->testResult($result, $path);
return $result;
}
/**
- * @param $dir
+ * @param resource $dir
+ * @param string $path
* @return bool
*/
- public function closedir($dir) {
+ public function closedir($dir, string $path): bool {
+ /** @var bool $result */
$result = smbclient_closedir($this->state, $dir);
- $this->testResult($result, $dir);
+ $this->testResult($result, $path);
return $result;
}
@@ -137,7 +159,8 @@ class NativeState {
* @param string $new
* @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);
$this->testResult($result, $new);
@@ -148,7 +171,8 @@ class NativeState {
* @param string $uri
* @return bool
*/
- public function unlink($uri) {
+ public function unlink(string $uri): bool {
+ /** @var bool $result */
$result = @smbclient_unlink($this->state, $uri);
$this->testResult($result, $uri);
@@ -160,7 +184,8 @@ class NativeState {
* @param int $mask
* @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);
$this->testResult($result, $uri);
@@ -171,7 +196,8 @@ class NativeState {
* @param string $uri
* @return bool
*/
- public function rmdir($uri) {
+ public function rmdir(string $uri): bool {
+ /** @var bool $result */
$result = @smbclient_rmdir($this->state, $uri);
$this->testResult($result, $uri);
@@ -180,9 +206,10 @@ class NativeState {
/**
* @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);
$this->testResult($result, $uri);
@@ -191,12 +218,14 @@ class NativeState {
/**
* @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);
- $this->testResult($result, $file);
+ $this->testResult($result, $path);
return $result;
}
@@ -206,7 +235,8 @@ class NativeState {
* @param int $mask
* @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);
$this->testResult($result, $uri);
@@ -218,7 +248,8 @@ class NativeState {
* @param int $mask
* @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);
$this->testResult($result, $uri);
@@ -228,12 +259,14 @@ class NativeState {
/**
* @param resource $file
* @param int $bytes
+ * @param string $path
* @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);
- $this->testResult($result, $file);
+ $this->testResult($result, $path);
return $result;
}
@@ -241,10 +274,11 @@ class NativeState {
* @param resource $file
* @param string $data
* @param string $path
- * @param int $length
+ * @param int|null $length
* @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);
$this->testResult($result, $path);
@@ -255,28 +289,38 @@ class NativeState {
* @param resource $file
* @param int $offset
* @param int $whence SEEK_SET | SEEK_CUR | SEEK_END
- * @return int|bool new file offset as measured from the start of the file on success, false on failure.
+ * @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);
- $this->testResult($result, $file);
+ $this->testResult($result, $path);
return $result;
}
/**
* @param resource $file
* @param int $size
+ * @param string $path
* @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);
- $this->testResult($result, $file);
+ $this->testResult($result, $path);
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);
$this->testResult($result, $path);
@@ -288,7 +332,8 @@ class NativeState {
* @param string $key
* @return string
*/
- public function getxattr($uri, $key) {
+ public function getxattr(string $uri, string $key) {
+ /** @var string $result */
$result = @smbclient_getxattr($this->state, $uri, $key);
$this->testResult($result, $uri);
@@ -300,9 +345,10 @@ class NativeState {
* @param string $key
* @param string $value
* @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);
$this->testResult($result, $uri);
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeStream.php b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeStream.php
index c75afaa5f1d..216c27f78e3 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeStream.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeStream.php
@@ -10,20 +10,24 @@ namespace Icewind\SMB\Native;
use Icewind\SMB\Exception\Exception;
use Icewind\SMB\Exception\InvalidRequestException;
use Icewind\Streams\File;
+use InvalidArgumentException;
-class NativeStream implements File {
+abstract class NativeStream implements File {
/**
* @var resource
+ * @psalm-suppress PropertyNotSetInConstructor
*/
public $context;
/**
* @var NativeState
+ * @psalm-suppress PropertyNotSetInConstructor
*/
protected $state;
/**
* @var resource
+ * @psalm-suppress PropertyNotSetInConstructor
*/
protected $handle;
@@ -35,19 +39,20 @@ class NativeStream implements File {
/**
* @var string
*/
- protected $url;
+ protected $url = '';
/**
* Wrap a stream from libsmbclient-php into a regular php stream
*
- * @param \Icewind\SMB\NativeState $state
+ * @param NativeState $state
* @param resource $smbStream
* @param string $mode
* @param string $url
+ * @param class-string<NativeStream> $class
* @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([
'nativesmb' => [
'state' => $state,
@@ -73,19 +78,35 @@ class NativeStream implements File {
}
public function stream_flush() {
+ return false;
}
public function stream_open($path, $mode, $options, &$opened_path) {
$context = stream_context_get_options($this->context);
- $this->state = $context['nativesmb']['state'];
- $this->handle = $context['nativesmb']['handle'];
- $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;
}
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) {
$this->eof = true;
}
@@ -95,12 +116,15 @@ class NativeStream implements File {
public function stream_seek($offset, $whence = SEEK_SET) {
$this->eof = false;
try {
- return $this->state->lseek($this->handle, $offset, $whence) !== false;
+ return $this->state->lseek($this->handle, $offset, $whence, $this->url) !== false;
} catch (InvalidRequestException $e) {
return false;
}
}
+ /**
+ * @return array{"mtime": int, "size": int, "mode": int}|false
+ */
public function stream_stat() {
try {
return $this->state->stat($this->url);
@@ -110,7 +134,7 @@ class NativeStream implements File {
}
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) {
@@ -118,7 +142,7 @@ class NativeStream implements File {
}
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) {
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeWriteStream.php b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeWriteStream.php
index 4e90e5a655d..7c27499764c 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeWriteStream.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeWriteStream.php
@@ -7,71 +7,63 @@
namespace Icewind\SMB\Native;
+use Icewind\SMB\StringBuffer;
+
/**
* Stream optimized for write only usage
*/
class NativeWriteStream extends NativeStream {
const CHUNK_SIZE = 1048576; // 1MB chunks
- /**
- * @var resource
- */
- private $writeBuffer = null;
- private $bufferSize = 0;
+ /** @var StringBuffer */
+ private $writeBuffer;
+ /** @var int */
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);
}
/**
* Wrap a stream from libsmbclient-php into a regular php stream
*
- * @param \Icewind\SMB\NativeState $state
+ * @param NativeState $state
* @param resource $smbStream
* @param string $mode
* @param string $url
* @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) {
$this->flushWrite();
$result = parent::stream_seek($offset, $whence);
if ($result) {
- $this->pos = parent::stream_tell();
+ $pos = parent::stream_tell();
+ if ($pos === false) {
+ return false;
+ }
+ $this->pos = $pos;
}
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) {
- $written = fwrite($this->writeBuffer, $data);
- $this->bufferSize += $written;
+ $written = $this->writeBuffer->push($data);
$this->pos += $written;
- if ($this->bufferSize >= self::CHUNK_SIZE) {
+ if ($this->writeBuffer->remaining() >= self::CHUNK_SIZE) {
$this->flushWrite();
}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Options.php b/apps/files_external/3rdparty/icewind/smb/src/Options.php
index 7a0d0149b73..f590594b993 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/Options.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/Options.php
@@ -25,11 +25,32 @@ class Options implements IOptions {
/** @var int */
private $timeout = 20;
- public function getTimeout() {
+ /** @var string|null */
+ private $minProtocol;
+ /** @var string|null */
+ private $maxProtocol;
+
+ public function getTimeout(): int {
return $this->timeout;
}
- public function setTimeout($timeout) {
+ public function setTimeout(int $timeout): void {
$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;
+ }
}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/ServerFactory.php b/apps/files_external/3rdparty/icewind/smb/src/ServerFactory.php
index 807b0b872cf..4c579d06843 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/ServerFactory.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/ServerFactory.php
@@ -31,7 +31,7 @@ class ServerFactory {
Server::class
];
- /** @var System */
+ /** @var ISystem */
private $system;
/** @var IOptions */
@@ -68,12 +68,12 @@ class ServerFactory {
/**
- * @param $host
+ * @param string $host
* @param IAuth $credentials
* @return IServer
* @throws DependencyException
*/
- public function createServer($host, IAuth $credentials) {
+ public function createServer(string $host, IAuth $credentials): IServer {
foreach (self::BACKENDS as $backend) {
if (call_user_func("$backend::available", $this->system)) {
return new $backend($host, $credentials, $this->system, $this->timeZoneProvider, $this->options);
diff --git a/apps/files_external/3rdparty/icewind/smb/src/StringBuffer.php b/apps/files_external/3rdparty/icewind/smb/src/StringBuffer.php
new file mode 100644
index 00000000000..85661218760
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/StringBuffer.php
@@ -0,0 +1,63 @@
+<?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;
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/System.php b/apps/files_external/3rdparty/icewind/smb/src/System.php
index 0e41ee032d6..919907477ab 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/System.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/System.php
@@ -10,7 +10,7 @@ namespace Icewind\SMB;
use Icewind\SMB\Exception\Exception;
class System implements ISystem {
- /** @var (string|bool)[] */
+ /** @var (string|null)[] */
private $paths = [];
/**
@@ -20,7 +20,7 @@ class System implements ISystem {
* @return string
* @throws Exception
*/
- public function getFD($num) {
+ public function getFD(int $num): string {
$folders = [
'/proc/self/fd',
'/dev/fd'
@@ -33,36 +33,36 @@ class System implements ISystem {
throw new Exception('Cant find file descriptor path');
}
- public function getSmbclientPath() {
+ public function getSmbclientPath(): ?string {
return $this->getBinaryPath('smbclient');
}
- public function getNetPath() {
+ public function getNetPath(): ?string {
return $this->getBinaryPath('net');
}
- public function getSmbcAclsPath() {
+ public function getSmbcAclsPath(): ?string {
return $this->getBinaryPath('smbcacls');
}
- public function getStdBufPath() {
+ public function getStdBufPath(): ?string {
return $this->getBinaryPath('stdbuf');
}
- public function getDatePath() {
+ public function getDatePath(): ?string {
return $this->getBinaryPath('date');
}
- public function libSmbclientAvailable() {
+ public function libSmbclientAvailable(): bool {
return function_exists('smbclient_state_new');
}
- protected function getBinaryPath($binary) {
+ protected function getBinaryPath(string $binary): ?string {
if (!isset($this->paths[$binary])) {
$result = null;
$output = [];
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];
}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/TimeZoneProvider.php b/apps/files_external/3rdparty/icewind/smb/src/TimeZoneProvider.php
index 7ae049c406f..4cd3b65681c 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/TimeZoneProvider.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/TimeZoneProvider.php
@@ -25,7 +25,7 @@ class TimeZoneProvider implements ITimeZoneProvider {
$this->system = $system;
}
- public function get($host) {
+ public function get(string $host): string {
if (!isset($this->timeZones[$host])) {
$timeZone = null;
$net = $this->system->getNetPath();
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Connection.php b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Connection.php
index 347b63db110..31b72b05d97 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Connection.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Connection.php
@@ -7,9 +7,11 @@
namespace Icewind\SMB\Wrapped;
+use Icewind\SMB\Exception\AccessDeniedException;
use Icewind\SMB\Exception\AuthenticationException;
use Icewind\SMB\Exception\ConnectException;
use Icewind\SMB\Exception\ConnectionException;
+use Icewind\SMB\Exception\ConnectionRefusedException;
use Icewind\SMB\Exception\InvalidHostException;
use Icewind\SMB\Exception\NoLoginServerException;
@@ -20,7 +22,12 @@ class Connection extends RawConnection {
/** @var 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);
$this->parser = $parser;
}
@@ -30,39 +37,48 @@ class Connection extends RawConnection {
*
* @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
*/
- public function clearTillPrompt() {
+ public function clearTillPrompt(): void {
$this->write('');
do {
$promptLine = $this->readLine();
+ if ($promptLine === false) {
+ break;
+ }
$this->parser->checkConnectionError($promptLine);
} while (!$this->isPrompt($promptLine));
- $this->write('');
+ if ($this->write('') === false) {
+ throw new ConnectionRefusedException();
+ }
$this->readLine();
}
/**
* 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[]
* @throws AuthenticationException
* @throws ConnectException
* @throws ConnectionException
* @throws InvalidHostException
* @throws NoLoginServerException
+ * @throws AccessDeniedException
*/
- public function read(callable $callback = null) {
+ public function read(callable $callback = null): array {
if (!$this->isValid()) {
throw new ConnectionException('Connection not valid');
}
$promptLine = $this->readLine(); //first line is prompt
+ if ($promptLine === false) {
+ $this->unknownError($promptLine);
+ }
$this->parser->checkConnectionError($promptLine);
$output = [];
@@ -74,7 +90,7 @@ class Connection extends RawConnection {
if ($line === false) {
$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)) {
$result = $callback($line);
if ($result === false) { // allow the callback to close the connection for infinite running commands
@@ -82,26 +98,21 @@ class Connection extends RawConnection {
break;
}
} else {
- $output[] .= $line;
+ $output[] = $line;
}
$line = $this->readLine();
}
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
+ * @return no-return
*/
private function unknownError($promptLine = '') {
if ($promptLine) { //maybe we have some error we missed on the previous line
@@ -116,7 +127,7 @@ class Connection extends RawConnection {
}
}
- public function close($terminate = true) {
+ public function close(bool $terminate = true): void {
if (get_resource_type($this->getInputStream()) === 'stream') {
// ignore any errors while trying to send the close command, the process might already be dead
@$this->write('close' . PHP_EOL);
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/FileInfo.php b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/FileInfo.php
index a310a6bc913..de5a696df7b 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/FileInfo.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/FileInfo.php
@@ -11,34 +11,17 @@ use Icewind\SMB\ACL;
use Icewind\SMB\IFileInfo;
class FileInfo implements IFileInfo {
- /**
- * @var string
- */
+ /** @var string */
protected $path;
-
- /**
- * @var string
- */
+ /** @var string */
protected $name;
-
- /**
- * @var int
- */
+ /** @var int */
protected $size;
-
- /**
- * @var int
- */
+ /** @var int */
protected $time;
-
- /**
- * @var int
- */
+ /** @var int */
protected $mode;
-
- /**
- * @var callable
- */
+ /** @var callable(): ACL[] */
protected $aclCallback;
/**
@@ -47,9 +30,9 @@ class FileInfo implements IFileInfo {
* @param int $size
* @param int $time
* @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->name = $name;
$this->size = $size;
@@ -61,63 +44,39 @@ class FileInfo implements IFileInfo {
/**
* @return string
*/
- public function getPath() {
+ public function getPath(): string {
return $this->path;
}
- /**
- * @return string
- */
- public function getName() {
+ public function getName(): string {
return $this->name;
}
- /**
- * @return int
- */
- public function getSize() {
+ public function getSize(): int {
return $this->size;
}
- /**
- * @return int
- */
- public function getMTime() {
+ public function getMTime(): int {
return $this->time;
}
- /**
- * @return bool
- */
- public function isDirectory() {
+ public function isDirectory(): bool {
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
- */
- public function isHidden() {
+ public function isHidden(): bool {
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
- */
- public function isArchived() {
+ public function isArchived(): bool {
return (bool)($this->mode & IFileInfo::MODE_ARCHIVE);
}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/NotifyHandler.php b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/NotifyHandler.php
index 090734381bb..18451f4daa6 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/NotifyHandler.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/NotifyHandler.php
@@ -14,16 +14,13 @@ use Icewind\SMB\Exception\RevisionMismatchException;
use Icewind\SMB\INotifyHandler;
class NotifyHandler implements INotifyHandler {
- /**
- * @var Connection
- */
+ /** @var Connection */
private $connection;
- /**
- * @var string
- */
+ /** @var string */
private $path;
+ /** @var bool */
private $listening = true;
// see error.h
@@ -35,7 +32,7 @@ class NotifyHandler implements INotifyHandler {
* @param Connection $connection
* @param string $path
*/
- public function __construct(Connection $connection, $path) {
+ public function __construct(Connection $connection, string $path) {
$this->connection = $connection;
$this->path = $path;
}
@@ -45,17 +42,17 @@ class NotifyHandler implements INotifyHandler {
*
* @return Change[]
*/
- public function getChanges() {
+ public function getChanges(): array {
if (!$this->listening) {
return [];
}
- stream_set_blocking($this->connection->getOutputStream(), 0);
+ stream_set_blocking($this->connection->getOutputStream(), false);
$lines = [];
while (($line = $this->connection->readLine())) {
$this->checkForError($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)));
}
@@ -64,21 +61,24 @@ class NotifyHandler implements INotifyHandler {
*
* 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) {
- $this->connection->read(function ($line) use ($callback) {
+ $this->connection->read(function (string $line) use ($callback): bool {
$this->checkForError($line);
$change = $this->parseChangeLine($line);
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);
if ($code === 0) {
return null;
@@ -91,14 +91,14 @@ class NotifyHandler implements INotifyHandler {
}
}
- private function checkForError($line) {
+ private function checkForError(string $line): void {
if (substr($line, 0, 16) === 'notify returned ') {
$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');
}
}
- public function stop() {
+ public function stop(): void {
$this->listening = false;
$this->connection->close();
}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Parser.php b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Parser.php
index a28432e4319..ec14ac4b1fb 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Parser.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Parser.php
@@ -7,6 +7,7 @@
namespace Icewind\SMB\Wrapped;
+use Icewind\SMB\ACL;
use Icewind\SMB\Exception\AccessDeniedException;
use Icewind\SMB\Exception\AlreadyExistsException;
use Icewind\SMB\Exception\AuthenticationException;
@@ -28,11 +29,6 @@ class Parser {
*/
protected $timeZone;
- /**
- * @var string
- */
- private $host;
-
// see error.h
const EXCEPTION_MAP = [
ErrorCodes::LogonFailure => AuthenticationException::class,
@@ -60,21 +56,29 @@ class Parser {
/**
* @param string $timeZone
*/
- public function __construct($timeZone) {
+ public function __construct(string $timeZone) {
$this->timeZone = $timeZone;
}
- private function getErrorCode($line) {
+ private function getErrorCode(string $line): ?string {
$parts = explode(' ', $line);
foreach ($parts as $part) {
if (substr($part, 0, 9) === 'NT_STATUS') {
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')) {
throw new NotFoundException($path);
}
@@ -91,13 +95,13 @@ class Parser {
/**
* check if the first line holds a connection failure
*
- * @param $line
+ * @param string $line
* @throws AuthenticationException
* @throws InvalidHostException
* @throws NoLoginServerException
* @throws AccessDeniedException
*/
- public function checkConnectionError($line) {
+ public function checkConnectionError(string $line): void {
$line = rtrim($line, ')');
if (substr($line, -23) === ErrorCodes::LogonFailure) {
throw new AuthenticationException('Invalid login');
@@ -119,7 +123,7 @@ class Parser {
}
}
- public function parseMode($mode) {
+ public function parseMode(string $mode): int {
$result = 0;
foreach (self::MODE_STRINGS as $char => $val) {
if (strpos($mode, $char) !== false) {
@@ -129,7 +133,12 @@ class Parser {
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 = [];
foreach ($output as $line) {
// A line = explode statement may not fill all array elements
@@ -143,14 +152,24 @@ class Parser {
$data[$name] = $value;
}
}
+ $attributeStart = strpos($data['attributes'], '(');
+ if ($attributeStart === false) {
+ throw new Exception("Malformed state response from server");
+ }
return [
'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
];
}
- 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
array_pop($output);
$regex = '/^\s*(.*?)\s\s\s\s+(?:([NDHARS]*)\s+)?([0-9]+)\s+(.*)$/';
@@ -163,7 +182,7 @@ class Parser {
$mode = $this->parseMode($mode);
$time = strtotime($time . ' ' . $this->timeZone);
$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);
});
}
@@ -172,7 +191,11 @@ class Parser {
return $content;
}
- public function parseListShares($output) {
+ /**
+ * @param string[] $output
+ * @return array<string, string>
+ */
+ public function parseListShares(array $output): array {
$shareNames = [];
foreach ($output as $line) {
if (strpos($line, '|')) {
@@ -188,4 +211,67 @@ class Parser {
}
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;
+ }
}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/RawConnection.php b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/RawConnection.php
index 3a114af5e4f..26a17cc584b 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/RawConnection.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/RawConnection.php
@@ -30,10 +30,10 @@ class RawConnection {
* $pipes[4] holds the stream for writing files
* $pipes[5] holds the stream for reading files
*/
- private $pipes;
+ private $pipes = [];
/**
- * @var resource $process
+ * @var resource|null $process
*/
private $process;
@@ -42,17 +42,20 @@ class RawConnection {
*/
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->env = $env;
}
/**
* @throws ConnectException
+ * @psalm-assert resource $this->process
*/
- public function connect() {
+ public function connect(): void {
if (is_null($this->getAuthStream())) {
throw new ConnectException('Authentication not set before connecting');
}
@@ -77,18 +80,18 @@ class RawConnection {
if (!$this->isValid()) {
throw new ConnectionException();
}
- $this->connected = true;
}
/**
* check if the connection is still active
*
* @return bool
+ * @psalm-assert-if-true resource $this->process
*/
- public function isValid() {
+ public function isValid(): bool {
if (is_resource($this->process)) {
$status = proc_get_status($this->process);
- return $status['running'];
+ return (bool)$status['running'];
} else {
return false;
}
@@ -98,10 +101,12 @@ class RawConnection {
* send input to the process
*
* @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());
+ return $result;
}
/**
@@ -116,18 +121,19 @@ class RawConnection {
/**
* read a line of output
*
- * @return string
+ * @return string|false
*/
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
*
- * @return array
+ * @return string[]
*/
- public function readAll() {
+ public function readAll(): array {
$output = [];
while ($line = $this->readLine()) {
$output[] = $line;
@@ -135,40 +141,67 @@ class RawConnection {
return $output;
}
+ /**
+ * @return resource
+ */
public function getInputStream() {
return $this->pipes[0];
}
+ /**
+ * @return resource
+ */
public function getOutputStream() {
return $this->pipes[1];
}
+ /**
+ * @return resource
+ */
public function getErrorStream() {
return $this->pipes[2];
}
+ /**
+ * @return resource|null
+ */
public function getAuthStream() {
return $this->authStream;
}
+ /**
+ * @return resource
+ */
public function getFileInputStream() {
return $this->pipes[4];
}
+ /**
+ * @return resource
+ */
public function getFileOutputStream() {
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\npassword=$password\n";
$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)) {
return;
}
@@ -176,9 +209,10 @@ class RawConnection {
proc_terminate($this->process);
}
proc_close($this->process);
+ $this->process = null;
}
- public function reconnect() {
+ public function reconnect(): void {
$this->close();
$this->connect();
}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Server.php b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Server.php
index b3763a73245..60cc9278dd9 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Server.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Server.php
@@ -11,6 +11,8 @@ use Icewind\SMB\AbstractServer;
use Icewind\SMB\Exception\AuthenticationException;
use Icewind\SMB\Exception\ConnectException;
use Icewind\SMB\Exception\ConnectionException;
+use Icewind\SMB\Exception\ConnectionRefusedException;
+use Icewind\SMB\Exception\Exception;
use Icewind\SMB\Exception\InvalidHostException;
use Icewind\SMB\IShare;
use Icewind\SMB\ISystem;
@@ -22,11 +24,11 @@ class Server extends AbstractServer {
* @param ISystem $system
* @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()) {
return '--authentication-file=' . $this->system->getFD(3);
} else {
@@ -41,22 +43,30 @@ class Server extends AbstractServer {
* @throws InvalidHostException
* @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(
- '%s %s %s -L %s',
- $this->system->getSmbclientPath(),
+ '%s %s %s %s %s -L %s',
+ $smbClient,
$this->getAuthFileArgument(),
$this->getAuth()->getExtraCommandLineArguments(),
+ $maxProtocol ? "--option='client max protocol=" . $maxProtocol . "'" : "",
+ $minProtocol ? "--option='client min protocol=" . $minProtocol . "'" : "",
escapeshellarg('//' . $this->getHost())
);
$connection = new RawConnection($command);
$connection->writeAuthentication($this->getAuth()->getUsername(), $this->getAuth()->getPassword());
$connection->connect();
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();
if (isset($output[0])) {
@@ -71,6 +81,9 @@ class Server extends AbstractServer {
if (isset($output[0])) {
$parser->checkConnectionError($output[0]);
}
+ if (count($output) === 0) {
+ throw new ConnectionRefusedException();
+ }
$shareNames = $parser->parseListShares($output);
@@ -85,7 +98,7 @@ class Server extends AbstractServer {
* @param string $name
* @return IShare
*/
- public function getShare($name) {
+ public function getShare(string $name): IShare {
return new Share($this, $name, $this->system);
}
}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Share.php b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Share.php
index ea386a87bfc..68446d380e0 100644
--- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Share.php
+++ b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Share.php
@@ -9,9 +9,14 @@ namespace Icewind\SMB\Wrapped;
use Icewind\SMB\AbstractShare;
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\DependencyException;
+use Icewind\SMB\Exception\Exception;
use Icewind\SMB\Exception\FileInUseException;
+use Icewind\SMB\Exception\InvalidHostException;
use Icewind\SMB\Exception\InvalidTypeException;
use Icewind\SMB\Exception\NotFoundException;
use Icewind\SMB\Exception\InvalidRequestException;
@@ -35,9 +40,9 @@ class Share extends AbstractShare {
private $name;
/**
- * @var Connection $connection
+ * @var Connection|null $connection
*/
- public $connection;
+ public $connection = null;
/**
* @var Parser
@@ -63,7 +68,7 @@ class Share extends AbstractShare {
* @param string $name
* @param ISystem $system
*/
- public function __construct(IServer $server, $name, ISystem $system) {
+ public function __construct(IServer $server, string $name, ISystem $system) {
parent::__construct();
$this->server = $server;
$this->name = $name;
@@ -71,7 +76,7 @@ class Share extends AbstractShare {
$this->parser = new Parser($server->getTimeZone());
}
- private function getAuthFileArgument() {
+ private function getAuthFileArgument(): string {
if ($this->server->getAuth()->getUsername()) {
return '--authentication-file=' . $this->system->getFD(3);
} else {
@@ -79,22 +84,31 @@ class Share extends AbstractShare {
}
}
- 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(
- '%s %s%s -t %s %s %s %s',
+ '%s %s%s -t %s %s %s %s %s %s',
self::EXEC_CMD,
- $this->system->getStdBufPath() ? $this->system->getStdBufPath() . ' -o0 ' : '',
- $this->system->getSmbclientPath(),
+ $stdBuf ? $stdBuf . ' -o0 ' : '',
+ $smbClient,
$this->server->getOptions()->getTimeout(),
$this->getAuthFileArgument(),
$this->server->getAuth()->getExtraCommandLineArguments(),
+ $maxProtocol ? "--option='client max protocol=" . $maxProtocol . "'" : "",
+ $minProtocol ? "--option='client min protocol=" . $minProtocol . "'" : "",
escapeshellarg('//' . $this->server->getHost() . '/' . $this->name)
);
$connection = new Connection($command, $this->parser);
$connection->writeAuthentication($this->server->getAuth()->getUsername(), $this->server->getAuth()->getPassword());
$connection->connect();
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
$connection->clearTillPrompt();
@@ -102,21 +116,33 @@ class Share extends AbstractShare {
}
/**
- * @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()) {
- return;
+ return $this->connection;
}
$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();
+ }
}
}
@@ -125,11 +151,11 @@ class Share extends AbstractShare {
*
* @return string
*/
- public function getName() {
+ public function getName(): string {
return $this->name;
}
- protected function simpleCommand($command, $path) {
+ protected function simpleCommand(string $command, string $path): bool {
$escapedPath = $this->escapePath($path);
$cmd = $command . ' ' . $escapedPath;
$output = $this->execute($cmd);
@@ -139,13 +165,13 @@ class Share extends AbstractShare {
/**
* 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);
$output = $this->execute('cd ' . $escapedPath);
//check output for errors
@@ -154,16 +180,16 @@ class Share extends AbstractShare {
$this->execute('cd /');
- return $this->parser->parseDir($output, $path, function ($path) {
+ return $this->parser->parseDir($output, $path, function (string $path) {
return $this->getAcls($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
// use the dir command instead to get the file info where possible
if ($path !== "" && $path !== "/") {
@@ -200,10 +226,10 @@ class Share extends AbstractShare {
* @param string $path
* @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);
}
@@ -213,10 +239,10 @@ class Share extends AbstractShare {
* @param string $path
* @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);
}
@@ -230,7 +256,7 @@ class Share extends AbstractShare {
* @throws NotFoundException
* @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
//we catch it so we can check if $path doesn't exist or is of invalid type
try {
@@ -261,10 +287,10 @@ class Share extends AbstractShare {
* @param string $to
* @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);
$path2 = $this->escapePath($to);
$output = $this->execute('rename ' . $path1 . ' ' . $path2);
@@ -278,10 +304,10 @@ class Share extends AbstractShare {
* @param string $target remove file
* @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
$path2 = $this->escapePath($target);
$output = $this->execute('put ' . $path1 . ' ' . $path2);
@@ -295,10 +321,10 @@ class Share extends AbstractShare {
* @param string $target local file
* @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);
$path2 = $this->escapeLocalPath($target); //second path is local, needs different escaping
$output = $this->execute('get ' . $path1 . ' ' . $path2);
@@ -311,10 +337,10 @@ class Share extends AbstractShare {
* @param string $source
* @return resource a read only stream with the contents of the remote file
*
- * @throws \Icewind\SMB\Exception\NotFoundException
- * @throws \Icewind\SMB\Exception\InvalidTypeException
+ * @throws NotFoundException
+ * @throws InvalidTypeException
*/
- public function read($source) {
+ public function read(string $source) {
$source = $this->escapePath($source);
// since returned stream is closed by the caller we need to create a new instance
// since we can't re-use the same file descriptor over multiple calls
@@ -333,10 +359,10 @@ class Share extends AbstractShare {
* @param string $target
* @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);
// 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
@@ -348,9 +374,14 @@ class Share extends AbstractShare {
// use a close callback to ensure the upload is finished before continuing
// this also serves as a way to keep the connection in scope
- return CallbackWrapper::wrap($fh, null, null, function () use ($connection, $target) {
+ $stream = CallbackWrapper::wrap($fh, null, null, function () use ($connection) {
$connection->close(false); // dont terminate, give the upload some time
});
+ if (is_resource($stream)) {
+ return $stream;
+ } else {
+ throw new InvalidRequestException($target);
+ }
}
/**
@@ -359,9 +390,9 @@ class Share extends AbstractShare {
*
* @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');
}
@@ -370,7 +401,7 @@ class Share extends AbstractShare {
* @param int $mode a combination of FileInfo::MODE_READONLY, FileInfo::MODE_ARCHIVE, FileInfo::MODE_SYSTEM and FileInfo::MODE_HIDDEN, FileInfo::NORMAL
* @return mixed
*/
- public function setMode($path, $mode) {
+ public function setMode(string $path, int $mode) {
$modeString = '';
foreach (self::MODE_MAP as $modeByte => $string) {
if ($mode & $modeByte) {
@@ -400,7 +431,7 @@ class Share extends AbstractShare {
* @throws ConnectionException
* @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
throw new DependencyException('stdbuf is required for usage of the notify command');
}
@@ -412,12 +443,11 @@ class Share extends AbstractShare {
/**
* @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();
}
/**
@@ -427,19 +457,18 @@ class Share extends AbstractShare {
* @param string $path
*
* @return bool
- * @throws \Icewind\SMB\Exception\AlreadyExistsException
+ * @throws AlreadyExistsException
* @throws \Icewind\SMB\Exception\AccessDeniedException
* @throws \Icewind\SMB\Exception\NotEmptyException
- * @throws \Icewind\SMB\Exception\InvalidTypeException
+ * @throws InvalidTypeException
* @throws \Icewind\SMB\Exception\Exception
* @throws NotFoundException
*/
- protected function parseOutput($lines, $path = '') {
+ protected function parseOutput(array $lines, string $path = ''): bool {
if (count($lines) === 0) {
return true;
} else {
$this->parser->checkForError($lines, $path);
- return false;
}
}
@@ -447,7 +476,7 @@ class Share extends AbstractShare {
* @param string $string
* @return string
*/
- protected function escape($string) {
+ protected function escape(string $string): string {
return escapeshellarg($string);
}
@@ -455,7 +484,7 @@ class Share extends AbstractShare {
* @param string $path
* @return string
*/
- protected function escapePath($path) {
+ protected function escapePath(string $path): string {
$this->verifyPath($path);
if ($path === '/') {
$path = '';
@@ -470,12 +499,18 @@ class Share extends AbstractShare {
* @param string $path
* @return string
*/
- protected function escapeLocalPath($path) {
+ protected function escapeLocalPath(string $path): string {
$path = str_replace('"', '\"', $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();
if (!$commandPath) {
return [];
@@ -494,62 +529,11 @@ class Share extends AbstractShare {
$connection->writeAuthentication($this->server->getAuth()->getUsername(), $this->server->getAuth()->getPassword());
$connection->connect();
if (!$connection->isValid()) {
- throw new ConnectionException($connection->readLine());
+ throw new ConnectionException((string)$connection->readLine());
}
$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 {