<?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);
    }

    $name1 = fread($fp, 7);
    $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);
    }

    $name2 = fread($fp, 9);
    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');
            echo "405 Method Not Allowed :(\n";
        } else if ($format === 'json') {
            header('Content-Type: application/json; charset=UTF-8');
            echo "{\"status\": \"error\", \"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 "{\"status\": \"success\", \"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-AT">
<head>
  <meta charset="UTF-8"/>
  <title>Mandanten - Elwig - Elektronische Winzergenossenschaftsverwaltung</title>
  <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"/>
</head>
<body>
  <h1>Mandanten</h1>
  <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><a href="clients?format=json">JSON-Format</a></p>
</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("Location: $c/");
        header('Status: 303');
        exit("303 See Other :)\n");
    } elseif ($path === "/$c/") {
        if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
            header("Status: 405");
            header("Allow: GET");
            exit("405 Method Not Allowed :(\n");
        }

        header('Content-Type: application/json; charset=UTF-8');
        echo "{\"status\": \"success\", \"data\": [\n";
        $first = true;
        foreach (scandir(".data/clients/$c/") as $file) {
            if (str_starts_with($file, ".") || str_ends_with($file, ".php")) continue;
            if (!$first) echo ",\n";
            $path = ".data/clients/$c/$file";
            $size = filesize($path);
            $url = "https://www.necronda.net/elwig/clients/$c/$file";
            $mod = date(DATE_ATOM, filemtime($path));
            $cre = date(DATE_ATOM, filectime($path));
            $datetime = "null";
            $zwstid = "null";
            if (str_ends_with($file, ".zip") && substr_count($file, "_") === 2) {
                $parts = explode("_", substr($file, 0, -4));
                $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 (str_contains($file, '/')) {
        header("Status: 400");
        exit("400 Bad Request :(\n");
    } elseif ($_SERVER['REQUEST_METHOD'] === 'GET') {
        $size = filesize($path);
        if ($size === false) {
            header("Status: 404");
            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);
    } elseif ($_SERVER['REQUEST_METHOD'] === 'PUT') {
        $putdata = fopen('php://input', 'r');
        $fp = fopen($path, 'wb');
        if ($fp === false) {
            header("Status: 500");
            exit("500 Internal Server Error :(\n");
        }
        while ($data = fread($putdata, 4096))
            fwrite($fp, $data);
        fclose($fp);
        fclose($putdata);
        header("Status: 201");
        exit("201 Created :)\n");
    } elseif ($_SERVER['REQUEST_METHOD'] === 'DELETE') {
        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");
        exit("405 Method Not Allowed :(\n");
    }

    exit();
}

header("Status: 404");
if ($format === 'text') {
    header('Content-Type: text/plain; charset=UTF-8');
    echo "404 Not Found :(\n";
} else if ($format === 'json') {
    header('Content-Type: application/json; charset=UTF-8');
    echo "{\"status\": \"error\", \"errors\": [{\"message\": \"Not found\"}]}\n";
} else {
    header('Content-Type: text/html; charset=UTF-8');
    header('Content-Length: 0');
}
exit();