diff --git a/composer.json b/composer.json index 1dd2ae3e898c9fc2201fb9c43b651d73bbd75f43..49b559c3eabe56769510e160144e013af0141285 100644 --- a/composer.json +++ b/composer.json @@ -11,12 +11,12 @@ } ], "require": { - "phpseclib/phpseclib": "^2.0.29" + "phpseclib/phpseclib": "^3.0" }, "require-dev": { - "drupal/key": "^1.8" + "drupal/key": "^1.19" }, "suggest": { - "drupal/key": "^1.8" + "drupal/key": "^1.19" } } diff --git a/sftp_client.info.yml b/sftp_client.info.yml index 2f79739ea64e3759892f28a5f1f0fcfc9bb37c6b..dc7cab61bde36a3a39ffa5830d3cc95bd9687d41 100644 --- a/sftp_client.info.yml +++ b/sftp_client.info.yml @@ -2,5 +2,5 @@ name: 'SFTP Client' description: 'The SFTP client for programmatic use.' package: Developer type: module -php: 7.3 -core_version_requirement: ^8 || ^9 +php: 8.1 +core_version_requirement: ^10.3 || ^11 diff --git a/src/SftpClient.php b/src/SftpClient.php index 3bc0e5b857f347a9da80305a2022e7f9cead5fb1..811c04e455c6f421fd2d402efa3d3d10afe469a7 100644 --- a/src/SftpClient.php +++ b/src/SftpClient.php @@ -3,14 +3,15 @@ namespace Drupal\sftp_client; use Drupal\Core\File\FileSystemInterface; +use Drupal\Core\File\FileExists; use Drupal\Core\Logger\LoggerChannelFactoryInterface; use Drupal\Core\Logger\LoggerChannelInterface; use Drupal\Core\Site\Settings; use Drupal\key\KeyRepositoryInterface; use Drupal\sftp_client\Exception\SftpException; use Drupal\sftp_client\Exception\SftpLoginException; -use phpseclib\Crypt\RSA; -use phpseclib\Net\SFTP; +use phpseclib3\Crypt\PublicKeyLoader; +use phpseclib3\Net\SFTP; use Psr\Log\LoggerInterface; use Psr\Log\LoggerTrait; use Psr\Log\LogLevel; @@ -91,7 +92,7 @@ class SftpClient implements SftpClientInterface { Settings $settings, FileSystemInterface $file_system, LoggerChannelFactoryInterface $logger_factory, - ?KeyRepositoryInterface $key_repository + ?KeyRepositoryInterface $key_repository, ) { $this->fileSystem = $file_system; $this->sftpSettings = $settings::get(static::SETTING, []); @@ -225,9 +226,11 @@ class SftpClient implements SftpClientInterface { } if ($this->settings['key_id'] !== FALSE) { - $rsa = new RSA(); - $rsa->loadKey($this->keyRepository->getKey($this->settings['key_id'])->getKeyValue()); - $rsa->setPassword($this->settings['password']); + $key_password = $this->settings['password']; + $key_value = $this->keyRepository->getKey($this->settings['key_id'])->getKeyValue(); + + /** @var \phpseclib3\Crypt\RSA $rsa */ + $rsa = PublicKeyLoader::load($key_value, $key_password); // Convert the password to RSA key. /* @see \phpseclib\Net\SFTP::_login_helper() */ @@ -387,9 +390,9 @@ class SftpClient implements SftpClientInterface { /** * {@inheritdoc} */ - public function moveFile(string $source, string $destination, int $replace = FileSystemInterface::EXISTS_ERROR): bool { + public function moveFile(string $source, string $destination, /* FileExists */ object $replace = FileExists::Error): bool { switch ($replace) { - case FileSystemInterface::EXISTS_RENAME: + case FileExists::Rename: $new_destination = $destination; $counter = 0; @@ -400,7 +403,7 @@ class SftpClient implements SftpClientInterface { $destination = $new_destination; break; - case FileSystemInterface::EXISTS_REPLACE: + case FileExists::Replace: if ($this->isFile($destination)) { $this->removeFile($destination); } @@ -515,7 +518,7 @@ class SftpClient implements SftpClientInterface { * * @link https://www.php.net/manual/en/class.filesystemiterator.php#filesystemiterator.constants.skip-dots */ - protected function listItems(string $path_remote, string $type_constant = NULL, bool $skip_dots = TRUE): \Generator { + protected function listItems(string $path_remote, ?string $type_constant = NULL, bool $skip_dots = TRUE): \Generator { $list = $this->connect()->rawlist($path_remote); if (\is_array($list)) { diff --git a/src/SftpClientInterface.php b/src/SftpClientInterface.php index 752163f29395f11ea90edddb750aa6deb72bdd4f..da24d352fa59dd8f62fda021ea41bf2a4b458b97 100644 --- a/src/SftpClientInterface.php +++ b/src/SftpClientInterface.php @@ -167,11 +167,11 @@ interface SftpClientInterface { * The path to a remote file. * @param string $destination * The path to a new location of a remote file. - * @param int $replace - * Replace behavior when the destination file already exists: - * - {@see FileSystemInterface::EXISTS_REPLACE}; - * - {@see FileSystemInterface::EXISTS_RENAME}; - * - {@see FileSystemInterface::EXISTS_ERROR}. + * @param object $replace + * Behavior when the destination file already exists: + * - {@see FileExists::Replace}; + * - {@see FileExists::Rename}; + * - {@see FileExists::Error}. * * @return bool * The state of whether a file was successfully moved. @@ -179,9 +179,9 @@ interface SftpClientInterface { * @throws \Drupal\sftp_client\Exception\SftpLoginException * When the connection to SFTP server cannot be established. * - * @see \Drupal\Core\File\FileSystemInterface + * @see \Drupal\Core\File\FileExists */ - public function moveFile(string $source, string $destination, int $replace): bool; + public function moveFile(string $source, string $destination, /* FileExists */ object $replace): bool; /** * Removes a remote file. diff --git a/src/SftpResource.php b/src/SftpResource.php index 6ccfa374b1e19b4673a0bda16d028f73d299a32e..9509861bc9fb5354e01695eebd53c79a8af3fd43 100644 --- a/src/SftpResource.php +++ b/src/SftpResource.php @@ -61,6 +61,11 @@ class SftpResource { * The data to create a resource. */ public function __construct(array $data) { + // Convert mode to permission. + if (!isset($data['permissions']) && isset($data['mode'])) { + $data['permissions'] = \decoct($data['mode']); + } + foreach ($this as $key => $value) { if (!isset($data[$key])) { throw new \InvalidArgumentException(\sprintf('The "%s" must exist in a resource definition!', $key)); diff --git a/tests/src/Unit/SftpClientTest.php b/tests/src/Unit/SftpClientTest.php index 47fae3b0b806d527256520e76e8af20ac8a3abc2..a322961233cbe567632e189c911e2e05b49f398c 100644 --- a/tests/src/Unit/SftpClientTest.php +++ b/tests/src/Unit/SftpClientTest.php @@ -11,7 +11,7 @@ use Drupal\key\KeyRepositoryInterface; use Drupal\sftp_client\Exception\SftpLoginException; use Drupal\sftp_client\SftpClient; use Drupal\Tests\UnitTestCase; -use phpseclib\Crypt\RSA; +use phpseclib3\Crypt\RSA; use PHPUnit\Framework\Error\Notice; /** @@ -61,17 +61,11 @@ class SftpClientTest extends UnitTestCase { $logger_channel = new LoggerChannel('sftp.client.test'); $logger_channel->addLogger($this->logger); - $this->fileSystem = $this - ->getMockBuilder(FileSystemInterface::class) - ->getMock(); + $this->fileSystem = $this->createMock(FileSystemInterface::class); - $this->keyRepository = $this - ->getMockBuilder(KeyRepositoryInterface::class) - ->getMock(); + $this->keyRepository = $this->createMock(KeyRepositoryInterface::class); - $this->loggerChannelFactory = $this - ->getMockBuilder(LoggerChannelFactoryInterface::class) - ->getMock(); + $this->loggerChannelFactory = $this->createMock(LoggerChannelFactoryInterface::class); $this->loggerChannelFactory ->method('get') @@ -92,7 +86,7 @@ class SftpClientTest extends UnitTestCase { protected function getSftpClient(Settings $settings, $key = NULL): SftpClient { $this->keyRepository ->method('getKey') - ->willReturn($key ?? $this->getMockBuilder(KeyInterface::class)->getMock()); + ->willReturn($key ?? $this->createMock(KeyInterface::class)); $sftp_client = new SftpClient( $settings, @@ -447,7 +441,7 @@ class SftpClientTest extends UnitTestCase { /** * {@inheritdoc} */ - public function providerRetry(): array { + public static function providerRetry(): array { return [ [ 5,