2f2e8869d6
Move shared PHP code into private/, move JavaScript files into js/, and block direct access to private/. Remove unused API key and cache artifacts from the working tree.
188 lines
4.2 KiB
PHP
188 lines
4.2 KiB
PHP
<?php
|
|
/*
|
|
* rktpkgs.php
|
|
*
|
|
* Maakt een volledige HTML-index van de Racket package catalogus.
|
|
*
|
|
* Bron:
|
|
* https://pkgs.racket-lang.org/pkgs-all
|
|
*
|
|
* Output:
|
|
* Alleen HTML.
|
|
*
|
|
* Package-links:
|
|
* /package?name=<pkg-name>&next=<id>
|
|
*
|
|
* Regels:
|
|
* - Geen filterveld.
|
|
* - Geen git-adressen tonen.
|
|
* - Geen package-details tonen.
|
|
* - Geen package-downloads implementeren in dit script.
|
|
* - De package-naam zelf is de link.
|
|
* - Eén next-id per gegenereerde HTML-pagina.
|
|
*
|
|
* .htaccess:
|
|
*
|
|
* Options -MultiViews
|
|
* RewriteEngine On
|
|
* RewriteRule ^racket-pkg-index$ rktpkgs.php [L,QSA]
|
|
*/
|
|
|
|
ini_set('display_errors', '1');
|
|
ini_set('display_startup_errors', '1');
|
|
ini_set('log_errors', '1');
|
|
error_reporting(E_ALL);
|
|
|
|
require_once __DIR__ . '/private/nexttoken.php';
|
|
require_once __DIR__ . '/private/lib/catalog-http.php';
|
|
require_once __DIR__ . '/private/lib/racket-data.php';
|
|
|
|
$TOKENS = new NextTokenStore(__DIR__ . '/data/racket-sandbox.sqlite');
|
|
|
|
@set_time_limit(180);
|
|
ignore_user_abort(false);
|
|
|
|
define('CATALOG_PKGS_ALL', 'https://pkgs.racket-lang.org/pkgs-all');
|
|
|
|
define('CACHE_DIR', __DIR__ . '/data');
|
|
define('CACHE_FILE', CACHE_DIR . '/pkgs-all.rktd');
|
|
define('CACHE_META_FILE', CACHE_DIR . '/pkgs-all.meta.json');
|
|
define('CACHE_TTL', 3600);
|
|
|
|
/*
|
|
* Eén next-id voor alle package-links op deze pagina.
|
|
*/
|
|
$NEXT_ID = $TOKENS->create();
|
|
|
|
function h($s)
|
|
{
|
|
return htmlspecialchars((string)$s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
|
|
}
|
|
|
|
function current_scheme()
|
|
{
|
|
if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
|
|
return strtolower(trim(explode(',', $_SERVER['HTTP_X_FORWARDED_PROTO'])[0]));
|
|
}
|
|
|
|
return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
|
|
}
|
|
|
|
function current_host()
|
|
{
|
|
return $_SERVER['HTTP_HOST'] ?? 'localhost';
|
|
}
|
|
|
|
function make_url($path, $query = array())
|
|
{
|
|
global $NEXT_ID;
|
|
|
|
$query['next'] = $NEXT_ID;
|
|
|
|
return current_scheme() . '://' . current_host() . $path . '?' . http_build_query($query);
|
|
}
|
|
|
|
function html_response($html, $status = 200)
|
|
{
|
|
http_response_code($status);
|
|
header('Content-Type: text/html; charset=utf-8');
|
|
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
|
|
header('Pragma: no-cache');
|
|
|
|
echo $html;
|
|
exit;
|
|
}
|
|
|
|
function fail_html($message, $status = 500)
|
|
{
|
|
html_response(
|
|
'<!doctype html>' .
|
|
'<html><head><meta charset="utf-8"><title>Error</title></head>' .
|
|
'<body><h1>Error</h1><pre>' . h($message) . '</pre></body></html>',
|
|
$status
|
|
);
|
|
}
|
|
|
|
function get_pkgs_all_text()
|
|
{
|
|
try {
|
|
return catalog_http_fetch_cached(
|
|
CATALOG_PKGS_ALL,
|
|
CACHE_FILE,
|
|
CACHE_META_FILE,
|
|
CACHE_TTL,
|
|
'rktsndbx-rktpkgs/1.0',
|
|
180
|
|
);
|
|
} catch (Throwable $e) {
|
|
fail_html($e->getMessage());
|
|
}
|
|
}
|
|
|
|
function serve_index()
|
|
{
|
|
global $NEXT_ID;
|
|
|
|
$text = get_pkgs_all_text();
|
|
$names = rktd_extract_top_level_package_names($text);
|
|
|
|
if (count($names) === 0) {
|
|
fail_html('Geen package-namen gevonden in pkgs-all.');
|
|
}
|
|
|
|
$rows = '';
|
|
|
|
foreach ($names as $i => $name) {
|
|
$url = make_url('/package', array('name' => $name));
|
|
|
|
$rows .=
|
|
'<tr id="pkg-' . h($name) . '">' .
|
|
'<td>' . h((string)($i + 1)) . '</td>' .
|
|
'<td class="pkg-name">' .
|
|
'<a class="pkg-link" href="' . h($url) . '">' . h($name) . '</a>' .
|
|
'</td>' .
|
|
'</tr>' . "\n";
|
|
}
|
|
|
|
html_response('<!doctype html>
|
|
<html lang="nl">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>Racket package index</title>
|
|
<link rel="stylesheet" href="/styles.css">
|
|
</head>
|
|
<body class="simple-doc package-index-page">
|
|
|
|
<h1>Racket package index</h1>
|
|
|
|
<p>
|
|
Volledige HTML-index van de Racket package catalogus op basis van
|
|
<code>pkgs-all</code>. De package-naam is de ophaallink via
|
|
<code>rktsndbx.dijkewijk.nl</code>.
|
|
</p>
|
|
|
|
<p>
|
|
Aantal packages: <code>' . h((string)count($names)) . '</code><br>
|
|
next-id voor alle package-links op deze pagina:
|
|
<code>' . h($NEXT_ID) . '</code>
|
|
</p>
|
|
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>#</th>
|
|
<th>package</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
' . $rows . '
|
|
</tbody>
|
|
</table>
|
|
|
|
</body>
|
|
</html>');
|
|
}
|
|
|
|
$TOKENS->check_valid_next('html');
|
|
serve_index();
|