|
|
|
|
@ -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); |
|
|
|
|
|