summaryrefslogtreecommitdiff
path: root/src/Connection.php
blob: 2052cd1605ea82b6e6a465c67752a5d574695e0f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<?php

namespace PHPIAC;

use PHPIAC\Support\SingletonTraitWithArguments;
use phpseclib3\Crypt\PublicKeyLoader;
use phpseclib3\Net\SFTP;
use phpseclib3\Net\SSH2;

/**
 * Class Connection
 *
 * @method static string exec(string $command, callback $callback = null)
 * @method static string|bool|null read(string $expect = '', int $read = 1)
 * @method static enablePty()
 * @method static disablePty()
 */
class Connection
{
    use SingletonTraitWithArguments;

    private SSH2 $ssh;
    private SFTP $sftp;

    /**
     * Connection constructor.
     *
     * @param string $host
     * @param string $user
     * @param string $key
     *
     * @throws \Exception
     */
    public function __construct(string $host, string $user, string $key)
    {
        $this->ssh = new SSH2($host);
        $key = PublicKeyLoader::load(file_get_contents($key));
        if (! $this->ssh->login($user, $key)) {
            throw new \Exception('SSH Login failed');
        }

        $this->sftp = new SFTP($host);
        if (! $this->sftp->login($user, $key)) {
            throw new \Exception('SFTP Login failed');
        }
    }

    /**
     * Calls SSH2 methods statically
     *
     * @param string $name
     * @param array $arguments
     *
     * @return mixed
     */
    public static function __callStatic(string $name, array $arguments): mixed
    {
        $self = self::getInstance();

        if (! method_exists($self->ssh, $name)) {
            return $self->sftp->$name(...$arguments);
        }

        return $self->ssh->$name(...$arguments);
    }

    /**
     * @see SFTP::put
     */
    public static function put($remote_file, $data, $mode = SFTP::SOURCE_STRING, $start = -1, $local_start = -1, $progressCallback = null): bool
    {
        $tmp = bin2hex(random_bytes(10)); # work around sftp sudo put restrictions

        return
            self::getInstance()->sftp->put("/tmp/$tmp", $data, $mode, $start, $local_start, $progressCallback) &&
            self::getInstance()->ssh->exec("sudo mv /tmp/$tmp $remote_file");
    }
}