diff options
Diffstat (limited to 'apps/files_external/3rdparty/icewind/smb/src/Wrapped')
8 files changed, 0 insertions, 1533 deletions
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Connection.php b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Connection.php deleted file mode 100644 index cc73ac1ad14..00000000000 --- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Connection.php +++ /dev/null @@ -1,116 +0,0 @@ -<?php -/** - * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com> - * This file is licensed under the Licensed under the MIT license: - * http://opensource.org/licenses/MIT - */ - -namespace Icewind\SMB\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; - -class Connection extends RawConnection { - const DELIMITER = 'smb:'; - const DELIMITER_LENGTH = 4; - - /** @var Parser */ - private $parser; - - /** - * @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; - } - - /** - * send input to smbclient - * - * @param string $input - */ - public function write(string $input) { - return parent::write($input . PHP_EOL); - } - - /** - * @throws ConnectException - */ - public function clearTillPrompt(): void { - $this->write(''); - do { - $promptLine = $this->readTillPrompt(); - if ($promptLine === false) { - break; - } - $this->parser->checkConnectionError($promptLine); - } while (!$this->isPrompt($promptLine)); - if ($this->write('') === false) { - throw new ConnectionRefusedException(); - } - $this->readTillPrompt(); - } - - /** - * get all unprocessed output from smbclient until the next prompt - * - * @return string[] - * @throws AuthenticationException - * @throws ConnectException - * @throws ConnectionException - * @throws InvalidHostException - * @throws NoLoginServerException - * @throws AccessDeniedException - */ - public function read(): array { - if (!$this->isValid()) { - throw new ConnectionException('Connection not valid'); - } - $output = $this->readTillPrompt(); - if ($output === false) { - $this->unknownError(false); - } - $output = explode("\n", $output); - // last line contains the prompt - array_pop($output); - return $output; - } - - private function isPrompt(string $line): bool { - return substr($line, 0, self::DELIMITER_LENGTH) === self::DELIMITER; - } - - /** - * @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 - throw new ConnectException('Unknown error (' . $promptLine . ')'); - } else { - $error = $this->readError(); // maybe something on stderr - if ($error) { - throw new ConnectException('Unknown error (' . $error . ')'); - } else { - throw new ConnectException('Unknown error'); - } - } - } - - 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); - } - $this->close_process($terminate); - } -} diff --git a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/ErrorCodes.php b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/ErrorCodes.php deleted file mode 100644 index 7df83b268d8..00000000000 --- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/ErrorCodes.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php -/** - * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com> - * This file is licensed under the Licensed under the MIT license: - * http://opensource.org/licenses/MIT - */ - -namespace Icewind\SMB\Wrapped; - -class ErrorCodes { - /** - * connection errors - */ - const LogonFailure = 'NT_STATUS_LOGON_FAILURE'; - const BadHostName = 'NT_STATUS_BAD_NETWORK_NAME'; - const Unsuccessful = 'NT_STATUS_UNSUCCESSFUL'; - const ConnectionRefused = 'NT_STATUS_CONNECTION_REFUSED'; - const NoLogonServers = 'NT_STATUS_NO_LOGON_SERVERS'; - - const PathNotFound = 'NT_STATUS_OBJECT_PATH_NOT_FOUND'; - const NoSuchFile = 'NT_STATUS_NO_SUCH_FILE'; - const ObjectNotFound = 'NT_STATUS_OBJECT_NAME_NOT_FOUND'; - const NameCollision = 'NT_STATUS_OBJECT_NAME_COLLISION'; - const AccessDenied = 'NT_STATUS_ACCESS_DENIED'; - const DirectoryNotEmpty = 'NT_STATUS_DIRECTORY_NOT_EMPTY'; - const FileIsADirectory = 'NT_STATUS_FILE_IS_A_DIRECTORY'; - const NotADirectory = 'NT_STATUS_NOT_A_DIRECTORY'; - const SharingViolation = 'NT_STATUS_SHARING_VIOLATION'; - const InvalidParameter = 'NT_STATUS_INVALID_PARAMETER'; - const RevisionMismatch = 'NT_STATUS_REVISION_MISMATCH'; -} diff --git a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/FileInfo.php b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/FileInfo.php deleted file mode 100644 index de5a696df7b..00000000000 --- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/FileInfo.php +++ /dev/null @@ -1,89 +0,0 @@ -<?php -/** - * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com> - * This file is licensed under the Licensed under the MIT license: - * http://opensource.org/licenses/MIT - */ - -namespace Icewind\SMB\Wrapped; - -use Icewind\SMB\ACL; -use Icewind\SMB\IFileInfo; - -class FileInfo implements IFileInfo { - /** @var string */ - protected $path; - /** @var string */ - protected $name; - /** @var int */ - protected $size; - /** @var int */ - protected $time; - /** @var int */ - protected $mode; - /** @var callable(): ACL[] */ - protected $aclCallback; - - /** - * @param string $path - * @param string $name - * @param int $size - * @param int $time - * @param int $mode - * @param callable(): ACL[] $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; - $this->time = $time; - $this->mode = $mode; - $this->aclCallback = $aclCallback; - } - - /** - * @return string - */ - public function getPath(): string { - return $this->path; - } - - public function getName(): string { - return $this->name; - } - - public function getSize(): int { - return $this->size; - } - - public function getMTime(): int { - return $this->time; - } - - public function isDirectory(): bool { - return (bool)($this->mode & IFileInfo::MODE_DIRECTORY); - } - - public function isReadOnly(): bool { - return (bool)($this->mode & IFileInfo::MODE_READONLY); - } - - public function isHidden(): bool { - return (bool)($this->mode & IFileInfo::MODE_HIDDEN); - } - - public function isSystem(): bool { - return (bool)($this->mode & IFileInfo::MODE_SYSTEM); - } - - public function isArchived(): bool { - return (bool)($this->mode & IFileInfo::MODE_ARCHIVE); - } - - /** - * @return ACL[] - */ - public function getAcls(): array { - return ($this->aclCallback)(); - } -} diff --git a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/NotifyHandler.php b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/NotifyHandler.php deleted file mode 100644 index ecb5bb1e3c1..00000000000 --- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/NotifyHandler.php +++ /dev/null @@ -1,113 +0,0 @@ -<?php -/** - * @copyright Copyright (c) 2016 Robin Appelman <robin@icewind.nl> - * This file is licensed under the Licensed under the MIT license: - * http://opensource.org/licenses/MIT - * - */ - -namespace Icewind\SMB\Wrapped; - -use Icewind\SMB\Change; -use Icewind\SMB\Exception\Exception; -use Icewind\SMB\Exception\RevisionMismatchException; -use Icewind\SMB\INotifyHandler; - -class NotifyHandler implements INotifyHandler { - /** @var Connection */ - private $connection; - - /** @var string */ - private $path; - - /** @var bool */ - private $listening = true; - - // see error.h - const EXCEPTION_MAP = [ - ErrorCodes::RevisionMismatch => RevisionMismatchException::class, - ]; - - /** - * @param Connection $connection - * @param string $path - */ - public function __construct(Connection $connection, string $path) { - $this->connection = $connection; - $this->path = $path; - } - - /** - * Get all changes detected since the start of the notify process or the last call to getChanges - * - * @return Change[] - */ - public function getChanges(): array { - if (!$this->listening) { - return []; - } - stream_set_blocking($this->connection->getOutputStream(), false); - $lines = []; - while (($line = $this->connection->readLine())) { - $this->checkForError($line); - $lines[] = $line; - } - stream_set_blocking($this->connection->getOutputStream(), true); - return array_values(array_filter(array_map([$this, 'parseChangeLine'], $lines))); - } - - /** - * 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(Change):?bool $callback - */ - public function listen(callable $callback): void { - if ($this->listening) { - while (true) { - $line = $this->connection->readLine(); - if ($line === false) { - break; - } - $this->checkForError($line); - $change = $this->parseChangeLine($line); - if ($change) { - $result = $callback($change); - if ($result === false) { - break; - } - } - }; - } - } - - private function parseChangeLine(string $line): ?Change { - $code = (int)substr($line, 0, 4); - if ($code === 0) { - return null; - } - $subPath = str_replace('\\', '/', substr($line, 5)); - if ($this->path === '') { - return new Change($code, $subPath); - } else { - return new Change($code, $this->path . '/' . $subPath); - } - } - - 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(): void { - $this->listening = false; - $this->connection->close(); - } - - public function __destruct() { - $this->stop(); - } -} diff --git a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Parser.php b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Parser.php deleted file mode 100644 index ec14ac4b1fb..00000000000 --- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Parser.php +++ /dev/null @@ -1,277 +0,0 @@ -<?php -/** - * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com> - * This file is licensed under the Licensed under the MIT license: - * http://opensource.org/licenses/MIT - */ - -namespace Icewind\SMB\Wrapped; - -use Icewind\SMB\ACL; -use Icewind\SMB\Exception\AccessDeniedException; -use Icewind\SMB\Exception\AlreadyExistsException; -use Icewind\SMB\Exception\AuthenticationException; -use Icewind\SMB\Exception\Exception; -use Icewind\SMB\Exception\FileInUseException; -use Icewind\SMB\Exception\InvalidHostException; -use Icewind\SMB\Exception\InvalidParameterException; -use Icewind\SMB\Exception\InvalidResourceException; -use Icewind\SMB\Exception\InvalidTypeException; -use Icewind\SMB\Exception\NoLoginServerException; -use Icewind\SMB\Exception\NotEmptyException; -use Icewind\SMB\Exception\NotFoundException; - -class Parser { - const MSG_NOT_FOUND = 'Error opening local file '; - - /** - * @var string - */ - protected $timeZone; - - // see error.h - const EXCEPTION_MAP = [ - ErrorCodes::LogonFailure => AuthenticationException::class, - ErrorCodes::PathNotFound => NotFoundException::class, - ErrorCodes::ObjectNotFound => NotFoundException::class, - ErrorCodes::NoSuchFile => NotFoundException::class, - ErrorCodes::NameCollision => AlreadyExistsException::class, - ErrorCodes::AccessDenied => AccessDeniedException::class, - ErrorCodes::DirectoryNotEmpty => NotEmptyException::class, - ErrorCodes::FileIsADirectory => InvalidTypeException::class, - ErrorCodes::NotADirectory => InvalidTypeException::class, - ErrorCodes::SharingViolation => FileInUseException::class, - ErrorCodes::InvalidParameter => InvalidParameterException::class - ]; - - const MODE_STRINGS = [ - 'R' => FileInfo::MODE_READONLY, - 'H' => FileInfo::MODE_HIDDEN, - 'S' => FileInfo::MODE_SYSTEM, - 'D' => FileInfo::MODE_DIRECTORY, - 'A' => FileInfo::MODE_ARCHIVE, - 'N' => FileInfo::MODE_NORMAL - ]; - - /** - * @param string $timeZone - */ - public function __construct(string $timeZone) { - $this->timeZone = $timeZone; - } - - private function getErrorCode(string $line): ?string { - $parts = explode(' ', $line); - foreach ($parts as $part) { - if (substr($part, 0, 9) === 'NT_STATUS') { - return $part; - } - } - return null; - } - - /** - * @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); - } - $error = $this->getErrorCode($output[0]); - - if (substr($output[0], 0, strlen(self::MSG_NOT_FOUND)) === self::MSG_NOT_FOUND) { - $localPath = substr($output[0], strlen(self::MSG_NOT_FOUND)); - throw new InvalidResourceException('Failed opening local file "' . $localPath . '" for writing'); - } - - throw Exception::fromMap(self::EXCEPTION_MAP, $error, $path); - } - - /** - * check if the first line holds a connection failure - * - * @param string $line - * @throws AuthenticationException - * @throws InvalidHostException - * @throws NoLoginServerException - * @throws AccessDeniedException - */ - public function checkConnectionError(string $line): void { - $line = rtrim($line, ')'); - if (substr($line, -23) === ErrorCodes::LogonFailure) { - throw new AuthenticationException('Invalid login'); - } - if (substr($line, -26) === ErrorCodes::BadHostName) { - throw new InvalidHostException('Invalid hostname'); - } - if (substr($line, -22) === ErrorCodes::Unsuccessful) { - throw new InvalidHostException('Connection unsuccessful'); - } - if (substr($line, -28) === ErrorCodes::ConnectionRefused) { - throw new InvalidHostException('Connection refused'); - } - if (substr($line, -26) === ErrorCodes::NoLogonServers) { - throw new NoLoginServerException('No login server'); - } - if (substr($line, -23) === ErrorCodes::AccessDenied) { - throw new AccessDeniedException('Access denied'); - } - } - - public function parseMode(string $mode): int { - $result = 0; - foreach (self::MODE_STRINGS as $char => $val) { - if (strpos($mode, $char) !== false) { - $result |= $val; - } - } - return $result; - } - - /** - * @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 - // properly. May happen when accessing non Windows Fileservers - $words = explode(':', $line, 2); - $name = isset($words[0]) ? $words[0] : ''; - $value = isset($words[1]) ? $words[1] : ''; - $value = trim($value); - - if (!isset($data[$name])) { - $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'], $attributeStart + 1, -1)), - 'size' => isset($data['stream']) ? (int)(explode(' ', $data['stream'])[1]) : 0 - ]; - } - - /** - * @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+(.*)$/'; - //2 spaces, filename, optional type, size, date - $content = []; - foreach ($output as $line) { - if (preg_match($regex, $line, $matches)) { - list(, $name, $mode, $size, $time) = $matches; - if ($name !== '.' and $name !== '..') { - $mode = $this->parseMode($mode); - $time = strtotime($time . ' ' . $this->timeZone); - $path = $basePath . '/' . $name; - $content[] = new FileInfo($path, $name, (int)$size, $time, $mode, function () use ($aclCallback, $path): array { - return $aclCallback($path); - }); - } - } - } - return $content; - } - - /** - * @param string[] $output - * @return array<string, string> - */ - public function parseListShares(array $output): array { - $shareNames = []; - foreach ($output as $line) { - if (strpos($line, '|')) { - list($type, $name, $description) = explode('|', $line); - if (strtolower($type) === 'disk') { - $shareNames[$name] = $description; - } - } elseif (strpos($line, 'Disk')) { - // new output format - list($name, $description) = explode('Disk', $line); - $shareNames[trim($name)] = trim($description); - } - } - 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 deleted file mode 100644 index 4aec674c3da..00000000000 --- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/RawConnection.php +++ /dev/null @@ -1,249 +0,0 @@ -<?php -/** - * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com> - * This file is licensed under the Licensed under the MIT license: - * http://opensource.org/licenses/MIT - */ - -namespace Icewind\SMB\Wrapped; - -use Icewind\SMB\Exception\ConnectException; -use Icewind\SMB\Exception\ConnectionException; - -class RawConnection { - /** - * @var string - */ - private $command; - - /** - * @var string[] - */ - private $env; - - /** - * @var resource[] $pipes - * - * $pipes[0] holds STDIN for smbclient - * $pipes[1] holds STDOUT for smbclient - * $pipes[3] holds the authfile for smbclient - * $pipes[4] holds the stream for writing files - * $pipes[5] holds the stream for reading files - */ - private $pipes = []; - - /** - * @var resource|null $process - */ - private $process; - - /** - * @var resource|null $authStream - */ - private $authStream = null; - - /** - * @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(): void { - if (is_null($this->getAuthStream())) { - throw new ConnectException('Authentication not set before connecting'); - } - - $descriptorSpec = [ - 0 => ['pipe', 'r'], // child reads from stdin - 1 => ['pipe', 'w'], // child writes to stdout - 2 => ['pipe', 'w'], // child writes to stderr - 3 => $this->getAuthStream(), // child reads from fd#3 - 4 => ['pipe', 'r'], // child reads from fd#4 - 5 => ['pipe', 'w'] // child writes to fd#5 - ]; - - setlocale(LC_ALL, Server::LOCALE); - $env = array_merge($this->env, [ - 'CLI_FORCE_INTERACTIVE' => 'y', // Make sure the prompt is displayed - 'CLI_NO_READLINE' => 1, // Not all distros build smbclient with readline, disable it to get consistent behaviour - 'LC_ALL' => Server::LOCALE, - 'LANG' => Server::LOCALE, - 'COLUMNS' => 8192 // prevent smbclient from line-wrapping it's output - ]); - $this->process = proc_open($this->command, $descriptorSpec, $this->pipes, '/', $env); - if (!$this->isValid()) { - throw new ConnectionException(); - } - } - - /** - * check if the connection is still active - * - * @return bool - * @psalm-assert-if-true resource $this->process - */ - public function isValid(): bool { - if (is_resource($this->process)) { - $status = proc_get_status($this->process); - return $status['running']; - } else { - return false; - } - } - - /** - * send input to the process - * - * @param string $input - * @return int|bool - */ - public function write(string $input) { - $result = @fwrite($this->getInputStream(), $input); - fflush($this->getInputStream()); - return $result; - } - - /** - * read output till the next prompt - * - * @return string|false - */ - public function readTillPrompt() { - $output = ""; - do { - $chunk = $this->readLine('\> '); - if ($chunk === false) { - return false; - } - $output .= $chunk; - } while (strlen($chunk) == 4096 && strpos($chunk, "smb:") === false); - return $output; - } - - /** - * read a line of output - * - * @return string|false - */ - public function readLine(string $end = "\n") { - return stream_get_line($this->getOutputStream(), 4096, $end); - } - - /** - * read a line of output - * - * @return string|false - */ - public function readError() { - $line = stream_get_line($this->getErrorStream(), 4086); - return $line !== false ? trim($line) : false; - } - - /** - * get all output until the process closes - * - * @return string[] - */ - public function readAll(): array { - $output = []; - while ($line = $this->readLine()) { - $output[] = $line; - } - 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]; - } - - /** - * @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->authStream, $auth); - } - - /** - * @param bool $terminate - * @psalm-assert null $this->process - */ - public function close(bool $terminate = true): void { - $this->close_process($terminate); - } - - /** - * @param bool $terminate - * @psalm-assert null $this->process - */ - protected function close_process(bool $terminate = true): void { - if (!is_resource($this->process)) { - return; - } - if ($terminate) { - proc_terminate($this->process); - } - proc_close($this->process); - $this->process = null; - } - - public function reconnect(): void { - $this->close(); - $this->connect(); - } - - public function __destruct() { - $this->close(); - } -} diff --git a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Server.php b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Server.php deleted file mode 100644 index dd8513eafd9..00000000000 --- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Server.php +++ /dev/null @@ -1,104 +0,0 @@ -<?php -/** - * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com> - * This file is licensed under the Licensed under the MIT license: - * http://opensource.org/licenses/MIT - */ - -namespace Icewind\SMB\Wrapped; - -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; - -class Server extends AbstractServer { - /** - * Check if the smbclient php extension is available - * - * @param ISystem $system - * @return bool - */ - public static function available(ISystem $system): bool { - return $system->getSmbclientPath() !== null; - } - - private function getAuthFileArgument(): string { - if ($this->getAuth()->getUsername()) { - return '--authentication-file=' . $this->system->getFD(3); - } else { - return ''; - } - } - - /** - * @return IShare[] - * - * @throws AuthenticationException - * @throws InvalidHostException - * @throws ConnectException - */ - 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 %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((string)$connection->readLine()); - } - - $parser = new Parser($this->timezoneProvider->get($this->host)); - - $output = $connection->readAll(); - if (isset($output[0])) { - $parser->checkConnectionError($output[0]); - } - - // sometimes we get an empty line first - if (count($output) < 2) { - $output = $connection->readAll(); - } - - if (isset($output[0])) { - $parser->checkConnectionError($output[0]); - } - if (count($output) === 0) { - throw new ConnectionRefusedException(); - } - - $shareNames = $parser->parseListShares($output); - - $shares = []; - foreach ($shareNames as $name => $_description) { - $shares[] = $this->getShare($name); - } - return $shares; - } - - /** - * @param string $name - * @return IShare - */ - 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 deleted file mode 100644 index eb68d3800b3..00000000000 --- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Share.php +++ /dev/null @@ -1,554 +0,0 @@ -<?php -/** - * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com> - * This file is licensed under the Licensed under the MIT license: - * http://opensource.org/licenses/MIT - */ - -namespace Icewind\SMB\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; -use Icewind\SMB\IFileInfo; -use Icewind\SMB\INotifyHandler; -use Icewind\SMB\IServer; -use Icewind\SMB\ISystem; -use Icewind\Streams\CallbackWrapper; -use Icewind\SMB\Native\NativeShare; -use Icewind\SMB\Native\NativeServer; - -class Share extends AbstractShare { - /** - * @var IServer $server - */ - private $server; - - /** - * @var string $name - */ - private $name; - - /** - * @var Connection|null $connection - */ - public $connection = null; - - /** - * @var Parser - */ - protected $parser; - - /** - * @var ISystem - */ - private $system; - - const MODE_MAP = [ - FileInfo::MODE_READONLY => 'r', - FileInfo::MODE_HIDDEN => 'h', - FileInfo::MODE_ARCHIVE => 'a', - FileInfo::MODE_SYSTEM => 's' - ]; - - const EXEC_CMD = 'exec'; - - /** - * @param IServer $server - * @param string $name - * @param ISystem $system - */ - public function __construct(IServer $server, string $name, ISystem $system) { - parent::__construct(); - $this->server = $server; - $this->name = $name; - $this->system = $system; - $this->parser = new Parser($server->getTimeZone()); - } - - private function getAuthFileArgument(): string { - if ($this->server->getAuth()->getUsername()) { - return '--authentication-file=' . $this->system->getFD(3); - } else { - return ''; - } - } - - 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', - self::EXEC_CMD, - $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((string)$connection->readLine()); - } - // some versions of smbclient add a help message in first of the first prompt - $connection->clearTillPrompt(); - return $connection; - } - - /** - * @throws ConnectionException - * @throws AuthenticationException - * @throws InvalidHostException - * @psalm-assert Connection $this->connection - */ - protected function connect(): Connection { - if ($this->connection and $this->connection->isValid()) { - return $this->connection; - } - $this->connection = $this->getConnection(); - return $this->connection; - } - - /** - * @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(); - } - } - } - - /** - * Get the name of the share - * - * @return string - */ - public function getName(): string { - return $this->name; - } - - protected function simpleCommand(string $command, string $path): bool { - $escapedPath = $this->escapePath($path); - $cmd = $command . ' ' . $escapedPath; - $output = $this->execute($cmd); - return $this->parseOutput($output, $path); - } - - /** - * List the content of a remote folder - * - * @param string $path - * @return IFileInfo[] - * - * @throws NotFoundException - * @throws InvalidTypeException - */ - public function dir(string $path): array { - $escapedPath = $this->escapePath($path); - $output = $this->execute('cd ' . $escapedPath); - //check output for errors - $this->parseOutput($output, $path); - $output = $this->execute('dir'); - - $this->execute('cd /'); - - return $this->parser->parseDir($output, $path, function (string $path) { - return $this->getAcls($path); - }); - } - - /** - * @param string $path - * @return IFileInfo - */ - 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 !== "/") { - $parent = dirname($path); - $dir = $this->dir($parent); - $file = array_values(array_filter($dir, function (IFileInfo $info) use ($path) { - return $info->getPath() === $path; - })); - if ($file) { - return $file[0]; - } - } - - $escapedPath = $this->escapePath($path); - $output = $this->execute('allinfo ' . $escapedPath); - // Windows and non Windows Fileserver may respond different - // to the allinfo command for directories. If the result is a single - // line = error line, redo it with a different allinfo parameter - if ($escapedPath == '""' && count($output) < 2) { - $output = $this->execute('allinfo ' . '"."'); - } - if (count($output) < 3) { - $this->parseOutput($output, $path); - } - $stat = $this->parser->parseStat($output); - return new FileInfo($path, basename($path), $stat['size'], $stat['mtime'], $stat['mode'], function () use ($path) { - return $this->getAcls($path); - }); - } - - /** - * Create a folder on the share - * - * @param string $path - * @return bool - * - * @throws NotFoundException - * @throws AlreadyExistsException - */ - public function mkdir(string $path): bool { - return $this->simpleCommand('mkdir', $path); - } - - /** - * Remove a folder on the share - * - * @param string $path - * @return bool - * - * @throws NotFoundException - * @throws InvalidTypeException - */ - public function rmdir(string $path): bool { - return $this->simpleCommand('rmdir', $path); - } - - /** - * Delete a file on the share - * - * @param string $path - * @param bool $secondTry - * @return bool - * @throws InvalidTypeException - * @throws NotFoundException - * @throws \Exception - */ - public function del(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 { - return $this->simpleCommand('del', $path); - } catch (NotFoundException $e) { - //no need to do anything with the result, we just check if this throws the not found error - try { - $this->simpleCommand('ls', $path); - } catch (NotFoundException $e2) { - throw $e; - } catch (\Exception $e2) { - throw new InvalidTypeException($path); - } - throw $e; - } catch (FileInUseException $e) { - if ($secondTry) { - throw $e; - } - $this->reconnect(); - return $this->del($path, true); - } - } - - /** - * Rename a remote file - * - * @param string $from - * @param string $to - * @return bool - * - * @throws NotFoundException - * @throws AlreadyExistsException - */ - public function rename(string $from, string $to): bool { - $path1 = $this->escapePath($from); - $path2 = $this->escapePath($to); - $output = $this->execute('rename ' . $path1 . ' ' . $path2); - return $this->parseOutput($output, $to); - } - - /** - * Upload a local file - * - * @param string $source local file - * @param string $target remove file - * @return bool - * - * @throws NotFoundException - * @throws InvalidTypeException - */ - 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); - return $this->parseOutput($output, $target); - } - - /** - * Download a remote file - * - * @param string $source remove file - * @param string $target local file - * @return bool - * - * @throws NotFoundException - * @throws InvalidTypeException - */ - 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); - return $this->parseOutput($output, $source); - } - - /** - * Open a readable stream to a remote file - * - * @param string $source - * @return resource a read only stream with the contents of the remote file - * - * @throws NotFoundException - * @throws InvalidTypeException - */ - 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 - $connection = $this->getConnection(); - stream_set_blocking($connection->getOutputStream(), false); - - $connection->write('get ' . $source . ' ' . $this->system->getFD(5)); - $connection->write('exit'); - $fh = $connection->getFileOutputStream(); - $fh = CallbackWrapper::wrap($fh, function() use ($connection) { - $connection->write(''); - }); - if (!is_resource($fh)) { - throw new Exception("Failed to wrap file output"); - } - return $fh; - } - - /** - * Open a writable stream to a remote file - * - * @param string $target - * @return resource a write only stream to upload a remote file - * - * @throws NotFoundException - * @throws InvalidTypeException - */ - 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 - $connection = $this->getConnection(); - - $fh = $connection->getFileInputStream(); - $connection->write('put ' . $this->system->getFD(4) . ' ' . $target); - $connection->write('exit'); - - // use a close callback to ensure the upload is finished before continuing - // this also serves as a way to keep the connection in scope - $stream = CallbackWrapper::wrap($fh, function() use ($connection) { - $connection->write(''); - }, 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); - } - } - - /** - * Append to stream - * Note: smbclient does not support this (Use php-libsmbclient) - * - * @param string $target - * - * @throws DependencyException - */ - public function append(string $target) { - throw new DependencyException('php-libsmbclient is required for append'); - } - - /** - * @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(string $path, int $mode) { - $modeString = ''; - foreach (self::MODE_MAP as $modeByte => $string) { - if ($mode & $modeByte) { - $modeString .= $string; - } - } - $path = $this->escapePath($path); - - // first reset the mode to normal - $cmd = 'setmode ' . $path . ' -rsha'; - $output = $this->execute($cmd); - $this->parseOutput($output, $path); - - if ($mode !== FileInfo::MODE_NORMAL) { - // then set the modes we want - $cmd = 'setmode ' . $path . ' ' . $modeString; - $output = $this->execute($cmd); - return $this->parseOutput($output, $path); - } else { - return true; - } - } - - /** - * @param string $path - * @return INotifyHandler - * @throws ConnectionException - * @throws DependencyException - */ - 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'); - } - $connection = $this->getConnection(); // use a fresh connection since the notify command blocks the process - $command = 'notify ' . $this->escapePath($path); - $connection->write($command . PHP_EOL); - return new NotifyHandler($connection, $path); - } - - /** - * @param string $command - * @return string[] - */ - protected function execute(string $command): array { - $this->connect()->write($command); - return $this->connect()->read(); - } - - /** - * check output for errors - * - * @param string[] $lines - * @param string $path - * - * @return bool - * @throws AlreadyExistsException - * @throws \Icewind\SMB\Exception\AccessDeniedException - * @throws \Icewind\SMB\Exception\NotEmptyException - * @throws InvalidTypeException - * @throws \Icewind\SMB\Exception\Exception - * @throws NotFoundException - */ - protected function parseOutput(array $lines, string $path = ''): bool { - if (count($lines) === 0) { - return true; - } else { - $this->parser->checkForError($lines, $path); - } - } - - /** - * @param string $string - * @return string - */ - protected function escape(string $string): string { - return escapeshellarg($string); - } - - /** - * @param string $path - * @return string - */ - protected function escapePath(string $path): string { - $this->verifyPath($path); - if ($path === '/') { - $path = ''; - } - $path = str_replace('/', '\\', $path); - $path = str_replace('"', '^"', $path); - $path = ltrim($path, '\\'); - return '"' . $path . '"'; - } - - /** - * @param string $path - * @return string - */ - protected function escapeLocalPath(string $path): string { - $path = str_replace('"', '\"', $path); - return '"' . $path . '"'; - } - - /** - * @param string $path - * @return ACL[] - * @throws ConnectionException - * @throws ConnectException - */ - protected function getAcls(string $path): array { - $commandPath = $this->system->getSmbcAclsPath(); - if (!$commandPath) { - return []; - } - - $command = sprintf( - '%s %s %s %s/%s %s', - $commandPath, - $this->getAuthFileArgument(), - $this->server->getAuth()->getExtraCommandLineArguments(), - escapeshellarg('//' . $this->server->getHost()), - escapeshellarg($this->name), - escapeshellarg($path) - ); - $connection = new RawConnection($command); - $connection->writeAuthentication($this->server->getAuth()->getUsername(), $this->server->getAuth()->getPassword()); - $connection->connect(); - if (!$connection->isValid()) { - throw new ConnectionException((string)$connection->readLine()); - } - - $rawAcls = $connection->readAll(); - return $this->parser->parseACLs($rawAcls); - } - - public function getServer(): IServer { - return $this->server; - } - - public function __destruct() { - unset($this->connection); - } -} |