mirror of
https://github.com/danog/phpseclib.git
synced 2025-01-22 04:51:19 +01:00
SFTP: use Strings::packSSH2() / Strings::unpackSSH2()
This commit is contained in:
parent
0001b81950
commit
cee3f3cd4a
@ -166,6 +166,9 @@ abstract class Strings
|
||||
$result.= $element ? "\1" : "\0";
|
||||
break;
|
||||
case 'N':
|
||||
if (is_float($element)) {
|
||||
$element = (int) $element;
|
||||
}
|
||||
if (!is_int($element)) {
|
||||
throw new \InvalidArgumentException('An integer was expected.');
|
||||
}
|
||||
|
@ -420,10 +420,9 @@ class SFTP extends SSH2
|
||||
|
||||
$this->window_size_server_to_client[self::CHANNEL] = $this->window_size;
|
||||
|
||||
$packet = pack(
|
||||
'CNa*N3',
|
||||
$packet = Strings::packSSH2(
|
||||
'CsN3',
|
||||
NET_SSH2_MSG_CHANNEL_OPEN,
|
||||
strlen('session'),
|
||||
'session',
|
||||
self::CHANNEL,
|
||||
$this->window_size,
|
||||
@ -439,14 +438,12 @@ class SFTP extends SSH2
|
||||
return false;
|
||||
}
|
||||
|
||||
$packet = pack(
|
||||
'CNNa*CNa*',
|
||||
$packet = Strings::packSSH2(
|
||||
'CNsbs',
|
||||
NET_SSH2_MSG_CHANNEL_REQUEST,
|
||||
$this->server_channels[self::CHANNEL],
|
||||
strlen('subsystem'),
|
||||
'subsystem',
|
||||
1,
|
||||
strlen('sftp'),
|
||||
true,
|
||||
'sftp'
|
||||
);
|
||||
$this->send_binary_packet($packet);
|
||||
@ -461,14 +458,12 @@ class SFTP extends SSH2
|
||||
"exec sftp-server";
|
||||
// we don't do $this->exec($command, false) because exec() operates on a different channel and plus the SSH_MSG_CHANNEL_OPEN that exec() does
|
||||
// is redundant
|
||||
$packet = pack(
|
||||
'CNNa*CNa*',
|
||||
$packet = Strings::packSSH2(
|
||||
'CNsCs',
|
||||
NET_SSH2_MSG_CHANNEL_REQUEST,
|
||||
$this->server_channels[self::CHANNEL],
|
||||
strlen('exec'),
|
||||
'exec',
|
||||
1,
|
||||
strlen($command),
|
||||
$command
|
||||
);
|
||||
$this->send_binary_packet($packet);
|
||||
@ -493,28 +488,9 @@ class SFTP extends SSH2
|
||||
. 'Got packet type: ' . $this->packet_type);
|
||||
}
|
||||
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nversion', Strings::shift($response, 4)));
|
||||
/** @var integer $version */
|
||||
|
||||
$this->version = $version;
|
||||
list($this->version) = Strings::unpackSSH2('N', $response);
|
||||
while (!empty($response)) {
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nlength', Strings::shift($response, 4)));
|
||||
/** @var integer $length */
|
||||
|
||||
$key = Strings::shift($response, $length);
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nlength', Strings::shift($response, 4)));
|
||||
/** @var integer $length */
|
||||
|
||||
$value = Strings::shift($response, $length);
|
||||
list($key, $value) = Strings::unpackSSH2('ss', $response);
|
||||
$this->extensions[$key] = $value;
|
||||
}
|
||||
|
||||
@ -643,20 +619,14 @@ class SFTP extends SSH2
|
||||
private function logError($response, $status = -1)
|
||||
{
|
||||
if ($status == -1) {
|
||||
if (strlen($response) < 4) {
|
||||
return;
|
||||
}
|
||||
extract(unpack('Nstatus', Strings::shift($response, 4)));
|
||||
/** @var integer $status */
|
||||
list($status) = Strings::unpackSSH2('N', $response);
|
||||
}
|
||||
|
||||
$error = $this->status_codes[$status];
|
||||
list($error) = $this->status_codes[$status];
|
||||
|
||||
if ($this->version > 2 || strlen($response) < 4) {
|
||||
extract(unpack('Nlength', Strings::shift($response, 4)));
|
||||
/** @var integer $length */
|
||||
|
||||
$this->sftp_errors[] = $error . ': ' . Strings::shift($response, $length);
|
||||
if ($this->version > 2) {
|
||||
list($message) = Strings::unpackSSH2('s', $response);
|
||||
$this->sftp_errors[] = "$error: $message";
|
||||
} else {
|
||||
$this->sftp_errors[] = $error;
|
||||
}
|
||||
@ -685,7 +655,7 @@ class SFTP extends SSH2
|
||||
|
||||
if ($this->pwd === false) {
|
||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.9
|
||||
if (!$this->send_sftp_packet(NET_SFTP_REALPATH, pack('Na*', strlen($path), $path))) {
|
||||
if (!$this->send_sftp_packet(NET_SFTP_REALPATH, Strings::packSSH2('s', $path))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -695,14 +665,8 @@ class SFTP extends SSH2
|
||||
// although SSH_FXP_NAME is implemented differently in SFTPv3 than it is in SFTPv4+, the following
|
||||
// should work on all SFTP versions since the only part of the SSH_FXP_NAME packet the following looks
|
||||
// at is the first part and that part is defined the same in SFTP versions 3 through 6.
|
||||
Strings::shift($response, 4); // skip over the count - it should be 1, anyway
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nlength', Strings::shift($response, 4)));
|
||||
/** @var integer $length */
|
||||
|
||||
return Strings::shift($response, $length);
|
||||
list(, $filename) = Strings::unpackSSH2('Ns', $response);
|
||||
return $filename;
|
||||
case NET_SFTP_STATUS:
|
||||
$this->logError($response);
|
||||
return false;
|
||||
@ -770,7 +734,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
|
||||
// way to get those with SFTP
|
||||
|
||||
if (!$this->send_sftp_packet(NET_SFTP_OPENDIR, pack('Na*', strlen($dir), $dir))) {
|
||||
if (!$this->send_sftp_packet(NET_SFTP_OPENDIR, Strings::packSSH2('s', $dir))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -910,7 +874,7 @@ class SFTP extends SSH2
|
||||
}
|
||||
|
||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.2
|
||||
if (!$this->send_sftp_packet(NET_SFTP_OPENDIR, pack('Na*', strlen($dir), $dir))) {
|
||||
if (!$this->send_sftp_packet(NET_SFTP_OPENDIR, Strings::packSSH2('s', $dir))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -938,34 +902,16 @@ class SFTP extends SSH2
|
||||
// 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
|
||||
// SSH_MSG_CHANNEL_DATA messages is not known to me.
|
||||
if (!$this->send_sftp_packet(NET_SFTP_READDIR, pack('Na*', strlen($handle), $handle))) {
|
||||
if (!$this->send_sftp_packet(NET_SFTP_READDIR, Strings::packSSH2('s', $handle))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$response = $this->get_sftp_packet();
|
||||
switch ($this->packet_type) {
|
||||
case NET_SFTP_NAME:
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Ncount', Strings::shift($response, 4)));
|
||||
/** @var integer $count */
|
||||
|
||||
list($count) = Strings::unpackSSH2('N', $response);
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nlength', Strings::shift($response, 4)));
|
||||
/** @var integer $length */
|
||||
|
||||
$shortname = Strings::shift($response, $length);
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nlength', Strings::shift($response, 4)));
|
||||
/** @var integer $length */
|
||||
|
||||
$longname = Strings::shift($response, $length);
|
||||
list($shortname, $longname) = Strings::unpackSSH2('ss', $response);
|
||||
$attributes = $this->parseAttributes($response);
|
||||
if (!isset($attributes['type'])) {
|
||||
$fileType = $this->parseLongname($longname);
|
||||
@ -990,12 +936,7 @@ class SFTP extends SSH2
|
||||
}
|
||||
break;
|
||||
case NET_SFTP_STATUS:
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nstatus', Strings::shift($response, 4)));
|
||||
/** @var integer $status */
|
||||
|
||||
list($status) = Strings::unpackSSH2('N', $response);
|
||||
if ($status != NET_SFTP_STATUS_EOF) {
|
||||
$this->logError($response, $status);
|
||||
return false;
|
||||
@ -1369,7 +1310,7 @@ class SFTP extends SSH2
|
||||
private function stat_helper($filename, $type)
|
||||
{
|
||||
// SFTPv4+ adds an additional 32-bit integer field - flags - to the following:
|
||||
$packet = pack('Na*', strlen($filename), $filename);
|
||||
$packet = Strings::packSSH2('s', $filename);
|
||||
if (!$this->send_sftp_packet($type, $packet)) {
|
||||
return false;
|
||||
}
|
||||
@ -1434,7 +1375,7 @@ class SFTP extends SSH2
|
||||
|
||||
$flags = NET_SFTP_OPEN_WRITE | NET_SFTP_OPEN_CREATE | NET_SFTP_OPEN_EXCL;
|
||||
$attr = pack('N3', NET_SFTP_ATTR_ACCESSTIME, $time, $atime);
|
||||
$packet = pack('Na*Na*', strlen($filename), $filename, $flags, $attr);
|
||||
$packet = Strings::packSSH2('sN', $filename, $flags) . $attr;
|
||||
if (!$this->send_sftp_packet(NET_SFTP_OPEN, $packet)) {
|
||||
return false;
|
||||
}
|
||||
@ -1576,7 +1517,7 @@ class SFTP extends SSH2
|
||||
|
||||
// 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.
|
||||
if (!$this->send_sftp_packet(NET_SFTP_SETSTAT, pack('Na*a*', strlen($filename), $filename, $attr))) {
|
||||
if (!$this->send_sftp_packet(NET_SFTP_SETSTAT, Strings::packSSH2('s', $filename) . $attr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1593,12 +1534,7 @@ class SFTP extends SSH2
|
||||
. 'Got packet type: ' . $this->packet_type);
|
||||
}
|
||||
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nstatus', Strings::shift($response, 4)));
|
||||
/** @var integer $status */
|
||||
|
||||
list($status) = Strings::unpackSSH2('N', $response);
|
||||
if ($status != NET_SFTP_STATUS_OK) {
|
||||
$this->logError($response, $status);
|
||||
return false;
|
||||
@ -1648,7 +1584,7 @@ class SFTP extends SSH2
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!$this->send_sftp_packet(NET_SFTP_SETSTAT, pack('Na*a*', strlen($temp), $temp, $attr))) {
|
||||
if (!$this->send_sftp_packet(NET_SFTP_SETSTAT, Strings::packSSH2('s', $temp) . $attr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1663,7 +1599,7 @@ class SFTP extends SSH2
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->send_sftp_packet(NET_SFTP_SETSTAT, pack('Na*a*', strlen($path), $path, $attr))) {
|
||||
if (!$this->send_sftp_packet(NET_SFTP_SETSTAT, Strings::packSSH2('s', $path) . $attr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1695,7 +1631,7 @@ class SFTP extends SSH2
|
||||
|
||||
$link = $this->realpath($link);
|
||||
|
||||
if (!$this->send_sftp_packet(NET_SFTP_READLINK, pack('Na*', strlen($link), $link))) {
|
||||
if (!$this->send_sftp_packet(NET_SFTP_READLINK, Strings::packSSH2('s', $link))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1711,23 +1647,15 @@ class SFTP extends SSH2
|
||||
. 'Got packet type: ' . $this->packet_type);
|
||||
}
|
||||
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Ncount', Strings::shift($response, 4)));
|
||||
/** @var integer $count */
|
||||
list($count) = Strings::unpackSSH2('N', $response);
|
||||
// the file isn't a symlink
|
||||
if (!$count) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nlength', Strings::shift($response, 4)));
|
||||
/** @var integer $length */
|
||||
list($filename) = Strings::unpackSSH2('s', $response);
|
||||
|
||||
return Strings::shift($response, $length);
|
||||
return $filename;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1750,7 +1678,7 @@ class SFTP extends SSH2
|
||||
//$target = $this->realpath($target);
|
||||
$link = $this->realpath($link);
|
||||
|
||||
$packet = pack('Na*Na*', strlen($target), $target, strlen($link), $link);
|
||||
$packet = Strings::packSSH2('ss', $target, $link);
|
||||
if (!$this->send_sftp_packet(NET_SFTP_SYMLINK, $packet)) {
|
||||
return false;
|
||||
}
|
||||
@ -1761,12 +1689,7 @@ class SFTP extends SSH2
|
||||
. 'Got packet type: ' . $this->packet_type);
|
||||
}
|
||||
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nstatus', Strings::shift($response, 4)));
|
||||
/** @var integer $status */
|
||||
|
||||
list($status) = Strings::unpackSSH2('N', $response);
|
||||
if ($status != NET_SFTP_STATUS_OK) {
|
||||
$this->logError($response, $status);
|
||||
return false;
|
||||
@ -1822,7 +1745,7 @@ class SFTP extends SSH2
|
||||
*/
|
||||
private function mkdir_helper($dir, $attr)
|
||||
{
|
||||
if (!$this->send_sftp_packet(NET_SFTP_MKDIR, pack('Na*a*', strlen($dir), $dir, $attr))) {
|
||||
if (!$this->send_sftp_packet(NET_SFTP_MKDIR, Strings::packSSH2('s', $dir) . $attr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1832,12 +1755,7 @@ class SFTP extends SSH2
|
||||
. 'Got packet type: ' . $this->packet_type);
|
||||
}
|
||||
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nstatus', Strings::shift($response, 4)));
|
||||
/** @var integer $status */
|
||||
|
||||
list($status) = Strings::unpackSSH2('N', $response);
|
||||
if ($status != NET_SFTP_STATUS_OK) {
|
||||
$this->logError($response, $status);
|
||||
return false;
|
||||
@ -1865,7 +1783,7 @@ class SFTP extends SSH2
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->send_sftp_packet(NET_SFTP_RMDIR, pack('Na*', strlen($dir), $dir))) {
|
||||
if (!$this->send_sftp_packet(NET_SFTP_RMDIR, Strings::packSSH2('s', $dir))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1875,12 +1793,7 @@ class SFTP extends SSH2
|
||||
. 'Got packet type: ' . $this->packet_type);
|
||||
}
|
||||
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nstatus', Strings::shift($response, 4)));
|
||||
/** @var integer $status */
|
||||
|
||||
list($status) = Strings::unpackSSH2('N', $response);
|
||||
if ($status != NET_SFTP_STATUS_OK) {
|
||||
// presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED?
|
||||
$this->logError($response, $status);
|
||||
@ -1973,7 +1886,7 @@ class SFTP extends SSH2
|
||||
$flags|= NET_SFTP_OPEN_TRUNCATE;
|
||||
}
|
||||
|
||||
$packet = pack('Na*N2', strlen($remote_file), $remote_file, $flags, 0);
|
||||
$packet = Strings::packSSH2('sNN', $remote_file, $flags, 0);
|
||||
if (!$this->send_sftp_packet(NET_SFTP_OPEN, $packet)) {
|
||||
return false;
|
||||
}
|
||||
@ -2115,12 +2028,7 @@ class SFTP extends SSH2
|
||||
. 'Got packet type: ' . $this->packet_type);
|
||||
}
|
||||
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nstatus', Strings::shift($response, 4)));
|
||||
/** @var integer $status */
|
||||
|
||||
list($status) = Strings::unpackSSH2('N', $response);
|
||||
if ($status != NET_SFTP_STATUS_OK) {
|
||||
$this->logError($response, $status);
|
||||
break;
|
||||
@ -2152,12 +2060,7 @@ class SFTP extends SSH2
|
||||
. 'Got packet type: ' . $this->packet_type);
|
||||
}
|
||||
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nstatus', Strings::shift($response, 4)));
|
||||
/** @var integer $status */
|
||||
|
||||
list($status) = Strings::unpackSSH2('N', $response);
|
||||
if ($status != NET_SFTP_STATUS_OK) {
|
||||
$this->logError($response, $status);
|
||||
return false;
|
||||
@ -2240,7 +2143,7 @@ class SFTP extends SSH2
|
||||
|
||||
$packet_size = $length > 0 ? min($this->max_sftp_packet, $length - $read) : $this->max_sftp_packet;
|
||||
|
||||
$packet = pack('Na*N3', strlen($handle), $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)) {
|
||||
if ($fclose_check) {
|
||||
fclose($fp);
|
||||
@ -2361,12 +2264,7 @@ class SFTP extends SSH2
|
||||
}
|
||||
|
||||
// if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nstatus', Strings::shift($response, 4)));
|
||||
/** @var integer $status */
|
||||
|
||||
list($status) = Strings::unpackSSH2('N', $response);
|
||||
if ($status != NET_SFTP_STATUS_OK) {
|
||||
$this->logError($response, $status);
|
||||
if (!$recursive) {
|
||||
@ -2419,7 +2317,7 @@ class SFTP extends SSH2
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!$this->send_sftp_packet(NET_SFTP_REMOVE, pack('Na*', strlen($temp), $temp))) {
|
||||
if (!$this->send_sftp_packet(NET_SFTP_REMOVE, Strings::packSSH2('s', $temp))) {
|
||||
return false;
|
||||
}
|
||||
$this->remove_from_stat_cache($temp);
|
||||
@ -2435,7 +2333,7 @@ class SFTP extends SSH2
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->send_sftp_packet(NET_SFTP_RMDIR, pack('Na*', strlen($path), $path))) {
|
||||
if (!$this->send_sftp_packet(NET_SFTP_RMDIR, Strings::packSSH2('s', $path))) {
|
||||
return false;
|
||||
}
|
||||
$this->remove_from_stat_cache($path);
|
||||
@ -2532,9 +2430,7 @@ class SFTP extends SSH2
|
||||
*/
|
||||
public function is_readable($path)
|
||||
{
|
||||
$path = $this->realpath($path);
|
||||
|
||||
$packet = pack('Na*N2', strlen($path), $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)) {
|
||||
return false;
|
||||
}
|
||||
@ -2560,9 +2456,7 @@ class SFTP extends SSH2
|
||||
*/
|
||||
public function is_writable($path)
|
||||
{
|
||||
$path = $this->realpath($path);
|
||||
|
||||
$packet = pack('Na*N2', strlen($path), $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)) {
|
||||
return false;
|
||||
}
|
||||
@ -2781,7 +2675,7 @@ class SFTP extends SSH2
|
||||
}
|
||||
|
||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3
|
||||
$packet = pack('Na*Na*', strlen($oldname), $oldname, strlen($newname), $newname);
|
||||
$packet = Strings::packSSH2('ss', $oldname, $newname);
|
||||
if (!$this->send_sftp_packet(NET_SFTP_RENAME, $packet)) {
|
||||
return false;
|
||||
}
|
||||
@ -2793,12 +2687,7 @@ class SFTP extends SSH2
|
||||
}
|
||||
|
||||
// if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
|
||||
if (strlen($response) < 4) {
|
||||
return false;
|
||||
}
|
||||
extract(unpack('Nstatus', Strings::shift($response, 4)));
|
||||
/** @var integer $status */
|
||||
|
||||
list($status) = Strings::unpackSSH2('N', $response);
|
||||
if ($status != NET_SFTP_STATUS_OK) {
|
||||
$this->logError($response, $status);
|
||||
return false;
|
||||
@ -2825,12 +2714,7 @@ class SFTP extends SSH2
|
||||
private function parseAttributes(&$response)
|
||||
{
|
||||
$attr = [];
|
||||
if (strlen($response) < 4) {
|
||||
//user_error('Malformed file attributes');
|
||||
return [];
|
||||
}
|
||||
extract(unpack('Nflags', Strings::shift($response, 4)));
|
||||
/** @var integer $flags */
|
||||
list($flags) = Strings::unpackSSH2('N', $response);
|
||||
|
||||
// SFTPv4+ have a type field (a byte) that follows the above flag field
|
||||
foreach ($this->attributes as $key => $value) {
|
||||
@ -2842,21 +2726,15 @@ class SFTP extends SSH2
|
||||
// IEEE 754 binary64 "double precision" on such platforms and
|
||||
// as such can represent integers of at least 2^50 without loss
|
||||
// of precision. Interpreted in filesize, 2^50 bytes = 1024 TiB.
|
||||
$attr['size'] = hexdec(Hex::encode(Strings::shift($response, 8)));
|
||||
list($upper, $size) = Strings::unpackSSH2('NN', $response);
|
||||
$attr['size'] = $upper ? 4294967296 * $upper : 0;
|
||||
$attr['size']+= $size < 0 ? ($size & 0x7FFFFFFF) + 0x80000000 : $size;
|
||||
break;
|
||||
case NET_SFTP_ATTR_UIDGID: // 0x00000002 (SFTPv3 only)
|
||||
if (strlen($response) < 8) {
|
||||
//user_error('Malformed file attributes');
|
||||
return $attr;
|
||||
}
|
||||
$attr+= unpack('Nuid/Ngid', Strings::shift($response, 8));
|
||||
list($attr['uid'], $attr['gid']) = Strings::unpackSSH2('NN', $response);
|
||||
break;
|
||||
case NET_SFTP_ATTR_PERMISSIONS: // 0x00000004
|
||||
if (strlen($response) < 4) {
|
||||
//user_error('Malformed file attributes');
|
||||
return $attr;
|
||||
}
|
||||
$attr+= unpack('Npermissions', Strings::shift($response, 4));
|
||||
list($attr['permissions']) = Strings::unpackSSH2('N', $response);
|
||||
// mode == permissions; permissions was the original array key and is retained for bc purposes.
|
||||
// mode was added because that's the more industry standard terminology
|
||||
$attr+= ['mode' => $attr['permissions']];
|
||||
@ -2866,38 +2744,13 @@ class SFTP extends SSH2
|
||||
}
|
||||
break;
|
||||
case NET_SFTP_ATTR_ACCESSTIME: // 0x00000008
|
||||
if (strlen($response) < 8) {
|
||||
//user_error('Malformed file attributes');
|
||||
return $attr;
|
||||
}
|
||||
$attr+= unpack('Natime/Nmtime', Strings::shift($response, 8));
|
||||
list($attr['atime'], $attr['mtime']) = Strings::unpackSSH2('NN', $response);
|
||||
break;
|
||||
case NET_SFTP_ATTR_EXTENDED: // 0x80000000
|
||||
if (strlen($response) < 4) {
|
||||
//user_error('Malformed file attributes');
|
||||
return $attr;
|
||||
}
|
||||
extract(unpack('Ncount', Strings::shift($response, 4)));
|
||||
/** @var integer $count */
|
||||
|
||||
list($count) = Strings::unpack('N', $response);
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
if (strlen($response) < 4) {
|
||||
//user_error('Malformed file attributes');
|
||||
return $attr;
|
||||
}
|
||||
extract(unpack('Nlength', Strings::shift($response, 4)));
|
||||
/** @var integer $length */
|
||||
|
||||
$key = Strings::shift($response, $length);
|
||||
|
||||
if (strlen($response) < 4) {
|
||||
//user_error('Malformed file attributes');
|
||||
return $attr;
|
||||
}
|
||||
extract(unpack('Nlength', Strings::shift($response, 4)));
|
||||
/** @var integer $length */
|
||||
|
||||
$attr[$key] = Strings::shift($response, $length);
|
||||
list($key, $value) = Strings::unpackSSH2('ss', $response);
|
||||
$attr[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user