gallery.php 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. <?php
  2. /**
  3. * Client gallery viewer: /gallery.php?g=<slug>
  4. *
  5. * - Unknown or expired galleries show the same neutral "not available" page.
  6. * - Password-protected galleries show a password form; a successful unlock
  7. * is remembered in the session for that gallery only.
  8. * - Thumbnails and full-res originals are loaded by the browser directly
  9. * from S3 via short-lived presigned URLs.
  10. */
  11. require dirname(__DIR__) . '/app/bootstrap.php';
  12. session_boot();
  13. $slug = (string)($_GET['g'] ?? '');
  14. $gallery = $slug !== '' ? gallery_load($slug) : null;
  15. if ($gallery === null || gallery_is_expired($gallery)) {
  16. http_response_code(404);
  17. public_header('Gallery not available');
  18. echo '<div class="gate"><div class="gate-card"><h1>Gallery not available</h1>'
  19. . '<p class="page-sub">This gallery does not exist or is no longer online.</p></div></div>';
  20. public_footer();
  21. exit;
  22. }
  23. $needsPassword = !empty($gallery['password_hash']);
  24. $unlocked = !$needsPassword || !empty($_SESSION['gallery_unlocked'][$slug]);
  25. if ($needsPassword && !$unlocked && $_SERVER['REQUEST_METHOD'] === 'POST') {
  26. csrf_verify();
  27. if (password_verify((string)($_POST['password'] ?? ''), $gallery['password_hash'])) {
  28. $_SESSION['gallery_unlocked'][$slug] = true;
  29. redirect('gallery.php?g=' . rawurlencode($slug));
  30. }
  31. $error = 'Wrong password.';
  32. }
  33. if ($needsPassword && !$unlocked) {
  34. public_header(e($gallery['title']));
  35. ?>
  36. <div class="gate"><div class="gate-card">
  37. <h1><?= e($gallery['title']) ?></h1>
  38. <?php if (!empty($error)): ?><div class="flash flash-error"><?= e($error) ?></div><?php endif; ?>
  39. <form method="post">
  40. <?= csrf_field() ?>
  41. <label for="pw">Password</label>
  42. <input type="password" id="pw" name="password" autofocus autocomplete="off">
  43. <button type="submit">Open gallery</button>
  44. </form>
  45. </div></div>
  46. <?php
  47. public_footer();
  48. exit;
  49. }
  50. public_header(e($gallery['title']));
  51. ?>
  52. <main class="page">
  53. <h1 class="page-title"><?= e($gallery['title']) ?></h1>
  54. <p class="page-sub">
  55. <?= count($gallery['images'] ?? []) ?> photos
  56. <?php if (!empty($gallery['expires_at'])): ?>
  57. · available until <?= e($gallery['expires_at']) ?>
  58. <?php endif; ?>
  59. </p>
  60. <div class="grid">
  61. <?php foreach ($gallery['images'] ?? [] as $img): ?>
  62. <a href="<?= e(s3_presign_get($img['key'])) ?>">
  63. <img src="<?= e(s3_presign_get($img['thumb'] ?? $img['key'])) ?>"
  64. alt="<?= e($img['name'] ?? '') ?>" loading="lazy">
  65. </a>
  66. <?php endforeach; ?>
  67. </div>
  68. </main>
  69. <?php public_footer(); ?>