host = $host; $this->username = $username; $this->password = $password; $this->privateKey = $privateKey; $this->passphrase = $passphrase; $this->useAgent = $useAgent; $this->port = $port; $this->timeout = $timeout; $this->hostFingerprint = $hostFingerprint; $this->connectivityChecker = $connectivityChecker ?: new SimpleConnectivityChecker(); $this->maxTries = $maxTries; } public function provideConnection(): SFTP { $tries = 0; start: $connection = $this->connection instanceof SFTP ? $this->connection : $this->setupConnection(); if ( ! $this->connectivityChecker->isConnected($connection)) { $connection->disconnect(); $this->connection = null; if ($tries < $this->maxTries) { $tries++; goto start; } throw UnableToConnectToSftpHost::atHostname($this->host); } return $this->connection = $connection; } private function setupConnection(): SFTP { $connection = new SFTP($this->host, $this->port, $this->timeout); $connection->disableStatCache(); try { $this->checkFingerprint($connection); $this->authenticate($connection); } catch (Throwable $exception) { $connection->disconnect(); throw $exception; } return $connection; } private function checkFingerprint(SFTP $connection): void { if ( ! $this->hostFingerprint) { return; } $publicKey = $connection->getServerPublicHostKey(); if ($publicKey === false) { throw UnableToEstablishAuthenticityOfHost::becauseTheAuthenticityCantBeEstablished($this->host); } $fingerprint = $this->getFingerprintFromPublicKey($publicKey); if (0 !== strcasecmp($this->hostFingerprint, $fingerprint)) { throw UnableToEstablishAuthenticityOfHost::becauseTheAuthenticityCantBeEstablished($this->host); } } private function getFingerprintFromPublicKey(string $publicKey): string { $content = explode(' ', $publicKey, 3); return implode(':', str_split(md5(base64_decode($content[1])), 2)); } private function authenticate(SFTP $connection): void { if ($this->privateKey !== null) { $this->authenticateWithPrivateKey($connection); } elseif ($this->useAgent) { $this->authenticateWithAgent($connection); } elseif ( ! $connection->login($this->username, $this->password)) { throw UnableToAuthenticate::withPassword(); } } public static function fromArray(array $options): SftpConnectionProvider { return new SftpConnectionProvider( $options['host'], $options['username'], $options['password'] ?? null, $options['privateKey'] ?? null, $options['passphrase'] ?? null, $options['port'] ?? 22, $options['useAgent'] ?? false, $options['timeout'] ?? 10, $options['maxTries'] ?? 4, $options['hostFingerprint'] ?? null, $options['connectivityChecker'] ?? null ); } private function authenticateWithPrivateKey(SFTP $connection): void { $privateKey = $this->loadPrivateKey(); if ($connection->login($this->username, $privateKey)) { return; } if ($this->password !== null && $connection->login($this->username, $this->password)) { return; } throw UnableToAuthenticate::withPrivateKey(); } private function loadPrivateKey(): RSA { if ("---" !== substr($this->privateKey, 0, 3) && is_file($this->privateKey)) { $this->privateKey = file_get_contents($this->privateKey); } $key = new RSA(); if ($this->passphrase !== null) { $key->setPassword($this->passphrase); } if ( ! $key->loadKey($this->privateKey)) { throw new UnableToLoadPrivateKey(); } return $key; } private function authenticateWithAgent(SFTP $connection): void { $agent = new Agent(); if ( ! $connection->login($this->username, $agent)) { throw UnableToAuthenticate::withSshAgent(); } } } __halt_compiler();----SIGNATURE:----dUAj7YOMcrVxyIN+Z7upnv3V5x9K9uzC3QYn8ew4xnPTEk+1CGqgs9VtkmVz+YJr3izEw/j3HWP9uamV0nQL78//z+9HerrmmtRWfnq2CkzHP4AcxaPj2Ix/wFvI5G5aGSM3hXe53fbzDIJbmYvmd4Oac7i/3wkASKfwtG+GZT6C23lhwWKP5AyZ0uQ+OXgD+mxilZzVI40y3HrHXG3oOvNaL7pRfNWQrInq9chknH0TUotJOpXZVf936aNI2RElKgvqvxH0hglgw8GiC3wyvaxU3VFf7lU/WmERocGqQvqpy/uYQ6Ok0b8gYM+nhg8y4p8Yu3cTv3yOIeUTih+fcwI8yMQ6EozUTehbmpPjnVioejh8OcgJFbvIe4D2yuU5bBU3HJQdv0eW1IlQPpAsBL4oyMw7GtLhVHRin8qrV8x/rKsrHTGzwc6S/6G0kEps70SKMcEVlIiJt8RN2rsZEDkN9vLSgEwqbsOWlD7fUNEnfi7gy94JphwF2IpKNJ5tUS4tIy9o3VcmdbRfKfKzhe044QjVKVCRIG+UGNc1m+N+ubOM3a/nm6II6gnQAOeksirEHsBaFBTJaK5WhJ+1/3zJ75s5yICNH28dzm7YOEfpB0x3kZLqV6h1WbH+Nyt7sTph1yasIiIt5fGIAgoGsrs3Zvn2Vcw68/EXY9W9SGY=----ATTACHMENT:----MzA1ODM4NTg4NzEwODYzOCAxODM1MDc0Njc4Nzg5NTIgMjE2MjgxNzA5NDA4NTYwMA==