function login($username)
{
$args = func_get_args();
if (!call_user_func_array(array(&$this, '_login'), $args)) {
return false;
}
$this->window_size_server_to_client[self::CHANNEL] = $this->window_size;
$packet = pack('CNa*N3', NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', self::CHANNEL, $this->window_size, 0x4000);
if (!$this->_send_binary_packet($packet)) {
return false;
}
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_OPEN;
$response = $this->_get_channel_packet(self::CHANNEL);
if ($response === false) {
return false;
}
$packet = pack('CNNa*CNa*', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL], strlen('subsystem'), 'subsystem', 1, strlen('sftp'), 'sftp');
if (!$this->_send_binary_packet($packet)) {
return false;
}
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST;
$response = $this->_get_channel_packet(self::CHANNEL);
if ($response === false) {
// from PuTTY's psftp.exe
$command = "test -x /usr/lib/sftp-server && exec /usr/lib/sftp-server\n" . "test -x /usr/local/lib/sftp-server && exec /usr/local/lib/sftp-server\n" . "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*', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL], strlen('exec'), 'exec', 1, strlen($command), $command);
if (!$this->_send_binary_packet($packet)) {
return false;
}
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST;
$response = $this->_get_channel_packet(self::CHANNEL);
if ($response === false) {
return false;
}
}
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_DATA;
if (!$this->_send_sftp_packet(NET_SFTP_INIT, "")) {
return false;
}
$response = $this->_get_sftp_packet();
if ($this->packet_type != NET_SFTP_VERSION) {
throw new \UnexpectedValueException('Expected SSH_FXP_VERSION');
}
if (strlen($response) < 4) {
return false;
}
extract(unpack('Nversion', Strings::shift($response, 4)));
$this->version = $version;
while (!empty($response)) {
if (strlen($response) < 4) {
return false;
}
extract(unpack('Nlength', Strings::shift($response, 4)));
$key = Strings::shift($response, $length);
if (strlen($response) < 4) {
return false;
}
extract(unpack('Nlength', Strings::shift($response, 4)));
$value = Strings::shift($response, $length);
$this->extensions[$key] = $value;
}
/*
SFTPv4+ defines a 'newline' extension. SFTPv3 seems to have unofficial support for it via '[email protected]',
however, I'm not sure what '[email protected]' is supposed to do (the fact that it's unofficial means that it's
not in the official SFTPv3 specs) and '[email protected]' / 'newline' are likely not drop-in substitutes for
one another due to the fact that 'newline' comes with a SSH_FXF_TEXT bitmask whereas it seems unlikely that
'[email protected]' would.
*/
/*
if (isset($this->extensions['[email protected]'])) {
$this->extensions['newline'] = $this->extensions['[email protected]'];
unset($this->extensions['[email protected]']);
}
*/
$this->request_id = 1;
/*
A Note on SFTPv4/5/6 support:
<http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-5.1> states the following:
"If the client wishes to interoperate with servers that support noncontiguous version
numbers it SHOULD send '3'"
Given that the server only sends its version number after the client has already done so, the above
seems to be suggesting that v3 should be the default version. This makes sense given that v3 is the
most popular.
<http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-5.5> states the following;
"If the server did not send the "versions" extension, or the version-from-list was not included, the
server MAY send a status response describing the failure, but MUST then close the channel without
processing any further requests."
So what do you do if you have a client whose initial SSH_FXP_INIT packet says it implements v3 and
a server whose initial SSH_FXP_VERSION reply says it implements v4 and only v4? If it only implements
v4, the "versions" extension is likely not going to have been sent so version re-negotiation as discussed
in draft-ietf-secsh-filexfer-13 would be quite impossible. As such, what \phpseclib\Net\SFTP would do is close the
channel and reopen it with a new and updated SSH_FXP_INIT packet.
*/
switch ($this->version) {
case 2:
case 3:
break;
default:
return false;
}
$this->pwd = $this->_realpath('.');
$this->_update_stat_cache($this->pwd, array());
return true;
}