mirror of
https://github.com/phpseclib/phpseclib.git
synced 2024-12-28 12:10:59 +00:00
Net_SFTP_Stream: Add limited support for notifications and...
...add NET_SFTP_STREAM_LOGGING
This commit is contained in:
parent
1c7fb5bd67
commit
a47c1c3980
@ -126,11 +126,22 @@ class Net_SFTP_Stream {
|
||||
*/
|
||||
var $context;
|
||||
|
||||
/**
|
||||
* Notification callback function
|
||||
*
|
||||
* @var Callable
|
||||
* @access public
|
||||
*/
|
||||
var $notification;
|
||||
|
||||
/**
|
||||
* Path Parser
|
||||
*
|
||||
* Extract a path from a URI and actually connect to an SSH server if appropriate
|
||||
*
|
||||
* If "notification" is set as a context parameter the message code for successful login is
|
||||
* NET_SSH2_MSG_USERAUTH_SUCCESS. For a failed login it's NET_SSH2_MSG_USERAUTH_FAILURE.
|
||||
*
|
||||
* @param String $path
|
||||
* @return String
|
||||
* @access private
|
||||
@ -143,6 +154,11 @@ class Net_SFTP_Stream {
|
||||
return false;
|
||||
}
|
||||
|
||||
$context = stream_context_get_params($this->context);
|
||||
if (isset($context['notification'])) {
|
||||
$this->notification = $context['notification'];
|
||||
}
|
||||
|
||||
if ($host[0] == '$') {
|
||||
$host = substr($host, 1);
|
||||
global $$host;
|
||||
@ -181,8 +197,27 @@ class Net_SFTP_Stream {
|
||||
$this->sftp = self::$instances[$host][$port][$user][(string) $pass];
|
||||
} else {
|
||||
$this->sftp = new Net_SFTP($host, isset($port) ? $port : 22);
|
||||
if (!$this->sftp->login($user, $pass)) {
|
||||
return false;
|
||||
if (isset($this->notification) && is_callable($this->notification)) {
|
||||
/* if !is_callable($this->notification) we could do this:
|
||||
|
||||
user_error('fopen(): failed to call user notifier', E_USER_WARNING);
|
||||
|
||||
the ftp wrapper gives errors like that when the notifier isn't callable.
|
||||
i've opted not to do that, however, since the ftp wrapper gives the line
|
||||
on which the fopen occurred as the line number - not the line that the
|
||||
user_error is on.
|
||||
*/
|
||||
call_user_func($this->notification, STREAM_NOTIFY_CONNECT, STREAM_NOTIFY_SEVERITY_INFO, '', 0, 0, 0);
|
||||
call_user_func($this->notification, STREAM_NOTIFY_AUTH_REQUIRED, STREAM_NOTIFY_SEVERITY_INFO, '', 0, 0, 0);
|
||||
if (!$this->sftp->login($user, $pass)) {
|
||||
call_user_func($this->notification, STREAM_NOTIFY_AUTH_RESULT, STREAM_NOTIFY_SEVERITY_ERR, 'Login Failure', NET_SSH2_MSG_USERAUTH_FAILURE, 0, 0);
|
||||
return false;
|
||||
}
|
||||
call_user_func($this->notification, STREAM_NOTIFY_AUTH_RESULT, STREAM_NOTIFY_SEVERITY_INFO, 'Login Success', NET_SSH2_MSG_USERAUTH_SUCCESS, 0, 0);
|
||||
} else {
|
||||
if (!$this->sftp->login($user, $pass)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
self::$instances[$host][$port][$user][(string) $pass] = $this->sftp;
|
||||
}
|
||||
@ -201,7 +236,7 @@ class Net_SFTP_Stream {
|
||||
* @return Boolean
|
||||
* @access public
|
||||
*/
|
||||
function stream_open($path, $mode, $options, &$opened_path)
|
||||
function _stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
$path = $this->_parse_path($path);
|
||||
|
||||
@ -239,7 +274,7 @@ class Net_SFTP_Stream {
|
||||
* @return Mixed
|
||||
* @access public
|
||||
*/
|
||||
function stream_read($count)
|
||||
function _stream_read($count)
|
||||
{
|
||||
switch ($this->mode) {
|
||||
case 'w':
|
||||
@ -256,7 +291,16 @@ class Net_SFTP_Stream {
|
||||
//}
|
||||
|
||||
$result = $this->sftp->get($this->path, false, $this->pos, $count);
|
||||
if (empty($result)) {
|
||||
if (isset($this->notification) && is_callable($this->notification)) {
|
||||
if ($result === false) {
|
||||
call_user_func($this->notification, STREAM_NOTIFY_FAILURE, STREAM_NOTIFY_SEVERITY_ERR, $this->sftp->getLastSFTPError(), NET_SFTP_OPEN, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
// seems that PHP calls stream_read in 8k chunks
|
||||
call_user_func($this->notification, STREAM_NOTIFY_PROGRESS, STREAM_NOTIFY_SEVERITY_INFO, '', 0, strlen($result), $size);
|
||||
}
|
||||
|
||||
if (empty($result)) { // ie. false or empty string
|
||||
$this->eof = true;
|
||||
return false;
|
||||
}
|
||||
@ -272,7 +316,7 @@ class Net_SFTP_Stream {
|
||||
* @return Mixed
|
||||
* @access public
|
||||
*/
|
||||
function stream_write($data)
|
||||
function _stream_write($data)
|
||||
{
|
||||
switch ($this->mode) {
|
||||
case 'r':
|
||||
@ -280,6 +324,15 @@ class Net_SFTP_Stream {
|
||||
}
|
||||
|
||||
$result = $this->sftp->put($this->path, $data, NET_SFTP_STRING, $this->pos);
|
||||
if (isset($this->notification) && is_callable($this->notification)) {
|
||||
if (!$result) {
|
||||
call_user_func($this->notification, STREAM_NOTIFY_FAILURE, STREAM_NOTIFY_SEVERITY_ERR, $this->sftp->getLastSFTPError(), NET_SFTP_OPEN, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
// seems that PHP splits up strings into 8k blocks before calling stream_write
|
||||
call_user_func($this->notification, STREAM_NOTIFY_PROGRESS, STREAM_NOTIFY_SEVERITY_INFO, '', 0, strlen($data), strlen($data));
|
||||
}
|
||||
|
||||
if ($result === false) {
|
||||
return false;
|
||||
}
|
||||
@ -297,7 +350,7 @@ class Net_SFTP_Stream {
|
||||
* @return Integer
|
||||
* @access public
|
||||
*/
|
||||
function stream_tell()
|
||||
function _stream_tell()
|
||||
{
|
||||
return $this->pos;
|
||||
}
|
||||
@ -315,7 +368,7 @@ class Net_SFTP_Stream {
|
||||
* @return Boolean
|
||||
* @access public
|
||||
*/
|
||||
function stream_eof()
|
||||
function _stream_eof()
|
||||
{
|
||||
return $this->eof;
|
||||
}
|
||||
@ -328,7 +381,7 @@ class Net_SFTP_Stream {
|
||||
* @return Boolean
|
||||
* @access public
|
||||
*/
|
||||
function stream_seek($offset, $whence)
|
||||
function _stream_seek($offset, $whence)
|
||||
{
|
||||
switch ($whence) {
|
||||
case SEEK_SET:
|
||||
@ -357,7 +410,7 @@ class Net_SFTP_Stream {
|
||||
* @return Boolean
|
||||
* @access public
|
||||
*/
|
||||
function stream_metadata($path, $option, $var)
|
||||
function _stream_metadata($path, $option, $var)
|
||||
{
|
||||
$path = $this->_parse_path($path);
|
||||
if ($path === false) {
|
||||
@ -389,7 +442,7 @@ class Net_SFTP_Stream {
|
||||
* @return Resource
|
||||
* @access public
|
||||
*/
|
||||
function stream_cast($cast_as)
|
||||
function _stream_cast($cast_as)
|
||||
{
|
||||
return $this->sftp->fsock;
|
||||
}
|
||||
@ -401,7 +454,7 @@ class Net_SFTP_Stream {
|
||||
* @return Boolean
|
||||
* @access public
|
||||
*/
|
||||
function stream_lock($operation)
|
||||
function _stream_lock($operation)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -418,7 +471,7 @@ class Net_SFTP_Stream {
|
||||
* @return Boolean
|
||||
* @access public
|
||||
*/
|
||||
function rename($path_from, $path_to)
|
||||
function _rename($path_from, $path_to)
|
||||
{
|
||||
$path1 = parse_url($path_from);
|
||||
$path2 = parse_url($path_to);
|
||||
@ -457,7 +510,7 @@ class Net_SFTP_Stream {
|
||||
* @return Boolean
|
||||
* @access public
|
||||
*/
|
||||
function dir_opendir($path, $options)
|
||||
function _dir_opendir($path, $options)
|
||||
{
|
||||
$path = $this->_parse_path($path);
|
||||
if ($path === false) {
|
||||
@ -474,7 +527,7 @@ class Net_SFTP_Stream {
|
||||
* @return Mixed
|
||||
* @access public
|
||||
*/
|
||||
function dir_readdir()
|
||||
function _dir_readdir()
|
||||
{
|
||||
if (isset($this->entries[$this->pos])) {
|
||||
return $this->entries[$this->pos++];
|
||||
@ -488,7 +541,7 @@ class Net_SFTP_Stream {
|
||||
* @return Boolean
|
||||
* @access public
|
||||
*/
|
||||
function dir_rewinddir()
|
||||
function _dir_rewinddir()
|
||||
{
|
||||
$this->pos = 0;
|
||||
return true;
|
||||
@ -500,7 +553,7 @@ class Net_SFTP_Stream {
|
||||
* @return Boolean
|
||||
* @access public
|
||||
*/
|
||||
function dir_closedir()
|
||||
function _dir_closedir()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -516,7 +569,7 @@ class Net_SFTP_Stream {
|
||||
* @return Boolean
|
||||
* @access public
|
||||
*/
|
||||
function mkdir($path, $mode, $options)
|
||||
function _mkdir($path, $mode, $options)
|
||||
{
|
||||
$path = $this->_parse_path($path);
|
||||
if ($path === false) {
|
||||
@ -540,7 +593,7 @@ class Net_SFTP_Stream {
|
||||
* @return Boolean
|
||||
* @access public
|
||||
*/
|
||||
function rmdir($path, $options)
|
||||
function _rmdir($path, $options)
|
||||
{
|
||||
$path = $this->_parse_path($path);
|
||||
if ($path === false) {
|
||||
@ -558,7 +611,7 @@ class Net_SFTP_Stream {
|
||||
* @return Boolean
|
||||
* @access public
|
||||
*/
|
||||
function stream_flush()
|
||||
function _stream_flush()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -569,7 +622,7 @@ class Net_SFTP_Stream {
|
||||
* @return Mixed
|
||||
* @access public
|
||||
*/
|
||||
function stream_stat()
|
||||
function _stream_stat()
|
||||
{
|
||||
$results = $this->sftp->stat($this->path);
|
||||
if ($results === false) {
|
||||
@ -585,7 +638,7 @@ class Net_SFTP_Stream {
|
||||
* @return Boolean
|
||||
* @access public
|
||||
*/
|
||||
function unlink($path)
|
||||
function _unlink($path)
|
||||
{
|
||||
$path = $this->_parse_path($path);
|
||||
if ($path === false) {
|
||||
@ -607,7 +660,7 @@ class Net_SFTP_Stream {
|
||||
* @return Mixed
|
||||
* @access public
|
||||
*/
|
||||
function url_stat($path, $flags)
|
||||
function _url_stat($path, $flags)
|
||||
{
|
||||
$path = $this->_parse_path($path);
|
||||
if ($path === false) {
|
||||
@ -629,7 +682,7 @@ class Net_SFTP_Stream {
|
||||
* @return Boolean
|
||||
* @access public
|
||||
*/
|
||||
function stream_truncate($new_size)
|
||||
function _stream_truncate($new_size)
|
||||
{
|
||||
if (!$this->sftp->truncate($this->path, $new_size)) {
|
||||
return false;
|
||||
@ -653,10 +706,54 @@ class Net_SFTP_Stream {
|
||||
* @return Boolean
|
||||
* @access public
|
||||
*/
|
||||
function stream_set_option($option, $arg1, $arg2)
|
||||
function _stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close an resource
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function _stream_close()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* __call Magic Method
|
||||
*
|
||||
* When you're utilizing an SFTP stream you're not calling the methods in this class directly - PHP is calling them for you.
|
||||
* Which kinda begs the question... what methods is PHP calling and what parameters is it passing to them? This function
|
||||
* lets you figure that out.
|
||||
*
|
||||
* If NET_SFTP_STREAM_LOGGING is defined all calls will be output on the screen and then (regardless of whether or not
|
||||
* NET_SFTP_STREAM_LOGGING is enabled) the parameters will be passed through to the appropriate method.
|
||||
*
|
||||
* @param String
|
||||
* @param Array
|
||||
* @return Mixed
|
||||
* @access public
|
||||
*/
|
||||
function __call($name, $arguments)
|
||||
{
|
||||
if (defined('NET_SFTP_STREAM_LOGGING')) {
|
||||
echo $name . '(';
|
||||
$last = count($arguments) - 1;
|
||||
foreach ($arguments as $i => $argument) {
|
||||
var_export($argument);
|
||||
if ($i != $last) {
|
||||
echo ',';
|
||||
}
|
||||
}
|
||||
echo ")\r\n";
|
||||
}
|
||||
$name = '_' . $name;
|
||||
if (!method_exists($this, $name)) {
|
||||
return false;
|
||||
}
|
||||
return call_user_func_array(array($this, $name), $arguments);
|
||||
}
|
||||
}
|
||||
|
||||
stream_wrapper_register('sftp', 'Net_SFTP_Stream');
|
||||
stream_wrapper_register('sftp', 'Net_SFTP_Stream');
|
Loading…
Reference in New Issue
Block a user