package.php 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. <?php
  2. declare(strict_types=1);
  3. // GET api/v1/package.php?version=vX.Y.Z
  4. // Streams a release ZIP to an authenticated instance.
  5. require_once __DIR__ . "/../../includes/api.php";
  6. require_once __DIR__ . "/../../includes/releases.php";
  7. manageApiRequireMethod("GET");
  8. $instance = manageApiAuthenticate();
  9. $version = trim((string) ($_GET["version"] ?? ""));
  10. if (!manageIsVersion($version)) {
  11. manageApiFail(400, "Ungültige Version.");
  12. }
  13. try {
  14. $release = manageReleaseResolve($version);
  15. } catch (Throwable $exception) {
  16. manageApiFail(404, $exception->getMessage());
  17. }
  18. $path = $release["package_path"];
  19. $size = filesize($path);
  20. $handle = fopen($path, "rb");
  21. if ($size === false || $handle === false) {
  22. manageApiFail(500, "Release-Paket konnte nicht geöffnet werden.");
  23. }
  24. manageInstanceTouch($instance["id"], []);
  25. manageLogAccess("Package downloaded", [
  26. "instance" => $instance["id"],
  27. "version" => $version,
  28. ]);
  29. header("Content-Type: application/zip");
  30. header("Content-Disposition: attachment; filename=\"" . addcslashes(basename($path), "\"\\") . "\"");
  31. header("Content-Length: " . (string) $size);
  32. // Private: the response is tied to an authenticated instance, so no shared
  33. // cache may keep a copy.
  34. header("Cache-Control: private, no-store");
  35. header("X-Content-Type-Options: nosniff");
  36. fpassthru($handle);
  37. fclose($handle);