2023-04-15 15:00:08 +00:00
|
|
|
/**
|
|
|
|
* The KeyLoader
|
|
|
|
*
|
|
|
|
* @var KeyLoader
|
|
|
|
* @since 3.2.0
|
|
|
|
*/
|
|
|
|
protected KeyLoader $key;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The client object
|
|
|
|
*
|
|
|
|
* @var SftpClient|null
|
|
|
|
* @since 3.2.0
|
|
|
|
**/
|
|
|
|
protected ?SftpClient $client = null;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The server details
|
|
|
|
*
|
|
|
|
* @var object
|
|
|
|
* @since 3.2.0
|
|
|
|
**/
|
|
|
|
protected ?object $details = null;
|
|
|
|
|
2023-10-24 08:36:46 +00:00
|
|
|
/**
|
|
|
|
* Application object.
|
|
|
|
*
|
|
|
|
* @var CMSApplication
|
|
|
|
* @since 3.2.0
|
|
|
|
**/
|
|
|
|
protected CMSApplication $app;
|
|
|
|
|
2023-04-15 15:00:08 +00:00
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
|
|
|
* @param KeyLoader $key The key loader object.
|
2023-10-24 08:36:46 +00:00
|
|
|
* @param CMSApplication|null $app The app object.
|
2023-04-15 15:00:08 +00:00
|
|
|
*
|
|
|
|
* @since 3.2.0
|
|
|
|
*/
|
2023-10-24 08:36:46 +00:00
|
|
|
public function __construct(KeyLoader $key, ?CMSApplication $app = null)
|
2023-04-15 15:00:08 +00:00
|
|
|
{
|
|
|
|
$this->key = $key;
|
2023-10-24 08:36:46 +00:00
|
|
|
$this->app = $app ?: Factory::getApplication();
|
2023-04-15 15:00:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* set the server details
|
|
|
|
*
|
|
|
|
* @param object $details The server details
|
|
|
|
*
|
|
|
|
* @return Sftp
|
|
|
|
* @since 3.2.0
|
|
|
|
**/
|
|
|
|
public function set(object $details): Sftp
|
|
|
|
{
|
|
|
|
// we need to make sure the if the details changed to get a new server client
|
|
|
|
if (!ObjectHelper::equal($details, $this->details))
|
|
|
|
{
|
|
|
|
// set the details
|
|
|
|
$this->details = $details;
|
|
|
|
|
|
|
|
// reset the client if it was set before
|
|
|
|
$this->client = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* move a file to server with the FTP client
|
|
|
|
*
|
|
|
|
* @param string $localPath The full local path to the file
|
|
|
|
* @param string $fileName The file name
|
|
|
|
*
|
|
|
|
* @return bool
|
|
|
|
* @since 3.2.0
|
|
|
|
**/
|
|
|
|
public function move(string $localPath, string $fileName): bool
|
|
|
|
{
|
|
|
|
if ($this->connected() &&
|
|
|
|
($data = FileHelper::getContent($localPath, null)) !== null)
|
|
|
|
{
|
|
|
|
// get the remote path
|
|
|
|
$path = '';
|
|
|
|
if (isset($this->details->path) &&
|
|
|
|
StringHelper::check($this->details->path) &&
|
|
|
|
$this->details->path !== '/')
|
|
|
|
{
|
2023-10-24 08:36:46 +00:00
|
|
|
$path = trim((string) $this->details->path);
|
|
|
|
$path = '/' . trim($path, '/') . '/';
|
2023-04-15 15:00:08 +00:00
|
|
|
}
|
|
|
|
|
2023-10-24 08:36:46 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
return $this->client->put($path . trim($fileName), $data);
|
|
|
|
}
|
|
|
|
catch(\Exception $e)
|
|
|
|
{
|
|
|
|
$this->app->enqueueMessage(
|
|
|
|
Text::sprintf('Moving of the %s failed', $fileName) . ': ' . $e->getMessage(),
|
|
|
|
'Error'
|
|
|
|
);
|
|
|
|
}
|
2023-04-15 15:00:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Make sure we are connected
|
|
|
|
*
|
|
|
|
* @return bool
|
|
|
|
* @since 3.2.0
|
|
|
|
**/
|
|
|
|
private function connected(): bool
|
|
|
|
{
|
|
|
|
// check if we have a connection
|
|
|
|
if ($this->client instanceof SftpClient && ($this->client->isConnected() || $this->client->ping()))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->client = $this->getClient();
|
|
|
|
|
|
|
|
return $this->client instanceof SftpClient;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get the SftpClient object
|
|
|
|
*
|
|
|
|
* @return SftpClient|null
|
|
|
|
* @since 3.2.0
|
|
|
|
**/
|
|
|
|
private function getClient(): ?SftpClient
|
|
|
|
{
|
|
|
|
// make sure we have a host value set
|
|
|
|
if (isset($this->details->host) && StringHelper::check($this->details->host) &&
|
|
|
|
isset($this->details->username) && StringHelper::check($this->details->username))
|
|
|
|
{
|
|
|
|
// insure the port is set
|
2023-10-24 08:36:46 +00:00
|
|
|
$port = (int)($this->details->port ?? 22);
|
2023-04-15 15:00:08 +00:00
|
|
|
|
|
|
|
// open the connection
|
|
|
|
$sftp = new SftpClient($this->details->host, $port);
|
|
|
|
|
|
|
|
// set the passphrase if it exist
|
2023-10-24 08:36:46 +00:00
|
|
|
$passphrase = (isset($this->details->secret) && StringHelper::check(trim($this->details->secret))) ? trim($this->details->secret) : false;
|
2023-04-15 15:00:08 +00:00
|
|
|
|
|
|
|
// set the password if it exist
|
2023-10-24 08:36:46 +00:00
|
|
|
$password = (isset($this->details->password) && StringHelper::check(trim($this->details->password))) ? trim($this->details->password) : false;
|
2023-04-15 15:00:08 +00:00
|
|
|
|
|
|
|
// now login based on authentication type
|
|
|
|
$key = null;
|
|
|
|
switch($this->details->authentication)
|
|
|
|
{
|
|
|
|
case 1: // password
|
2023-10-24 08:36:46 +00:00
|
|
|
$key = $password ?? null;
|
2023-04-15 15:00:08 +00:00
|
|
|
$password = null;
|
|
|
|
break;
|
|
|
|
case 2: // private key file
|
|
|
|
case 3: // both password and private key file
|
|
|
|
if (isset($this->details->private) && StringHelper::check($this->details->private) &&
|
|
|
|
($private_key = FileHelper::getContent($this->details->private, null)) !== null)
|
|
|
|
{
|
2023-10-24 08:36:46 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
$key = $this->key::load(trim($private_key), $passphrase);
|
|
|
|
}
|
|
|
|
catch(\Exception $e)
|
|
|
|
{
|
|
|
|
$this->app->enqueueMessage(
|
|
|
|
Text::_('Loading the private key file failed') . ': ' . $e->getMessage(),
|
|
|
|
'Error'
|
|
|
|
);
|
|
|
|
$key = null;
|
|
|
|
}
|
2023-04-15 15:00:08 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 4: // private key field
|
|
|
|
case 5: // both password and private key field
|
|
|
|
if (isset($this->details->private_key) && StringHelper::check($this->details->private_key))
|
|
|
|
{
|
2023-10-24 08:36:46 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
$key = $this->key::load(trim($this->details->private_key), $passphrase);
|
|
|
|
}
|
|
|
|
catch(\Exception $e)
|
|
|
|
{
|
|
|
|
$this->app->enqueueMessage(
|
|
|
|
Text::_('Loading the private key text failed') . ': ' . $e->getMessage(),
|
|
|
|
'Error'
|
|
|
|
);
|
|
|
|
$key = null;
|
|
|
|
}
|
2023-04-15 15:00:08 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2023-10-24 08:36:46 +00:00
|
|
|
// remove any null bites from the username
|
|
|
|
$this->details->username = trim($this->details->username);
|
|
|
|
|
2023-04-15 15:00:08 +00:00
|
|
|
// login
|
2023-10-24 08:36:46 +00:00
|
|
|
if (!empty($key) && !empty($password))
|
2023-04-15 15:00:08 +00:00
|
|
|
{
|
2023-10-24 08:36:46 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
$sftp->login($this->details->username, $key, $password);
|
|
|
|
return $sftp;
|
|
|
|
}
|
|
|
|
catch(\Exception $e)
|
|
|
|
{
|
|
|
|
$this->app->enqueueMessage(
|
|
|
|
Text::_('Login failed') . ': ' . $e->getMessage(),
|
|
|
|
'Error'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
elseif (!empty($key))
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
$sftp->login($this->details->username, $key);
|
|
|
|
return $sftp;
|
|
|
|
}
|
|
|
|
catch(\Exception $e)
|
|
|
|
{
|
|
|
|
$this->app->enqueueMessage(
|
|
|
|
Text::_('Login failed') . ': ' . $e->getMessage(),
|
|
|
|
'Error'
|
|
|
|
);
|
|
|
|
}
|
2023-04-15 15:00:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
2023-10-24 08:36:46 +00:00
|
|
|
}
|