| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- #!/usr/bin/env php
- <?php declare(strict_types=1);
- /**
- * PrivateBin
- *
- * a zero-knowledge paste bin
- *
- * @link https://github.com/PrivateBin/PrivateBin
- * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
- * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
- */
- /**
- * Regenerates the subresource integrity (SRI) hashes of all JavaScript files
- * in the 'sri' array of lib/Configuration.php. Entries for new files get
- * added, entries for removed files get dropped and the array is kept sorted.
- * On master this is run by the GitHub workflow .github/workflows/sri.yml.
- */
- define('PATH', dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR);
- // JS files that browsers never load, so they need no SRI hash
- const IGNORED_FILES = ['common.js', 'eslint.config.js'];
- $opts = getopt('ch', ['check', 'help']);
- if ($opts === false) {
- fail('Erroneous command line options. Please use --help');
- }
- if (array_key_exists('h', $opts) || array_key_exists('help', $opts)) {
- echo <<<'EOT'
- Usage:
- sri [--check]
- Regenerates the SRI hashes of all JavaScript files in js/ and writes them into
- the 'sri' array of lib/Configuration.php.
- Options:
- -c, --check don't write anything, exit with status 1 if any hash is
- outdated, missing or superfluous
- -h, --help displays this help message
- EOT;
- exit(0);
- }
- $check = array_key_exists('c', $opts) || array_key_exists('check', $opts);
- // calculate the hashes of all JS files
- $hashes = [];
- foreach (glob(PATH . 'js' . DIRECTORY_SEPARATOR . '*.js') as $file) {
- $name = basename($file);
- if (in_array($name, IGNORED_FILES, true)) {
- continue;
- }
- $hashes['js/' . $name] = 'sha512-' . base64_encode(
- hash('sha512', file_get_contents($file), true)
- );
- }
- if (count($hashes) === 0) {
- fail('No JS files found in ' . PATH . 'js');
- }
- ksort($hashes, SORT_STRING);
- // find the 'sri' array in the configuration defaults
- $file = PATH . 'lib' . DIRECTORY_SEPARATOR . 'Configuration.php';
- $content = file_get_contents($file);
- if ($content === false) {
- fail('Could not read ' . $file);
- }
- if (preg_match(
- '#^( *)\'sri\' => \[\n(.*?)^\1\],\n#ms',
- $content, $matches, PREG_OFFSET_CAPTURE
- ) !== 1) {
- fail('Could not find the \'sri\' array in ' . $file);
- }
- $indent = $matches[1][0] . ' ';
- $block = $matches[2][0];
- $start = $matches[2][1];
- $current = [];
- preg_match_all('#\'(js/[^\']+)\' *=> \'([^\']*)\',#', $block, $entries, PREG_SET_ORDER);
- foreach ($entries as $entry) {
- $current[$entry[1]] = $entry[2];
- }
- // generate the new array content, aligning the arrows
- $width = max(array_map('strlen', array_keys($hashes))) + 2;
- $lines = '';
- foreach ($hashes as $key => $hash) {
- $lines .= $indent . str_pad('\'' . $key . '\'', $width) . ' => \'' . $hash . '\',' . "\n";
- }
- // report the differences
- $changes = 0;
- foreach ($hashes as $key => $hash) {
- if (!array_key_exists($key, $current)) {
- echo 'added: ', $key, PHP_EOL;
- ++$changes;
- } elseif ($current[$key] !== $hash) {
- echo 'updated: ', $key, PHP_EOL;
- ++$changes;
- }
- }
- foreach (array_diff_key($current, $hashes) as $key => $hash) {
- echo 'removed: ', $key, PHP_EOL;
- ++$changes;
- }
- if ($lines === $block) {
- echo 'SRI hashes are up to date.', PHP_EOL;
- exit(0);
- }
- if ($check) {
- fail('SRI hashes in ' . $file . ' are outdated, run bin/sri to update them.', 1);
- }
- if ($changes === 0) {
- echo 'reformatted the \'sri\' array', PHP_EOL;
- }
- $content = substr($content, 0, $start) . $lines . substr($content, $start + strlen($block));
- if (file_put_contents($file, $content) === false) {
- fail('Could not write ' . $file);
- }
- /**
- * print an error to STDERR and exit
- *
- * @param string $message
- * @param int $code
- */
- function fail(string $message, int $code = 2): void
- {
- fwrite(STDERR, $message . PHP_EOL);
- exit($code);
- }
|