diff options
author | Robin Appelman <robin@icewind.nl> | 2023-08-31 15:39:56 +0200 |
---|---|---|
committer | Robin Appelman <robin@icewind.nl> | 2023-09-04 16:30:11 +0200 |
commit | aa2a3ae6c8c7d5edf99a194a430bf6cccd102e39 (patch) | |
tree | b8475e9754c5e588a048f394aa88f486b58c6193 /apps/files_external | |
parent | b41c8e0ef52d7fdd491d19b13d04c5d5a9546478 (diff) | |
download | nextcloud-server-aa2a3ae6c8c7d5edf99a194a430bf6cccd102e39.tar.gz nextcloud-server-aa2a3ae6c8c7d5edf99a194a430bf6cccd102e39.zip |
implement fseek for sftp read stream
Signed-off-by: Robin Appelman <robin@icewind.nl>
Diffstat (limited to 'apps/files_external')
-rw-r--r-- | apps/files_external/lib/Lib/Storage/SFTP.php | 5 | ||||
-rw-r--r-- | apps/files_external/lib/Lib/Storage/SFTPReadStream.php | 28 |
2 files changed, 30 insertions, 3 deletions
diff --git a/apps/files_external/lib/Lib/Storage/SFTP.php b/apps/files_external/lib/Lib/Storage/SFTP.php index 5dd11b2fe53..bc25477bcf6 100644 --- a/apps/files_external/lib/Lib/Storage/SFTP.php +++ b/apps/files_external/lib/Lib/Storage/SFTP.php @@ -381,11 +381,12 @@ class SFTP extends Common { switch ($mode) { case 'r': case 'rb': - if (!$this->file_exists($path)) { + $stat = $this->stat($path); + if (!$stat) { return false; } SFTPReadStream::register(); - $context = stream_context_create(['sftp' => ['session' => $connection]]); + $context = stream_context_create(['sftp' => ['session' => $connection, 'size' => $stat['size']]]); $handle = fopen('sftpread://' . trim($absPath, '/'), 'r', false, $context); return RetryWrapper::wrap($handle); case 'w': diff --git a/apps/files_external/lib/Lib/Storage/SFTPReadStream.php b/apps/files_external/lib/Lib/Storage/SFTPReadStream.php index 7a53f41aa61..aaae811c57b 100644 --- a/apps/files_external/lib/Lib/Storage/SFTPReadStream.php +++ b/apps/files_external/lib/Lib/Storage/SFTPReadStream.php @@ -50,6 +50,7 @@ class SFTPReadStream implements File { private $buffer = ''; private bool $pendingRead = false; + private int $size = 0; public static function register($protocol = 'sftpread') { if (in_array($protocol, stream_get_wrappers(), true)) { @@ -76,6 +77,9 @@ class SFTPReadStream implements File { } else { throw new \BadMethodCallException('Invalid context, session not set'); } + if (isset($context['size'])) { + $this->size = $context['size']; + } return $context; } @@ -119,7 +123,25 @@ class SFTPReadStream implements File { } public function stream_seek($offset, $whence = SEEK_SET) { - return false; + switch ($whence) { + case SEEK_SET: + $this->seekTo($offset); + break; + case SEEK_CUR: + $this->seekTo($this->readPosition + $offset); + break; + case SEEK_END: + $this->seekTo($this->size + $offset); + break; + } + return true; + } + + private function seekTo(int $offset) { + $this->internalPosition = $offset; + $this->readPosition = $offset; + $this->buffer = ''; + $this->request_chunk(256 * 1024); } public function stream_tell() { @@ -143,6 +165,10 @@ class SFTPReadStream implements File { } private function request_chunk($size) { + if ($this->pendingRead) { + $this->sftp->_get_sftp_packet(); + } + $packet = pack('Na*N3', strlen($this->handle), $this->handle, $this->internalPosition / 4294967296, $this->internalPosition, $size); $this->pendingRead = true; return $this->sftp->_send_sftp_packet(NET_SFTP_READ, $packet); |