diff options
Diffstat (limited to 'apps/files_external/3rdparty/icewind/smb/src/Wrapped')
4 files changed, 61 insertions, 44 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 index 31b72b05d97..cc73ac1ad14 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Connection.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Connection.php @@ -47,7 +47,7 @@ class Connection extends RawConnection { public function clearTillPrompt(): void { $this->write(''); do { - $promptLine = $this->readLine(); + $promptLine = $this->readTillPrompt(); if ($promptLine === false) { break; } @@ -56,13 +56,12 @@ class Connection extends RawConnection { if ($this->write('') === false) { throw new ConnectionRefusedException(); } - $this->readLine(); + $this->readTillPrompt(); } /** * get all unprocessed output from smbclient until the next prompt * - * @param (callable(string):bool)|null $callback (optional) callback to call for every line read * @return string[] * @throws AuthenticationException * @throws ConnectException @@ -71,42 +70,22 @@ class Connection extends RawConnection { * @throws NoLoginServerException * @throws AccessDeniedException */ - public function read(callable $callback = null): array { + public function read(): 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 = []; - if (!$this->isPrompt($promptLine)) { - $line = $promptLine; - } else { - $line = $this->readLine(); - } - if ($line === false) { - $this->unknownError($promptLine); - } - 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 - $this->close(true); - break; - } - } else { - $output[] = $line; - } - $line = $this->readLine(); + $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 mb_substr($line, 0, self::DELIMITER_LENGTH) === self::DELIMITER; + return substr($line, 0, self::DELIMITER_LENGTH) === self::DELIMITER; } /** @@ -132,6 +111,6 @@ class Connection extends RawConnection { // ignore any errors while trying to send the close command, the process might already be dead @$this->write('close' . PHP_EOL); } - parent::close($terminate); + $this->close_process($terminate); } } 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 18451f4daa6..ecb5bb1e3c1 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/NotifyHandler.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/NotifyHandler.php @@ -65,16 +65,20 @@ class NotifyHandler implements INotifyHandler { */ public function listen(callable $callback): void { if ($this->listening) { - $this->connection->read(function (string $line) use ($callback): bool { + while (true) { + $line = $this->connection->readLine(); + if ($line === false) { + break; + } $this->checkForError($line); $change = $this->parseChangeLine($line); if ($change) { $result = $callback($change); - return $result === false ? false : true; - } else { - return true; + if ($result === false) { + break; + } } - }); + }; } } 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 26a17cc584b..4aec674c3da 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/RawConnection.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/RawConnection.php @@ -71,7 +71,8 @@ class RawConnection { setlocale(LC_ALL, Server::LOCALE); $env = array_merge($this->env, [ - 'CLI_FORCE_INTERACTIVE' => 'y', // Needed or the prompt isn't displayed!! + '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 @@ -91,7 +92,7 @@ class RawConnection { public function isValid(): bool { if (is_resource($this->process)) { $status = proc_get_status($this->process); - return (bool)$status['running']; + return $status['running']; } else { return false; } @@ -110,12 +111,29 @@ class RawConnection { } /** + * 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() { - return stream_get_line($this->getOutputStream(), 4086, "\n"); + public function readLine(string $end = "\n") { + return stream_get_line($this->getOutputStream(), 4096, $end); } /** @@ -202,6 +220,14 @@ class RawConnection { * @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; } 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 68446d380e0..eb68d3800b3 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Share.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Share.php @@ -345,11 +345,17 @@ class Share extends AbstractShare { // 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(); - stream_context_set_option($fh, 'file', 'connection', $connection); + $fh = CallbackWrapper::wrap($fh, function() use ($connection) { + $connection->write(''); + }); + if (!is_resource($fh)) { + throw new Exception("Failed to wrap file output"); + } return $fh; } @@ -374,7 +380,9 @@ 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 - $stream = CallbackWrapper::wrap($fh, null, null, function () use ($connection) { + $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)) { @@ -446,7 +454,7 @@ class Share extends AbstractShare { * @return string[] */ protected function execute(string $command): array { - $this->connect()->write($command . PHP_EOL); + $this->connect()->write($command); return $this->connect()->read(); } |