| 123456789101112131415161718192021222324252627282930313233343536373839404142434445 |
- <?php
- /**
- * Gallery archive download: /gallery/download.php?g=<slug>
- *
- * Hands the visitor a short-lived presigned URL for the gallery's prebuilt ZIP
- * and gets out of the way. The transfer runs browser ↔ S3, so a 3 GB archive is
- * unaffected by the host's 60 s execution limit and stays resumable — this
- * script only ever sends a redirect.
- *
- * An out-of-date archive is refused rather than served, mirroring the disabled
- * button on the gallery page: a client must not be handed a ZIP that silently
- * omits the photos uploaded since it was built.
- *
- * Every failure looks the same as an unknown gallery, so the endpoint reveals
- * nothing the visitor does not already know from the link.
- */
- define('SITE_BASE', '../');
- require dirname(__DIR__) . '/app/bootstrap.php';
- session_boot();
- $slug = (string)($_GET['g'] ?? '');
- $gallery = $slug !== '' ? gallery_load($slug) : null;
- $allowed = $gallery !== null
- && !gallery_is_expired($gallery)
- && !empty($gallery['downloads_enabled'])
- && !empty($gallery['archive']['key'])
- && !archive_is_stale($gallery)
- // The same per-gallery session unlock the viewer sets.
- && (empty($gallery['password_hash']) || !empty($_SESSION['gallery_unlocked'][$slug]));
- if (!$allowed) {
- http_response_code(404);
- public_header('Download not available');
- echo '<div class="gate"><div class="gate-card"><h1>Download not available</h1>'
- . '<p class="page-sub">This download does not exist or is not ready yet.</p></div></div>';
- public_footer();
- exit;
- }
- // Short TTL on purpose: the browser only needs the URL long enough to start the
- // transfer. A GET already in flight is not cut off when the signature expires.
- redirect(s3_presign_get((string)$gallery['archive']['key'], 900));
|