mirror of
https://github.com/phpseclib/phpseclib.git
synced 2024-11-11 08:10:58 +00:00
SFTP: reopen channel on channel closure
This commit is contained in:
parent
bd0e217793
commit
05828a8759
@ -284,6 +284,16 @@ class SFTP extends SSH2
|
|||||||
*/
|
*/
|
||||||
private $preserveTime = false;
|
private $preserveTime = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Was the last packet due to the channels being closed or not?
|
||||||
|
*
|
||||||
|
* @see self::get()
|
||||||
|
* @see self::get_sftp_packet()
|
||||||
|
* @var bool
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
private $channel_close = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default Constructor.
|
* Default Constructor.
|
||||||
*
|
*
|
||||||
@ -442,6 +452,18 @@ class SFTP extends SSH2
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $this->init_sftp_connection();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Re)initializes the SFTP channel
|
||||||
|
*
|
||||||
|
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||||
|
* @return bool
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
private function init_sftp_connection()
|
||||||
|
{
|
||||||
$this->window_size_server_to_client[self::CHANNEL] = $this->window_size;
|
$this->window_size_server_to_client[self::CHANNEL] = $this->window_size;
|
||||||
|
|
||||||
$packet = Strings::packSSH2(
|
$packet = Strings::packSSH2(
|
||||||
@ -457,10 +479,7 @@ class SFTP extends SSH2
|
|||||||
|
|
||||||
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_OPEN;
|
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_OPEN;
|
||||||
|
|
||||||
$response = $this->get_channel_packet(self::CHANNEL, true);
|
$this->get_channel_packet(self::CHANNEL, true);
|
||||||
if ($response === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$packet = Strings::packSSH2(
|
$packet = Strings::packSSH2(
|
||||||
'CNsbs',
|
'CNsbs',
|
||||||
@ -501,10 +520,7 @@ class SFTP extends SSH2
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_DATA;
|
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_DATA;
|
||||||
|
$this->send_sftp_packet(NET_SFTP_INIT, "\0\0\0\3");
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_INIT, "\0\0\0\3")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_VERSION) {
|
if ($this->packet_type != NET_SFTP_VERSION) {
|
||||||
@ -577,7 +593,7 @@ class SFTP extends SSH2
|
|||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function disableStatCache()
|
public function disableStatCache()
|
||||||
{
|
{
|
||||||
$this->use_stat_cache = false;
|
$this->use_stat_cache = false;
|
||||||
}
|
}
|
||||||
@ -679,9 +695,7 @@ class SFTP extends SSH2
|
|||||||
|
|
||||||
if ($this->pwd === false) {
|
if ($this->pwd === false) {
|
||||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.9
|
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.9
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_REALPATH, Strings::packSSH2('s', $path))) {
|
$this->send_sftp_packet(NET_SFTP_REALPATH, Strings::packSSH2('s', $path));
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
switch ($this->packet_type) {
|
switch ($this->packet_type) {
|
||||||
@ -758,9 +772,7 @@ class SFTP extends SSH2
|
|||||||
// the file's uid / gid match the currently logged in user's uid / gid but how there's no easy
|
// the file's uid / gid match the currently logged in user's uid / gid but how there's no easy
|
||||||
// way to get those with SFTP
|
// way to get those with SFTP
|
||||||
|
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_OPENDIR, Strings::packSSH2('s', $dir))) {
|
$this->send_sftp_packet(NET_SFTP_OPENDIR, Strings::packSSH2('s', $dir));
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// see \phpseclib3\Net\SFTP::nlist() for a more thorough explanation of the following
|
// see \phpseclib3\Net\SFTP::nlist() for a more thorough explanation of the following
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
@ -899,9 +911,7 @@ class SFTP extends SSH2
|
|||||||
}
|
}
|
||||||
|
|
||||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.2
|
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.2
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_OPENDIR, Strings::packSSH2('s', $dir))) {
|
$this->send_sftp_packet(NET_SFTP_OPENDIR, Strings::packSSH2('s', $dir));
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
switch ($this->packet_type) {
|
switch ($this->packet_type) {
|
||||||
@ -927,9 +937,7 @@ class SFTP extends SSH2
|
|||||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.2
|
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.2
|
||||||
// why multiple SSH_FXP_READDIR packets would be sent when the response to a single one can span arbitrarily many
|
// why multiple SSH_FXP_READDIR packets would be sent when the response to a single one can span arbitrarily many
|
||||||
// SSH_MSG_CHANNEL_DATA messages is not known to me.
|
// SSH_MSG_CHANNEL_DATA messages is not known to me.
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_READDIR, Strings::packSSH2('s', $handle))) {
|
$this->send_sftp_packet(NET_SFTP_READDIR, Strings::packSSH2('s', $handle));
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
switch ($this->packet_type) {
|
switch ($this->packet_type) {
|
||||||
@ -1319,9 +1327,7 @@ class SFTP extends SSH2
|
|||||||
{
|
{
|
||||||
// SFTPv4+ adds an additional 32-bit integer field - flags - to the following:
|
// SFTPv4+ adds an additional 32-bit integer field - flags - to the following:
|
||||||
$packet = Strings::packSSH2('s', $filename);
|
$packet = Strings::packSSH2('s', $filename);
|
||||||
if (!$this->send_sftp_packet($type, $packet)) {
|
$this->send_sftp_packet($type, $packet);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
switch ($this->packet_type) {
|
switch ($this->packet_type) {
|
||||||
@ -1384,9 +1390,7 @@ class SFTP extends SSH2
|
|||||||
$flags = NET_SFTP_OPEN_WRITE | NET_SFTP_OPEN_CREATE | NET_SFTP_OPEN_EXCL;
|
$flags = NET_SFTP_OPEN_WRITE | NET_SFTP_OPEN_CREATE | NET_SFTP_OPEN_EXCL;
|
||||||
$attr = pack('N3', NET_SFTP_ATTR_ACCESSTIME, $time, $atime);
|
$attr = pack('N3', NET_SFTP_ATTR_ACCESSTIME, $time, $atime);
|
||||||
$packet = Strings::packSSH2('sN', $filename, $flags) . $attr;
|
$packet = Strings::packSSH2('sN', $filename, $flags) . $attr;
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_OPEN, $packet)) {
|
$this->send_sftp_packet(NET_SFTP_OPEN, $packet);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
switch ($this->packet_type) {
|
switch ($this->packet_type) {
|
||||||
@ -1475,9 +1479,7 @@ class SFTP extends SSH2
|
|||||||
// tell us if the file actually exists.
|
// tell us if the file actually exists.
|
||||||
// incidentally, SFTPv4+ adds an additional 32-bit integer field - flags - to the following:
|
// incidentally, SFTPv4+ adds an additional 32-bit integer field - flags - to the following:
|
||||||
$packet = pack('Na*', strlen($filename), $filename);
|
$packet = pack('Na*', strlen($filename), $filename);
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_STAT, $packet)) {
|
$this->send_sftp_packet(NET_SFTP_STAT, $packet);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
switch ($this->packet_type) {
|
switch ($this->packet_type) {
|
||||||
@ -1525,9 +1527,7 @@ class SFTP extends SSH2
|
|||||||
|
|
||||||
// SFTPv4+ has an additional byte field - type - that would need to be sent, as well. setting it to
|
// SFTPv4+ has an additional byte field - type - that would need to be sent, as well. setting it to
|
||||||
// SSH_FILEXFER_TYPE_UNKNOWN might work. if not, we'd have to do an SSH_FXP_STAT before doing an SSH_FXP_SETSTAT.
|
// SSH_FILEXFER_TYPE_UNKNOWN might work. if not, we'd have to do an SSH_FXP_STAT before doing an SSH_FXP_SETSTAT.
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_SETSTAT, Strings::packSSH2('s', $filename) . $attr)) {
|
$this->send_sftp_packet(NET_SFTP_SETSTAT, Strings::packSSH2('s', $filename) . $attr);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
"Because some systems must use separate system calls to set various attributes, it is possible that a failure
|
"Because some systems must use separate system calls to set various attributes, it is possible that a failure
|
||||||
@ -1592,9 +1592,7 @@ class SFTP extends SSH2
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_SETSTAT, Strings::packSSH2('s', $temp) . $attr)) {
|
$this->send_sftp_packet(NET_SFTP_SETSTAT, Strings::packSSH2('s', $temp) . $attr);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$i++;
|
$i++;
|
||||||
|
|
||||||
@ -1607,9 +1605,7 @@ class SFTP extends SSH2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_SETSTAT, Strings::packSSH2('s', $path) . $attr)) {
|
$this->send_sftp_packet(NET_SFTP_SETSTAT, Strings::packSSH2('s', $path) . $attr);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$i++;
|
$i++;
|
||||||
|
|
||||||
@ -1639,9 +1635,7 @@ class SFTP extends SSH2
|
|||||||
|
|
||||||
$link = $this->realpath($link);
|
$link = $this->realpath($link);
|
||||||
|
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_READLINK, Strings::packSSH2('s', $link))) {
|
$this->send_sftp_packet(NET_SFTP_READLINK, Strings::packSSH2('s', $link));
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
switch ($this->packet_type) {
|
switch ($this->packet_type) {
|
||||||
@ -1687,9 +1681,7 @@ class SFTP extends SSH2
|
|||||||
$link = $this->realpath($link);
|
$link = $this->realpath($link);
|
||||||
|
|
||||||
$packet = Strings::packSSH2('ss', $target, $link);
|
$packet = Strings::packSSH2('ss', $target, $link);
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_SYMLINK, $packet)) {
|
$this->send_sftp_packet(NET_SFTP_SYMLINK, $packet);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||||
@ -1751,9 +1743,7 @@ class SFTP extends SSH2
|
|||||||
private function mkdir_helper($dir, $mode)
|
private function mkdir_helper($dir, $mode)
|
||||||
{
|
{
|
||||||
// send SSH_FXP_MKDIR without any attributes (that's what the \0\0\0\0 is doing)
|
// send SSH_FXP_MKDIR without any attributes (that's what the \0\0\0\0 is doing)
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_MKDIR, Strings::packSSH2('s', $dir) . "\0\0\0\0")) {
|
$this->send_sftp_packet(NET_SFTP_MKDIR, Strings::packSSH2('s', $dir) . "\0\0\0\0");
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||||
@ -1793,9 +1783,7 @@ class SFTP extends SSH2
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_RMDIR, Strings::packSSH2('s', $dir))) {
|
$this->send_sftp_packet(NET_SFTP_RMDIR, Strings::packSSH2('s', $dir));
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||||
@ -1898,9 +1886,7 @@ class SFTP extends SSH2
|
|||||||
$this->remove_from_stat_cache($remote_file);
|
$this->remove_from_stat_cache($remote_file);
|
||||||
|
|
||||||
$packet = Strings::packSSH2('sNN', $remote_file, $flags, 0);
|
$packet = Strings::packSSH2('sNN', $remote_file, $flags, 0);
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_OPEN, $packet)) {
|
$this->send_sftp_packet(NET_SFTP_OPEN, $packet);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
switch ($this->packet_type) {
|
switch ($this->packet_type) {
|
||||||
@ -1982,11 +1968,13 @@ class SFTP extends SSH2
|
|||||||
|
|
||||||
$subtemp = $offset + $sent;
|
$subtemp = $offset + $sent;
|
||||||
$packet = pack('Na*N3a*', strlen($handle), $handle, $subtemp / 4294967296, $subtemp, strlen($temp), $temp);
|
$packet = pack('Na*N3a*', strlen($handle), $handle, $subtemp / 4294967296, $subtemp, strlen($temp), $temp);
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_WRITE, $packet, $j)) {
|
try {
|
||||||
|
$this->send_sftp_packet(NET_SFTP_WRITE, $packet, $j);
|
||||||
|
} catch (\Exception $e) {
|
||||||
if ($mode & self::SOURCE_LOCAL_FILE) {
|
if ($mode & self::SOURCE_LOCAL_FILE) {
|
||||||
fclose($fp);
|
fclose($fp);
|
||||||
}
|
}
|
||||||
return false;
|
throw $e;
|
||||||
}
|
}
|
||||||
$sent+= strlen($temp);
|
$sent+= strlen($temp);
|
||||||
if (is_callable($progressCallback)) {
|
if (is_callable($progressCallback)) {
|
||||||
@ -2066,9 +2054,7 @@ class SFTP extends SSH2
|
|||||||
*/
|
*/
|
||||||
private function close_handle($handle)
|
private function close_handle($handle)
|
||||||
{
|
{
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_CLOSE, pack('Na*', strlen($handle), $handle))) {
|
$this->send_sftp_packet(NET_SFTP_CLOSE, pack('Na*', strlen($handle), $handle));
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// "The client MUST release all resources associated with the handle regardless of the status."
|
// "The client MUST release all resources associated with the handle regardless of the status."
|
||||||
// -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.3
|
// -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.3
|
||||||
@ -2117,9 +2103,7 @@ class SFTP extends SSH2
|
|||||||
}
|
}
|
||||||
|
|
||||||
$packet = pack('Na*N2', strlen($remote_file), $remote_file, NET_SFTP_OPEN_READ, 0);
|
$packet = pack('Na*N2', strlen($remote_file), $remote_file, NET_SFTP_OPEN_READ, 0);
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_OPEN, $packet)) {
|
$this->send_sftp_packet(NET_SFTP_OPEN, $packet);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
switch ($this->packet_type) {
|
switch ($this->packet_type) {
|
||||||
@ -2163,11 +2147,13 @@ class SFTP extends SSH2
|
|||||||
$packet_size = $length > 0 ? min($this->max_sftp_packet, $length - $read) : $this->max_sftp_packet;
|
$packet_size = $length > 0 ? min($this->max_sftp_packet, $length - $read) : $this->max_sftp_packet;
|
||||||
|
|
||||||
$packet = Strings::packSSH2('sN3', $handle, $tempoffset / 4294967296, $tempoffset, $packet_size);
|
$packet = Strings::packSSH2('sN3', $handle, $tempoffset / 4294967296, $tempoffset, $packet_size);
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_READ, $packet, $i)) {
|
try {
|
||||||
|
$this->send_sftp_packet(NET_SFTP_READ, $packet, $i);
|
||||||
|
} catch (\Exception $e) {
|
||||||
if ($fclose_check) {
|
if ($fclose_check) {
|
||||||
fclose($fp);
|
fclose($fp);
|
||||||
}
|
}
|
||||||
return false;
|
throw $e;
|
||||||
}
|
}
|
||||||
$packet = null;
|
$packet = null;
|
||||||
$read+= $packet_size;
|
$read+= $packet_size;
|
||||||
@ -2216,8 +2202,12 @@ class SFTP extends SSH2
|
|||||||
if ($fclose_check) {
|
if ($fclose_check) {
|
||||||
fclose($fp);
|
fclose($fp);
|
||||||
}
|
}
|
||||||
throw new \UnexpectedValueException('Expected NET_SFTP_DATA or NET_SFTP_STATUS. '
|
if ($this->channel_close) {
|
||||||
. 'Got packet type: ' . $this->packet_type);
|
$this->init_sftp_connection();
|
||||||
|
} else {
|
||||||
|
throw new \UnexpectedValueException('Expected NET_SFTP_DATA or NET_SFTP_STATUS. '
|
||||||
|
. 'Got packet type: ' . $this->packet_type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$response = null;
|
$response = null;
|
||||||
}
|
}
|
||||||
@ -2282,9 +2272,7 @@ class SFTP extends SSH2
|
|||||||
}
|
}
|
||||||
|
|
||||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3
|
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_REMOVE, pack('Na*', strlen($path), $path))) {
|
$this->send_sftp_packet(NET_SFTP_REMOVE, pack('Na*', strlen($path), $path));
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||||
@ -2347,9 +2335,7 @@ class SFTP extends SSH2
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_REMOVE, Strings::packSSH2('s', $temp))) {
|
$this->send_sftp_packet(NET_SFTP_REMOVE, Strings::packSSH2('s', $temp));
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$this->remove_from_stat_cache($temp);
|
$this->remove_from_stat_cache($temp);
|
||||||
|
|
||||||
$i++;
|
$i++;
|
||||||
@ -2363,9 +2349,7 @@ class SFTP extends SSH2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_RMDIR, Strings::packSSH2('s', $path))) {
|
$this->send_sftp_packet(NET_SFTP_RMDIR, Strings::packSSH2('s', $path));
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$this->remove_from_stat_cache($path);
|
$this->remove_from_stat_cache($path);
|
||||||
|
|
||||||
$i++;
|
$i++;
|
||||||
@ -2461,9 +2445,7 @@ class SFTP extends SSH2
|
|||||||
public function is_readable($path)
|
public function is_readable($path)
|
||||||
{
|
{
|
||||||
$packet = Strings::packSSH2('sNN', $this->realpath($path), NET_SFTP_OPEN_READ, 0);
|
$packet = Strings::packSSH2('sNN', $this->realpath($path), NET_SFTP_OPEN_READ, 0);
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_OPEN, $packet)) {
|
$this->send_sftp_packet(NET_SFTP_OPEN, $packet);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
switch ($this->packet_type) {
|
switch ($this->packet_type) {
|
||||||
@ -2487,9 +2469,7 @@ class SFTP extends SSH2
|
|||||||
public function is_writable($path)
|
public function is_writable($path)
|
||||||
{
|
{
|
||||||
$packet = Strings::packSSH2('sNN', $this->realpath($path), NET_SFTP_OPEN_WRITE, 0);
|
$packet = Strings::packSSH2('sNN', $this->realpath($path), NET_SFTP_OPEN_WRITE, 0);
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_OPEN, $packet)) {
|
$this->send_sftp_packet(NET_SFTP_OPEN, $packet);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
switch ($this->packet_type) {
|
switch ($this->packet_type) {
|
||||||
@ -2706,9 +2686,7 @@ class SFTP extends SSH2
|
|||||||
|
|
||||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3
|
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3
|
||||||
$packet = Strings::packSSH2('ss', $oldname, $newname);
|
$packet = Strings::packSSH2('ss', $oldname, $newname);
|
||||||
if (!$this->send_sftp_packet(NET_SFTP_RENAME, $packet)) {
|
$this->send_sftp_packet(NET_SFTP_RENAME, $packet);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||||
@ -2942,6 +2920,8 @@ class SFTP extends SSH2
|
|||||||
*/
|
*/
|
||||||
private function get_sftp_packet($request_id = null)
|
private function get_sftp_packet($request_id = null)
|
||||||
{
|
{
|
||||||
|
$this->channel_close = false;
|
||||||
|
|
||||||
if (isset($request_id) && isset($this->requestBuffer[$request_id])) {
|
if (isset($request_id) && isset($this->requestBuffer[$request_id])) {
|
||||||
$this->packet_type = $this->requestBuffer[$request_id]['packet_type'];
|
$this->packet_type = $this->requestBuffer[$request_id]['packet_type'];
|
||||||
$temp = $this->requestBuffer[$request_id]['packet'];
|
$temp = $this->requestBuffer[$request_id]['packet'];
|
||||||
@ -2966,7 +2946,7 @@ class SFTP extends SSH2
|
|||||||
$this->packet_buffer.= $temp;
|
$this->packet_buffer.= $temp;
|
||||||
}
|
}
|
||||||
if (strlen($this->packet_buffer) < 4) {
|
if (strlen($this->packet_buffer) < 4) {
|
||||||
return false;
|
throw new \RuntimeException('Packet is too small');
|
||||||
}
|
}
|
||||||
extract(unpack('Nlength', Strings::shift($this->packet_buffer, 4)));
|
extract(unpack('Nlength', Strings::shift($this->packet_buffer, 4)));
|
||||||
/** @var integer $length */
|
/** @var integer $length */
|
||||||
|
@ -2657,10 +2657,7 @@ class SSH2
|
|||||||
|
|
||||||
$this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_OPEN;
|
$this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_OPEN;
|
||||||
|
|
||||||
$response = $this->get_channel_packet(self::CHANNEL_EXEC);
|
$this->get_channel_packet(self::CHANNEL_EXEC);
|
||||||
if ($response === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->request_pty === true) {
|
if ($this->request_pty === true) {
|
||||||
$terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
|
$terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
|
||||||
@ -2719,8 +2716,7 @@ class SSH2
|
|||||||
|
|
||||||
$this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_REQUEST;
|
$this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_REQUEST;
|
||||||
|
|
||||||
$response = $this->get_channel_packet(self::CHANNEL_EXEC);
|
if (!$this->get_channel_packet(self::CHANNEL_EXEC)) {
|
||||||
if ($response === false) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2783,10 +2779,7 @@ class SSH2
|
|||||||
|
|
||||||
$this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_OPEN;
|
$this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_OPEN;
|
||||||
|
|
||||||
$response = $this->get_channel_packet(self::CHANNEL_SHELL);
|
$this->get_channel_packet(self::CHANNEL_SHELL);
|
||||||
if ($response === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
|
$terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
|
||||||
$packet = Strings::packSSH2(
|
$packet = Strings::packSSH2(
|
||||||
@ -2884,8 +2877,7 @@ class SSH2
|
|||||||
|
|
||||||
$this->send_binary_packet($packet);
|
$this->send_binary_packet($packet);
|
||||||
|
|
||||||
$response = $this->get_channel_packet($request_channel);
|
if (!$this->get_channel_packet($request_channel)) {
|
||||||
if ($response === false) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2937,9 +2929,9 @@ class SSH2
|
|||||||
return Strings::shift($this->interactiveBuffer, $pos + strlen($match));
|
return Strings::shift($this->interactiveBuffer, $pos + strlen($match));
|
||||||
}
|
}
|
||||||
$response = $this->get_channel_packet($channel);
|
$response = $this->get_channel_packet($channel);
|
||||||
if (is_bool($response)) {
|
if ($response === true) {
|
||||||
$this->in_request_pty_exec = false;
|
$this->in_request_pty_exec = false;
|
||||||
return $response ? Strings::shift($this->interactiveBuffer, strlen($this->interactiveBuffer)) : false;
|
return Strings::shift($this->interactiveBuffer, strlen($this->interactiveBuffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->interactiveBuffer.= $response;
|
$this->interactiveBuffer.= $response;
|
||||||
@ -2999,10 +2991,7 @@ class SSH2
|
|||||||
|
|
||||||
$this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_OPEN;
|
$this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_OPEN;
|
||||||
|
|
||||||
$response = $this->get_channel_packet(self::CHANNEL_SUBSYSTEM);
|
$this->get_channel_packet(self::CHANNEL_SUBSYSTEM);
|
||||||
if ($response === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$packet = Strings::packSSH2(
|
$packet = Strings::packSSH2(
|
||||||
'CNsCs',
|
'CNsCs',
|
||||||
@ -3016,8 +3005,7 @@ class SSH2
|
|||||||
|
|
||||||
$this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_REQUEST;
|
$this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_REQUEST;
|
||||||
|
|
||||||
$response = $this->get_channel_packet(self::CHANNEL_SUBSYSTEM);
|
if (!$this->get_channel_packet(self::CHANNEL_SUBSYSTEM)) {
|
||||||
if ($response === false) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3335,7 +3323,8 @@ class SSH2
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (strlen($raw) < 5) {
|
if (strlen($raw) < 5) {
|
||||||
return false;
|
$this->bitmap = 0;
|
||||||
|
throw new \RuntimeException('Plaintext is too short');
|
||||||
}
|
}
|
||||||
extract(unpack('Npacket_length/Cpadding_length', Strings::shift($raw, 5)));
|
extract(unpack('Npacket_length/Cpadding_length', Strings::shift($raw, 5)));
|
||||||
/**
|
/**
|
||||||
@ -3686,7 +3675,16 @@ class SSH2
|
|||||||
/**
|
/**
|
||||||
* Gets channel data
|
* Gets channel data
|
||||||
*
|
*
|
||||||
* Returns the data as a string if it's available and false if not.
|
* Returns the data as a string. bool(true) is returned if:
|
||||||
|
*
|
||||||
|
* - the server closes the channel
|
||||||
|
* - if the connection times out
|
||||||
|
* - if the channel status is CHANNEL_OPEN and the response was CHANNEL_OPEN_CONFIRMATION
|
||||||
|
* - if the channel status is CHANNEL_REQUEST and the response was CHANNEL_SUCCESS
|
||||||
|
*
|
||||||
|
* bool(false) is returned if:
|
||||||
|
*
|
||||||
|
* - if the channel status is CHANNEL_REQUEST and the response was CHANNEL_FAILURE
|
||||||
*
|
*
|
||||||
* @param int $client_channel
|
* @param int $client_channel
|
||||||
* @param bool $skip_extended
|
* @param bool $skip_extended
|
||||||
|
Loading…
Reference in New Issue
Block a user