| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- <?php
- declare(strict_types=1);
- // Flat-file storage primitives. Ported from the PSA order system
- // (includes/functions.php readJsonFile/writeJsonFile): atomic writes via a
- // temp file plus rename, so a crashed request can never leave a half-written
- // index behind.
- function manageEnsureDirectory(string $dir): void
- {
- if (!is_dir($dir) && !mkdir($dir, 02775, true) && !is_dir($dir)) {
- throw new RuntimeException("Verzeichnis konnte nicht erstellt werden: " . $dir);
- }
- @chmod($dir, 02775);
- }
- function manageReadJsonFile(string $file): array
- {
- if (!is_file($file)) {
- return [];
- }
- $content = file_get_contents($file);
- if ($content === false || trim($content) === "") {
- return [];
- }
- $decoded = json_decode($content, true);
- if (!is_array($decoded)) {
- throw new RuntimeException("JSON-Datei ist beschädigt: " . basename($file));
- }
- return $decoded;
- }
- function manageWriteJsonFile(string $file, array $data): void
- {
- manageEnsureDirectory(dirname($file));
- if (is_file($file) && !is_writable($file)) {
- @chmod($file, 0664);
- }
- $json = json_encode(
- $data,
- JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE,
- );
- if ($json === false) {
- throw new RuntimeException("JSON konnte nicht kodiert werden.");
- }
- $tmpFile = $file . ".tmp";
- if (file_put_contents($tmpFile, $json . PHP_EOL, LOCK_EX) === false) {
- throw new RuntimeException("JSON konnte nicht geschrieben werden.");
- }
- @chmod($tmpFile, 0664);
- // rename() is atomic on the same filesystem.
- if (!rename($tmpFile, $file)) {
- @unlink($tmpFile);
- throw new RuntimeException("JSON konnte nicht gespeichert werden.");
- }
- @chmod($file, 0664);
- }
- function manageRemoveDirectory(string $dir): void
- {
- if (!is_dir($dir)) {
- return;
- }
- $items = new RecursiveIteratorIterator(
- new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS),
- RecursiveIteratorIterator::CHILD_FIRST,
- );
- foreach ($items as $item) {
- if ($item->isDir()) {
- @rmdir($item->getPathname());
- } else {
- @unlink($item->getPathname());
- }
- }
- @rmdir($dir);
- }
- // Reads the first bytes of a file and reports whether they look like a ZIP
- // local file / empty archive / spanned archive header.
- function manageFileIsZip(string $path): bool
- {
- $handle = @fopen($path, "rb");
- if ($handle === false) {
- return false;
- }
- $signature = fread($handle, 4);
- fclose($handle);
- return $signature === "PK\x03\x04" ||
- $signature === "PK\x05\x06" ||
- $signature === "PK\x07\x08";
- }
|