1<?php
2
3if (PHP_SAPI !== 'cli') {
4 exit(1);
5}
6
7$root = dirname(__DIR__);
8$directory = rtrim((string)($argv[1] ?? ''), '/\\');
9$jsonFile = $directory . '/update.json';
10$signatureFile = $directory . '/update.json.sig';
11if (!is_file($jsonFile) || !is_file($signatureFile) || !is_file($root . '/engine/update-public.pem')) {
12 fwrite(STDERR, "Release files are missing.\n");
13 exit(1);
14}
15
16$json = (string)file_get_contents($jsonFile);
17$signature = base64_decode(trim((string)file_get_contents($signatureFile)), true);
18$manifest = json_decode($json, true);
19if ($signature === false || !is_array($manifest) || openssl_verify($json, $signature, (string)file_get_contents($root . '/engine/update-public.pem'), OPENSSL_ALGO_SHA256) !== 1) {
20 fwrite(STDERR, "The release signature is invalid.\n");
21 exit(1);
22}
23
24$package = $directory . '/' . (string)$manifest['package']['name'];
25if (!is_file($package) || hash_file('sha256', $package) !== (string)$manifest['package']['sha256'] || filesize($package) !== (int)$manifest['package']['size']) {
26 fwrite(STDERR, "The package checksum or size is invalid.\n");
27 exit(1);
28}
29
30$zip = new ZipArchive();
31if ($zip->open($package) !== true) {
32 fwrite(STDERR, "The package cannot be opened.\n");
33 exit(1);
34}
35$seen = array();
36for ($index = 0; $index < $zip->numFiles; $index++) {
37 $path = (string)$zip->getNameIndex($index);
38 if (str_ends_with($path, '/')) {
39 continue;
40 }
41 $data = $zip->getFromIndex($index);
42 if (!is_string($data) || !isset($manifest['files'][$path]) || hash('sha256', $data) !== (string)$manifest['files'][$path]) {
43 $zip->close();
44 fwrite(STDERR, "A packaged file is invalid: " . $path . "\n");
45 exit(1);
46 }
47 $seen[$path] = true;
48}
49$zip->close();
50if (count($seen) !== count($manifest['files'])) {
51 fwrite(STDERR, "The signed file list does not match the package.\n");
52 exit(1);
53}
54
55echo "Valid release " . $manifest['version'] . "\n";
56echo count($seen) . " signed files\n";
57