49 lines
1.2 KiB
PHP
49 lines
1.2 KiB
PHP
<?php
|
|
|
|
namespace App\Support;
|
|
|
|
use RuntimeException;
|
|
|
|
/** Required evidence must be readable; an I/O failure is never empty content or a matching hash. */
|
|
final class CheckedFile
|
|
{
|
|
/** @phpstan-impure */
|
|
public static function read(string $path): string
|
|
{
|
|
$bytes = @file_get_contents($path);
|
|
if ($bytes === false) {
|
|
throw new RuntimeException('Required file could not be read.');
|
|
}
|
|
|
|
return $bytes;
|
|
}
|
|
|
|
/** @phpstan-impure */
|
|
public static function sha256(string $path): string
|
|
{
|
|
$hash = @hash_file('sha256', $path);
|
|
if ($hash === false) {
|
|
throw new RuntimeException('Required file integrity could not be verified.');
|
|
}
|
|
|
|
return $hash;
|
|
}
|
|
|
|
/** @phpstan-impure */
|
|
public static function size(string $path): int
|
|
{
|
|
$size = @filesize($path);
|
|
if ($size === false) {
|
|
throw new RuntimeException('Required file size could not be verified.');
|
|
}
|
|
|
|
return $size;
|
|
}
|
|
|
|
/** @phpstan-impure */
|
|
public static function matches(string $path, string $expected): bool
|
|
{
|
|
return hash_equals($expected, self::sha256($path));
|
|
}
|
|
}
|