1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace EasyRSA; |
6
|
|
|
|
7
|
|
|
use EasyRSA\Interfaces\DownloaderInterface; |
8
|
|
|
use splitbrain\PHPArchive\Tar; |
9
|
|
|
|
10
|
|
|
class Downloader extends Worker implements DownloaderInterface |
11
|
|
|
{ |
12
|
|
|
/** |
13
|
|
|
* Url via which possible to get the latest release of EasyRSA. |
14
|
|
|
*/ |
15
|
|
|
public const URL_LATEST_RELEASE = 'https://api.github.com/repos/OpenVPN/easy-rsa/releases/latest'; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* Exec some operation by cURL. |
19
|
|
|
* |
20
|
|
|
* @param string $url |
21
|
|
|
* @param string|null $filename |
22
|
|
|
* |
23
|
|
|
* @return string|null |
24
|
|
|
*/ |
25
|
|
|
private function curlExec(string $url, string $filename = null): ?string |
26
|
|
|
{ |
27
|
|
|
$curl = curl_init(); |
28
|
|
|
|
29
|
|
|
curl_setopt($curl, CURLOPT_USERAGENT, 'useragent'); |
30
|
|
|
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); |
31
|
|
|
curl_setopt($curl, CURLOPT_URL, $url); |
32
|
|
|
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); |
33
|
|
|
|
34
|
|
|
// If filename is not set |
35
|
|
|
if (null !== $filename) { |
36
|
|
|
$fp = fopen($filename, 'wb+'); |
37
|
|
|
curl_setopt($curl, CURLOPT_FILE, $fp); |
38
|
|
|
} |
39
|
|
|
|
40
|
|
|
$result = curl_exec($curl); |
41
|
|
|
curl_close($curl); |
42
|
|
|
|
43
|
|
|
return is_bool($result) ? null : $result; |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* {@inheritdoc} |
48
|
|
|
*/ |
49
|
|
|
public function getLatestVersion(): string |
50
|
|
|
{ |
51
|
|
|
$json = $this->curlExec(self::URL_LATEST_RELEASE); |
52
|
|
|
$json = json_decode($json, true, 512, JSON_THROW_ON_ERROR); |
53
|
|
|
|
54
|
|
|
return $json['tarball_url']; |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* {@inheritdoc} |
59
|
|
|
*/ |
60
|
|
|
public function downloadLatestVersion(): ?string |
61
|
|
|
{ |
62
|
|
|
// Get full path to archive file |
63
|
|
|
$filename = $this->config->getArchive(); |
64
|
|
|
|
65
|
|
|
// Get url with latest release |
66
|
|
|
$latest = $this->getLatestVersion(); |
67
|
|
|
|
68
|
|
|
// Download and return status |
69
|
|
|
return $this->curlExec($latest, $filename); |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* {@inheritdoc} |
74
|
|
|
* |
75
|
|
|
* @throws \splitbrain\PHPArchive\ArchiveIllegalCompressionException If archive is broken |
76
|
|
|
* @throws \splitbrain\PHPArchive\ArchiveIOException If not possible to read archive |
77
|
|
|
* @throws \splitbrain\PHPArchive\ArchiveCorruptedException If archive corrupted |
78
|
|
|
*/ |
79
|
|
|
public function extractArchive(): array |
80
|
|
|
{ |
81
|
|
|
$tar = new Tar(); |
82
|
|
|
$tar->open($this->config->get('archive')); |
|
|
|
|
83
|
|
|
$tar->extract($this->config->get('scripts'), 1); |
|
|
|
|
84
|
|
|
|
85
|
|
|
return $tar->contents(); |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* {@inheritdoc} |
90
|
|
|
* |
91
|
|
|
* @throws \splitbrain\PHPArchive\ArchiveIllegalCompressionException If archive is broken |
92
|
|
|
* @throws \splitbrain\PHPArchive\ArchiveIOException If not possible to read archive |
93
|
|
|
* @throws \splitbrain\PHPArchive\ArchiveCorruptedException If archive corrupted |
94
|
|
|
*/ |
95
|
|
|
public function getEasyRSA(): void |
96
|
|
|
{ |
97
|
|
|
$this->downloadLatestVersion(); |
98
|
|
|
$this->extractArchive(); |
99
|
|
|
} |
100
|
|
|
} |
101
|
|
|
|
This check looks at variables that are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.