clients: Move /clients to sync.elwig.at

This commit is contained in:
2025-05-03 16:22:30 +02:00
parent 223c959cd9
commit 25805f0475
6 changed files with 16 additions and 305 deletions

View File

@ -19,15 +19,3 @@ function authenticate(): void {
http_401_unauthorized();
}
}
function authenticate_client(string $client): void {
global $CLIENT_CREDENTIALS;
$credentials = $CLIENT_CREDENTIALS[$client];
if (!array_key_exists('PHP_AUTH_USER', $_SERVER) ||
!array_key_exists('PHP_AUTH_PW', $_SERVER) ||
!array_key_exists($_SERVER['PHP_AUTH_USER'], $credentials) ||
$_SERVER['PHP_AUTH_PW'] !== $credentials[$_SERVER['PHP_AUTH_USER']])
{
http_401_unauthorized();
}
}

View File

@ -1,16 +1,9 @@
<?php
global $GITEA_TOKEN;
global $CREDENTIALS;
global $CLIENT_CREDENTIALS;
$GITEA_TOKEN = 'token';
$CREDENTIALS = [
'username' => 'password',
];
$CLIENT_CREDENTIALS = [
'name' => [
'username' => 'password',
],
];

View File

@ -1,276 +0,0 @@
<?php
require ".php/format.inc";
require ".php/auth.inc";
require ".php/credentials.inc";
global $CLIENT_CREDENTIALS;
$clients = array_keys($CLIENT_CREDENTIALS);
$format = get_fmt();
function get_zip_meta($path): array {
$meta = 'null';
$fp = fopen($path, "rb");
$zipHdr1 = fread($fp, 30);
if (strlen($zipHdr1) !== 30 || !str_starts_with($zipHdr1, "PK\x03\x04") ||
$zipHdr1[8] !== "\x00" || $zipHdr1[9] !== "\x00" || $zipHdr1[26] !== "\x07" || $zipHdr1[27] !== "\x00")
{
fclose($fp);
return array($meta, null, null);
}
$extraFieldLen1 = unpack("v", substr($zipHdr1, 28, 2))[1];
$name1 = fread($fp, 7);
fseek($fp, $extraFieldLen1, SEEK_CUR);
$data1 = fread($fp, unpack("V", substr($zipHdr1, 18, 4))[1]);
if ($name1 !== "version" || !str_starts_with($data1, "elwig:")) {
fclose($fp);
return array($meta, null, null);
}
$version = (int)substr($data1, 6);
$zipHdr2 = fread($fp, 30);
if (strlen($zipHdr2) !== 30 || !str_starts_with($zipHdr2, "PK\x03\x04") ||
$zipHdr2[8] !== "\x00" || $zipHdr2[9] !== "\x00" || $zipHdr2[26] !== "\x09" || $zipHdr2[27] !== "\x00")
{
fclose($fp);
return array($meta, $version, null);
}
$extraFieldLen2 = unpack("v", substr($zipHdr2, 28, 2))[1];
$name2 = fread($fp, 9);
fseek($fp, $extraFieldLen2, SEEK_CUR);
if ($name2 !== "meta.json") {
fclose($fp);
return array($meta, $version, null);
}
$meta = fread($fp, unpack("V", substr($zipHdr2, 18, 4))[1]);
$files = "{";
$first = true;
while (!feof($fp)) {
$zipHdr3 = fread($fp, 30);
if (strlen($zipHdr3) !== 30 || !str_starts_with($zipHdr3, "PK\x03\x04"))
continue;
$compSize = unpack("V", substr($zipHdr3, 18, 4))[1];
$uncompSize = unpack("V", substr($zipHdr3, 22, 4))[1];
$name = fread($fp, unpack("v", substr($zipHdr3, 26, 2))[1]);
$crc = unpack("V", substr($zipHdr3, 14, 4))[1];
fseek($fp, $compSize, SEEK_CUR);
$hex = substr("00000000" . dechex($crc), -8);
if (!$first) $files .= ", ";
$files .= "\"$name\": {\"compressed_size\": $compSize, \"uncompressed_size\": $uncompSize, \"crc32\": \"$hex\"}";
$first = false;
}
$files .= "}";
fclose($fp);
return array($meta, $version, $files);
}
$path = $_SERVER['PATH_INFO'];
if ($path == '') {
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
header('Status: 405');
header('Allow: GET');
if ($format === 'text') {
header('Content-Type: text/plain; charset=UTF-8');
header('Content-Length: 23');
echo "405 Method Not Allowed\n";
} else if ($format === 'json') {
header('Content-Type: application/json; charset=UTF-8');
header('Content-Length: 48');
echo "{\"errors\": [{\"message\": \"Method not allowed\"}]}\n";
} else {
header('Content-Type: text/html; charset=UTF-8');
header('Content-Length: 0');
}
exit();
}
if ($format === 'text') {
header('Content-Type: text/plain; charset=UTF-8');
foreach ($clients as $c)
echo "$c\n";
} else if ($format === 'json') {
header('Content-Type: application/json; charset=UTF-8');
echo "{\"data\": [";
$first = true;
foreach ($clients as $c) {
if (!$first) echo ",";
echo "\n {\"name\": \"$c\"}";
$first = false;
}
echo "\n]}\n";
} else if ($format === 'html') {
header('Content-Type: application/xhtml+xml; charset=UTF-8');
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
?>
<html xmlns="http://www.w3.org/1999/xhtml" lang="de">
<head>
<meta charset="UTF-8"/>
<title>Mandanten - Elwig</title>
<meta name="description" content="Elektronische Winzergenossenschaftsverwaltung"/>
<link rel="icon" href="/favicon.ico" sizes="16x16 20x20 24x24 30x30 32x32 36x36 40x40 48x48 60x60 64x64 72x72 80x80 96x96 128x128 256x256"/>
<link rel="stylesheet" href="/res/style.css"/>
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
</head>
<body>
<main>
<section>
<h3>Mandanten</h3>
<p class="center"><a href="/">Startseite</a></p>
<table>
<thead><tr><th>Name</th></tr></thead>
<tbody>
<?php foreach ($clients as $c) {
echo " <tr><td><a href='clients/$c'>$c</a></td></tr>\n";
} ?>
</tbody>
</table>
<p class="center"><a href="?format=json">JSON-Format</a></p>
</section>
</main>
</body>
</html>
<?php }
exit();
}
foreach ($clients as $c) {
if ($path !== "/$c" && !str_starts_with($path, "/$c/"))
continue;
header('Content-Type: text/plain; charset=UTF-8');
authenticate_client($c);
if ($path === "/$c") {
header('Status: 308');
header("Location: $c/");
header('Content-Length: 23');
exit("308 Permanent Redirect\n");
} else if ($path === "/$c/") {
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
header("Status: 405");
header("Allow: GET");
header('Content-Length: 23');
exit("405 Method Not Allowed\n");
}
header('Content-Type: application/json; charset=UTF-8');
echo "{\"data\": [\n";
$first = true;
foreach (scandir(".data/clients/$c/") as $file) {
if (str_starts_with($file, ".") || str_ends_with($file, ".php") || str_ends_with($file, ".inc")) continue;
if (!$first) echo ",\n";
$path = ".data/clients/$c/$file";
$size = filesize($path);
$url = "https://elwig.at/clients/$c/$file";
$mod = date(DATE_ATOM, filemtime($path));
$cre = date(DATE_ATOM, filectime($path));
$datetime = "null";
$zwstid = "null";
if (str_ends_with($file, ".elwig.zip") && substr_count($file, "_") === 2) {
$parts = explode("_", substr($file, 0, -10));
$time = str_replace("-", ":", $parts[1]);
$dt = DateTime::createFromFormat("Y-m-d H:i:s", "$parts[0] $time");
$datetime = '"' . $dt->format(DateTimeInterface::RFC3339) . '"';
$zwstid = "\"$parts[2]\"";
}
list($meta, $version, $files) = get_zip_meta($path);
$files ??= "null";
$version ??= "null";
echo " {\"name\": \"$file\", \"timestamp\": $datetime, \"zwstid\": $zwstid, \"meta\": $meta, \"files\": $files, " .
"\"version\": $version, \"url\": \"$url\", \"size\": $size, \"created\": \"$cre\", \"modified\": \"$mod\"}";
$first = false;
}
echo "\n]}\n";
exit();
}
$file = substr($path, strlen("/$c/"));
$path = ".data/clients/$c/$file";
if (!preg_match_all('/[A-Za-z0-9_.-]+/', $file) && !($file === '*' && $_SERVER['REQUEST_METHOD'] === 'DELETE')) {
header('Status: 400');
header('Content-Length: 16');
exit("400 Bad Request\n");
} else if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$size = filesize($path);
if ($size === false) {
header('Status: 404');
header('Content-Length: 14');
exit("404 Not Found\n");
}
$type = mime_content_type($path);
header("Content-Type: $type");
header("Content-Disposition: attachment; filename=\"$file\"");
header("Content-Length: $size");
readfile($path);
} else if ($_SERVER['REQUEST_METHOD'] === 'PUT') {
$upload = fopen("php://input", "r");
$fp = fopen("/tmp/upload-$file", "wb+");
if (!$upload || !$fp) {
fclose($fp);
fclose($upload);
header('Status: 500');
header('Content-Length: 26');
exit("500 Internal Server Error\n");
}
while ($data = fread($upload, 4096)) fwrite($fp, $data);
fclose($fp);
fclose($upload);
if (!rename("/tmp/upload-$file", $path)) {
header('Status: 500');
header('Content-Length: 26');
exit("500 Internal Server Error\n");
}
header("Status: 201");
header('Content-Length: 12');
exit("201 Created\n");
} else if ($_SERVER['REQUEST_METHOD'] === 'DELETE') {
if ($file === '*') {
foreach (scandir(".data/clients/$c/") as $f) {
if (str_starts_with($f, ".") || str_ends_with($f, ".php") || str_ends_with($f, ".inc")) continue;
if (unlink(".data/clients/$c/$f") === false) {
header("Status: 500");
exit("500 Internal Server Error\n");
}
echo "Deleted $f\n";
}
} else if (!is_file($path)) {
header("Status: 404");
header("Content-Length: 14");
exit("404 Not Found\n");
} else if (unlink($path) === false) {
header("Status: 500");
exit("500 Internal Server Error\n");
}
exit("200 OK\n");
} else {
header("Status: 405");
header("Allow: GET, PUT, DELETE");
header("Content-Length: 23");
exit("405 Method Not Allowed\n");
}
exit();
}
header("Status: 404");
if ($format === 'text') {
header('Content-Type: text/plain; charset=UTF-8');
header('Content-Length: 14');
echo "404 Not Found\n";
} else if ($format === 'json') {
header('Content-Type: application/json; charset=UTF-8');
header('Content-Length: 39');
echo "{\"errors\": [{\"message\": \"Not found\"}]}\n";
} else {
header('Content-Type: text/html; charset=UTF-8');
header('Content-Length: 0');
}
exit();

View File

@ -34,10 +34,17 @@ switch ($_SERVER['PATH_INFO']) {
header("Status: 303");
header("Location: https://access.elwig.at/");
break;
case '/clients':
header("Status: 303");
header("Location: https://sync.elwig.at/");
break;
default:
if (str_starts_with($_SERVER['PATH_INFO'], '/access/')) {
header("Status: 308");
header("Location: https://access.elwig.at/" . substr($_SERVER['PATH_INFO'], 8));
} else if (str_starts_with($_SERVER['PATH_INFO'], '/clients/')) {
header("Status: 308");
header("Location: https://sync.elwig.at/" . substr($_SERVER['PATH_INFO'], 9));
} else {
header("Status: 404");
}

View File

@ -145,6 +145,15 @@ table a {
color: var(--main-color);
}
main section h3 {
text-align: center;
font-size: 2em;
}
.center {
text-align: center;
}
/**** Index ****/
main span[id] {
@ -263,15 +272,6 @@ main section p {
text-align: justify;
}
.center {
text-align: center;
}
main section h3 {
text-align: center;
font-size: 2em;
}
main .about {
padding: 0 0 1em 0;
}

View File

@ -1,4 +1,3 @@
# robots.txt for elwig.at
User-Agent: *
Disallow: /clients/
Sitemap: https://elwig.at/sitemap.xml