JFIF x x C C " } !1AQa "q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w !1AQ aq"2B #3Rbr{
File "SCP.php"
Full Path: /home/palsarh/web/palsarh.in/public_html/vendor/phpseclib/phpseclib/phpseclib/Net/SCP.php
File size: 9.39 KB
MIME-type: text/x-php
Charset: utf-8
<?php
/**
* Pure-PHP implementation of SCP.
*
* PHP version 5
*
* The API for this library is modeled after the API from PHP's {@link http://php.net/book.ftp FTP extension}.
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'vendor/autoload.php';
*
* $scp = new \phpseclib3\Net\SCP('www.domain.tld');
* if (!$scp->login('username', 'password')) {
* exit('Login Failed');
* }
*
* echo $scp->exec('pwd') . "\r\n";
* $scp->put('filename.ext', 'hello, world!');
* echo $scp->exec('ls -latr');
* ?>
* </code>
*
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2009 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
namespace phpseclib3\Net;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Exception\FileNotFoundException;
/**
* Pure-PHP implementations of SCP.
*
* @author Jim Wigginton <terrafrost@php.net>
*/
class SCP extends SSH2
{
/**
* Reads data from a local file.
*
* @see \phpseclib3\Net\SCP::put()
*/
const SOURCE_LOCAL_FILE = 1;
/**
* Reads data from a string.
*
* @see \phpseclib3\Net\SCP::put()
*/
// this value isn't really used anymore but i'm keeping it reserved for historical reasons
const SOURCE_STRING = 2;
/**
* SCP.php doesn't support SOURCE_CALLBACK because, with that one, we don't know the size, in advance
*/
//const SOURCE_CALLBACK = 16;
/**
* Error information
*
* @see self::getSCPErrors()
* @see self::getLastSCPError()
* @var array
*/
private $scp_errors = [];
/**
* Uploads a file to the SCP server.
*
* By default, \phpseclib\Net\SCP::put() does not read from the local filesystem. $data is dumped directly into $remote_file.
* So, for example, if you set $data to 'filename.ext' and then do \phpseclib\Net\SCP::get(), you will get a file, twelve bytes
* long, containing 'filename.ext' as its contents.
*
* Setting $mode to self::SOURCE_LOCAL_FILE will change the above behavior. With self::SOURCE_LOCAL_FILE, $remote_file will
* contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how
* large $remote_file will be, as well.
*
* Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take
* care of that, yourself.
*
* @param string $remote_file
* @param string $data
* @param int $mode
* @param callable $callback
* @return bool
* @access public
*/
public function put($remote_file, $data, $mode = self::SOURCE_STRING, $callback = null)
{
if (!($this->bitmap & self::MASK_LOGIN)) {
return false;
}
if (empty($remote_file)) {
// remote file cannot be blank
return false;
}
if (!$this->exec('scp -t ' . escapeshellarg($remote_file), false)) { // -t = to
return false;
}
$temp = $this->get_channel_packet(self::CHANNEL_EXEC, true);
if ($temp !== chr(0)) {
$this->close_channel(self::CHANNEL_EXEC, true);
return false;
}
$packet_size = $this->packet_size_client_to_server[self::CHANNEL_EXEC] - 4;
$remote_file = basename($remote_file);
$dataCallback = false;
switch (true) {
case is_resource($data):
$mode = $mode & ~self::SOURCE_LOCAL_FILE;
$info = stream_get_meta_data($data);
if (isset($info['wrapper_type']) && $info['wrapper_type'] == 'PHP' && $info['stream_type'] == 'Input') {
$fp = fopen('php://memory', 'w+');
stream_copy_to_stream($data, $fp);
rewind($fp);
} else {
$fp = $data;
}
break;
case $mode & self::SOURCE_LOCAL_FILE:
if (!is_file($data)) {
throw new FileNotFoundException("$data is not a valid file");
}
$fp = @fopen($data, 'rb');
if (!$fp) {
$this->close_channel(self::CHANNEL_EXEC, true);
return false;
}
}
if (isset($fp)) {
$stat = fstat($fp);
$size = !empty($stat) ? $stat['size'] : 0;
} else {
$size = strlen($data);
}
$sent = 0;
$size = $size < 0 ? ($size & 0x7FFFFFFF) + 0x80000000 : $size;
$temp = 'C0644 ' . $size . ' ' . $remote_file . "\n";
$this->send_channel_packet(self::CHANNEL_EXEC, $temp);
$temp = $this->get_channel_packet(self::CHANNEL_EXEC, true);
if ($temp !== chr(0)) {
$this->close_channel(self::CHANNEL_EXEC, true);
return false;
}
$sent = 0;
while ($sent < $size) {
$temp = $mode & self::SOURCE_STRING ? substr($data, $sent, $packet_size) : fread($fp, $packet_size);
$this->send_channel_packet(self::CHANNEL_EXEC, $temp);
$sent += strlen($temp);
if (is_callable($callback)) {
call_user_func($callback, $sent);
}
}
$this->close_channel(self::CHANNEL_EXEC, true);
if ($mode != self::SOURCE_STRING) {
fclose($fp);
}
return true;
}
/**
* Downloads a file from the SCP server.
*
* Returns a string containing the contents of $remote_file if $local_file is left undefined or a boolean false if
* the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the
* operation
*
* @param string $remote_file
* @param string $local_file
* @return mixed
* @access public
*/
public function get($remote_file, $local_file = null, $progressCallback = null)
{
if (!($this->bitmap & self::MASK_LOGIN)) {
return false;
}
if (!$this->exec('scp -f ' . escapeshellarg($remote_file), false)) { // -f = from
return false;
}
$this->send_channel_packet(self::CHANNEL_EXEC, chr(0));
$info = $this->get_channel_packet(self::CHANNEL_EXEC, true);
// per https://goteleport.com/blog/scp-familiar-simple-insecure-slow/ non-zero responses mean there are errors
if ($info[0] === chr(1) || $info[0] == chr(2)) {
$type = $info[0] === chr(1) ? 'warning' : 'error';
$this->scp_errors[] = "$type: " . substr($info, 1);
$this->close_channel(self::CHANNEL_EXEC, true);
return false;
}
$this->send_channel_packet(self::CHANNEL_EXEC, chr(0));
if (!preg_match('#(?<perms>[^ ]+) (?<size>\d+) (?<name>.+)#', rtrim($info), $info)) {
$this->close_channel(self::CHANNEL_EXEC, true);
return false;
}
$fclose_check = false;
if (is_resource($local_file)) {
$fp = $local_file;
} elseif (!is_null($local_file)) {
$fp = @fopen($local_file, 'wb');
if (!$fp) {
$this->close_channel(self::CHANNEL_EXEC, true);
return false;
}
$fclose_check = true;
} else {
$content = '';
}
$size = 0;
while (true) {
$data = $this->get_channel_packet(self::CHANNEL_EXEC, true);
// Terminate the loop in case the server repeatedly sends an empty response
if ($data === false) {
$this->close_channel(self::CHANNEL_EXEC, true);
// no data received from server
return false;
}
// SCP usually seems to split stuff out into 16k chunks
$length = strlen($data);
$size += $length;
$end = $size > $info['size'];
if ($end) {
$diff = $size - $info['size'];
$offset = $length - $diff;
if ($data[$offset] === chr(0)) {
$data = substr($data, 0, -$diff);
} else {
$type = $data[$offset] === chr(1) ? 'warning' : 'error';
$this->scp_errors[] = "$type: " . substr($data, 1);
$this->close_channel(self::CHANNEL_EXEC, true);
return false;
}
}
if (is_null($local_file)) {
$content .= $data;
} else {
fputs($fp, $data);
}
if (is_callable($progressCallback)) {
call_user_func($progressCallback, $size);
}
if ($end) {
break;
}
}
$this->close_channel(self::CHANNEL_EXEC, true);
if ($fclose_check) {
fclose($fp);
}
// if $content isn't set that means a file was written to
return isset($content) ? $content : true;
}
/**
* Returns all errors on the SCP layer
*
* @return array
*/
public function getSCPErrors()
{
return $this->scp_errors;
}
/**
* Returns the last error on the SCP layer
*
* @return string
*/
public function getLastSCPError()
{
return count($this->scp_errors) ? $this->scp_errors[count($this->scp_errors) - 1] : '';
}
}