diff options
author | Robin Appelman <robin@icewind.nl> | 2023-08-31 15:39:56 +0200 |
---|---|---|
committer | backportbot-nextcloud[bot] <backportbot-nextcloud[bot]@users.noreply.github.com> | 2023-09-18 17:33:43 +0000 |
commit | 373bd09fbfcd6875b0fe4e3d2d756e9aaab9ad42 (patch) | |
tree | 9d09408efc484113e6374c1f24aa4382f03cc473 /apps/files_external/lib/Lib/Storage | |
parent | 02a50bd99c725b70a29c98a66037fc7534b67ea0 (diff) | |
download | nextcloud-server-373bd09fbfcd6875b0fe4e3d2d756e9aaab9ad42.tar.gz nextcloud-server-373bd09fbfcd6875b0fe4e3d2d756e9aaab9ad42.zip |
implement fseek for sftp read stream
Signed-off-by: Robin Appelman <robin@icewind.nl>
Diffstat (limited to 'apps/files_external/lib/Lib/Storage')
-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 d41963de82c..83d29edb3f6 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); |