summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-10-30 00:07:24 +0100
committersalmonik <salmonik@tuta.io>2026-10-30 00:07:24 +0100
commit2f92026ec648d47c25fea6fc8f354fbc04f4d714 (patch)
treea432320c6630eb9e5f44a2499a40da63fffbc37a
parentmake the download page dynamic: scan builds, show versions and SHA-256 (diff)
downloadzagan-bet-2f92026ec648d47c25fea6fc8f354fbc04f4d714.tar.gz
zagan-bet-2f92026ec648d47c25fea6fc8f354fbc04f4d714.zip
strip the download page to plain HTML: no CSS, sha256sum-format checksums
-rw-r--r--web/README.md5
-rw-r--r--web/index.php309
2 files changed, 53 insertions, 261 deletions
diff --git a/web/README.md b/web/README.md
index 3c6ee08..5434e28 100644
--- a/web/README.md
+++ b/web/README.md
@@ -2,7 +2,8 @@
2 2
3`index.php` scans `bin/client` and `bin/server` on every request and renders 3`index.php` scans `bin/client` and `bin/server` on every request and renders
4whatever builds it finds, with version, size and SHA-256. No database, no 4whatever builds it finds, with version, size and SHA-256. No database, no
5JavaScript, no dependencies. PHP 8.0+. 5JavaScript, no CSS, no dependencies. The page is plain browser defaults:
6black text, blue links, monospace checksums. PHP 8.0+.
6 7
7## Layout 8## Layout
8 9
@@ -62,3 +63,5 @@ Then open <http://127.0.0.1:8899/>.
62 handful of builds; add an mtime-keyed cache if the directory grows. 63 handful of builds; add an mtime-keyed cache if the directory grows.
63- The page lists every build it finds, newest version first, so old releases 64- The page lists every build it finds, newest version first, so old releases
64 stay downloadable until you remove them from `bin/`. 65 stay downloadable until you remove them from `bin/`.
66- The checksum block is in `sha256sum` format, so visitors can save it as
67 `SHA256SUMS` and run `sha256sum -c SHA256SUMS`.
diff --git a/web/index.php b/web/index.php
index cd77dad..361fdcf 100644
--- a/web/index.php
+++ b/web/index.php
@@ -164,274 +164,63 @@ foreach (KINDS as $kind => $meta) {
164<meta name="viewport" content="width=device-width, initial-scale=1"> 164<meta name="viewport" content="width=device-width, initial-scale=1">
165<title>Download · zagan.bet</title> 165<title>Download · zagan.bet</title>
166<meta name="description" content="Official zagan.bet client and server downloads."> 166<meta name="description" content="Official zagan.bet client and server downloads.">
167<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:"> 167<meta http-equiv="Content-Security-Policy" content="default-src 'none'">
168<link rel="icon" href="data:,">
169<style>
170 :root {
171 --bg: #0b0e11;
172 --panel: #11171d;
173 --line: #222c35;
174 --text: #dde6ec;
175 --muted: #8b9aa6;
176 --accent: #5fd0e0;
177 --win: #6ee7a0;
178 --radius: 10px;
179 }
180
181 * { box-sizing: border-box; }
182
183 body {
184 margin: 0;
185 background: var(--bg);
186 color: var(--text);
187 font: 16px/1.55 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
188 }
189
190 code, pre, .mono {
191 font-family: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;
192 }
193
194 .wrap {
195 max-width: 880px;
196 margin: 0 auto;
197 padding: 3rem 1.25rem 4rem;
198 }
199
200 header { margin-bottom: 2.5rem; }
201
202 h1 {
203 margin: 0 0 .35rem;
204 font: 700 2rem/1.1 ui-monospace, "SF Mono", Menlo, Consolas, monospace;
205 letter-spacing: -.02em;
206 }
207
208 h1 span { color: var(--accent); }
209
210 .tagline { margin: 0; color: var(--muted); }
211
212 .stamp { margin: .6rem 0 0; color: var(--muted); font-size: .8rem; }
213
214 section { margin-top: 2.5rem; }
215
216 h2 {
217 margin: 0 0 .9rem;
218 font-size: .8rem;
219 font-weight: 600;
220 letter-spacing: .12em;
221 text-transform: uppercase;
222 color: var(--muted);
223 border-bottom: 1px solid var(--line);
224 padding-bottom: .6rem;
225 }
226
227 .hint { margin: -.3rem 0 1rem; color: var(--muted); font-size: .9rem; }
228
229 .empty { color: var(--muted); font-size: .9rem; }
230
231 .grid {
232 list-style: none;
233 margin: 0;
234 padding: 0;
235 display: grid;
236 grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
237 gap: .9rem;
238 }
239
240 .card {
241 background: var(--panel);
242 border: 1px solid var(--line);
243 border-radius: var(--radius);
244 padding: 1rem;
245 display: flex;
246 flex-direction: column;
247 gap: .3rem;
248 }
249
250 .card-head {
251 display: flex;
252 align-items: baseline;
253 justify-content: space-between;
254 gap: .5rem;
255 }
256
257 .card h3 { margin: 0; font-size: 1rem; }
258
259 .ver {
260 font-size: .75rem;
261 color: var(--accent);
262 border: 1px solid var(--line);
263 border-radius: 999px;
264 padding: .1rem .5rem;
265 white-space: nowrap;
266 }
267
268 .card .arch { margin: 0; color: var(--muted); font-size: .85rem; }
269
270 .card .meta { margin: 0; color: var(--muted); font-size: .8rem; }
271
272 .card .btn { margin-top: .7rem; }
273
274 .btn {
275 display: block;
276 text-align: center;
277 text-decoration: none;
278 padding: .55rem .8rem;
279 border-radius: 7px;
280 background: var(--accent);
281 color: #06222a;
282 font-weight: 600;
283 font-size: .92rem;
284 }
285
286 .btn:hover { background: #86e2ee; }
287
288 .btn:focus-visible,
289 summary:focus-visible {
290 outline: 2px solid var(--win);
291 outline-offset: 2px;
292 }
293
294 pre {
295 margin: 0 0 1rem;
296 padding: .85rem 1rem;
297 overflow-x: auto;
298 background: var(--panel);
299 border: 1px solid var(--line);
300 border-radius: var(--radius);
301 font-size: .88rem;
302 line-height: 1.6;
303 }
304
305 pre .c { color: var(--muted); }
306
307 .table-wrap { overflow-x: auto; }
308
309 table {
310 width: 100%;
311 border-collapse: collapse;
312 font-size: .82rem;
313 }
314
315 th, td {
316 text-align: left;
317 padding: .55rem .7rem;
318 border-bottom: 1px solid var(--line);
319 vertical-align: top;
320 }
321
322 th {
323 color: var(--muted);
324 font-weight: 600;
325 font-size: .75rem;
326 letter-spacing: .06em;
327 text-transform: uppercase;
328 white-space: nowrap;
329 }
330
331 td.file { word-break: break-all; }
332 td.sum { word-break: break-all; color: var(--muted); }
333 td.size { white-space: nowrap; color: var(--muted); }
334
335 footer {
336 margin-top: 3rem;
337 padding-top: 1.5rem;
338 border-top: 1px solid var(--line);
339 color: var(--muted);
340 font-size: .88rem;
341 }
342
343 footer p { margin: .6rem 0 0; }
344
345 a { color: var(--accent); }
346</style>
347</head> 168</head>
348<body> 169<body>
349<div class="wrap">
350
351 <header>
352 <h1>zagan<span>.bet</span></h1>
353 <p class="tagline">Terminal betting. Slots, roulette, blackjack and crash.</p>
354 <?php if ($newest > 0): ?>
355 <p class="stamp">Builds published <?= e(gmdate('j M Y H:i', $newest)) ?> UTC</p>
356 <?php endif; ?>
357 </header>
358 170
359 <main> 171<h1>zagan.bet</h1>
360 <?php foreach (KINDS as $kind => $meta): ?> 172<p>Official client and server builds.</p>
361 <section> 173<?php if ($newest > 0): ?>
362 <h2><?= e($meta['title']) ?></h2> 174<p>Builds published <?= e(gmdate('j M Y H:i', $newest)) ?> UTC.</p>
363 <p class="hint"><?= e($meta['hint']) ?></p> 175<?php endif; ?>
364 176
365 <?php if ($releases[$kind] === []): ?> 177<h2>Client</h2>
366 <p class="empty">Nothing published yet.</p> 178<p>Needs a terminal of at least 80×24 cells.</p>
367 <?php else: ?> 179<?php if ($releases['client'] === []): ?>
368 <ul class="grid"> 180<p>Nothing published yet.</p>
369 <?php foreach ($releases[$kind] as $release): ?> 181<?php else: ?>
370 <li class="card"> 182<ul>
371 <div class="card-head"> 183<?php foreach ($releases['client'] as $release): ?>
372 <h3><?= e(PLATFORMS[$release['platform']] ?? ucfirst($release['platform'])) ?></h3> 184<li><a href="<?= e($release['href']) ?>" download><?= e(PLATFORMS[$release['platform']] ?? ucfirst($release['platform'])) ?> <?= e($release['arch']) ?><?php if (isset(ARCHES[$release['arch']])): ?> (<?= e(ARCHES[$release['arch']]) ?>)<?php endif; ?> — version <?= e($release['version']) ?> — <?= e(human_size($release['size'])) ?></a></li>
373 <span class="ver">v<?= e($release['version']) ?></span> 185<?php endforeach; ?>
374 </div> 186</ul>
375 <p class="arch"> 187<?php endif; ?>
376 <?= e($release['arch']) ?><?php if (isset(ARCHES[$release['arch']])): ?> 188
377 · <?= e(ARCHES[$release['arch']]) ?> 189<h2>Server</h2>
378 <?php endif; ?> 190<p>Generates its own TLS identity on first run.</p>
379 </p> 191<?php if ($releases['server'] === []): ?>
380 <p class="meta"><?= e(human_size($release['size'])) ?></p> 192<p>Nothing published yet.</p>
381 <a class="btn" href="<?= e($release['href']) ?>" download>Download</a> 193<?php else: ?>
382 </li> 194<ul>
383 <?php endforeach; ?> 195<?php foreach ($releases['server'] as $release): ?>
384 </ul> 196<li><a href="<?= e($release['href']) ?>" download><?= e(PLATFORMS[$release['platform']] ?? ucfirst($release['platform'])) ?> <?= e($release['arch']) ?><?php if (isset(ARCHES[$release['arch']])): ?> (<?= e(ARCHES[$release['arch']]) ?>)<?php endif; ?> — version <?= e($release['version']) ?> — <?= e(human_size($release['size'])) ?></a></li>
385 <?php endif; ?> 197<?php endforeach; ?>
386 </section> 198</ul>
387 <?php endforeach; ?> 199<?php endif; ?>
388 200
389 <?php $all = array_merge($releases['client'], $releases['server']); ?> 201<?php $all = array_merge($releases['client'], $releases['server']); ?>
390 <?php if ($all !== []): ?> 202<?php if ($all !== []): ?>
391 <section> 203<h2>SHA-256</h2>
392 <h2>Checksums</h2> 204<p>Save this block as <code>SHA256SUMS</code> and run <code>sha256sum -c SHA256SUMS</code>. On Windows use <code>Get-FileHash &lt;file&gt;</code>.</p>
393 <p class="hint">SHA-256 of every published file.</p> 205<pre><?php
394 <div class="table-wrap"> 206$sums = '';
395 <table> 207foreach ($all as $release) {
396 <thead> 208 $sums .= $release['sha256'] . ' ' . $release['file'] . "\n";
397 <tr> 209}
398 <th>File</th> 210echo e($sums);
399 <th>Version</th> 211?></pre>
400 <th>Size</th> 212<?php endif; ?>
401 <th>SHA-256</th>
402 </tr>
403 </thead>
404 <tbody>
405 <?php foreach ($all as $release): ?>
406 <tr>
407 <td class="file mono"><?= e($release['file']) ?></td>
408 <td><?= e($release['version']) ?></td>
409 <td class="size"><?= e(human_size($release['size'])) ?></td>
410 <td class="sum mono"><?= e($release['sha256']) ?></td>
411 </tr>
412 <?php endforeach; ?>
413 </tbody>
414 </table>
415 </div>
416 </section>
417 <?php endif; ?>
418 </main>
419 213
420 <footer> 214<h2>Running it</h2>
421 <h2>Running it</h2> 215<p>Client:</p>
422 <pre><code><span class="c"># client (use the file you downloaded)</span> 216<pre><code>chmod +x &lt;downloaded-client&gt;
423chmod +x &lt;downloaded-client&gt;
424./&lt;downloaded-client&gt;</code></pre> 217./&lt;downloaded-client&gt;</code></pre>
425 218<p>Server, first run creates <code>identity.p12</code>, <code>key.pem</code> and <code>cert.pem</code>:</p>
426 <pre><code><span class="c"># server: first run creates identity.p12, key.pem and cert.pem</span> 219<pre><code>chmod +x &lt;downloaded-server&gt;
427chmod +x &lt;downloaded-server&gt;
428./&lt;downloaded-server&gt; --init 220./&lt;downloaded-server&gt; --init
429./&lt;downloaded-server&gt; -i 0.0.0.0 -p 11525</code></pre> 221./&lt;downloaded-server&gt; -i 0.0.0.0 -p 11525</code></pre>
430 222
431 <p>Windows: run the <code>.exe</code> from Windows Terminal or another real terminal.</p> 223<p>Windows: run the <code>.exe</code> from Windows Terminal or another real terminal.</p>
432 <p>Verify a download before running it: <code>sha256sum &lt;file&gt;</code> (Linux) or <code>Get-FileHash &lt;file&gt;</code> (Windows).</p>
433 </footer>
434 224
435</div>
436</body> 225</body>
437</html> 226</html>