diff --git a/.gitignore b/.gitignore index 541957b..31d4891 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .idea credentials.* +devices.inc !*.sample.* diff --git a/www/.php/auth.inc b/www/.php/auth.inc index 63d0503..8975800 100644 --- a/www/.php/auth.inc +++ b/www/.php/auth.inc @@ -1,21 +1,44 @@ 'password', + 'username' => ['scope', 'password'], ]; diff --git a/www/.php/devices.sample.inc b/www/.php/devices.sample.inc new file mode 100644 index 0000000..22d85c2 --- /dev/null +++ b/www/.php/devices.sample.inc @@ -0,0 +1,7 @@ + [ + 'DESKTOP-0123456' => 'Office PC', + ], +]; diff --git a/www/files/create.sql.php b/www/files/create.sql.php index a4e07fb..bb1bd14 100644 --- a/www/files/create.sql.php +++ b/www/files/create.sql.php @@ -4,7 +4,7 @@ require "../.php/credentials.inc"; global $GITEA_TOKEN; if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW']) || $_SERVER['PHP_AUTH_USER'] !== 'elwig' || $_SERVER['PHP_AUTH_PW'] !== 'ganzGeheim123!') { - http_401_unauthorized(); + http_401_unauthorized('text'); } $repo = "winzer/elwig-misc.git"; diff --git a/www/files/index.php b/www/files/index.php index 91ccd0e..f0cfde7 100644 --- a/www/files/index.php +++ b/www/files/index.php @@ -5,7 +5,7 @@ require "../.php/auth.inc"; $ua = $_SERVER['HTTP_USER_AGENT'] ?? null;; if ($_SERVER['REQUEST_METHOD'] === 'PUT') { - authenticate(); + authenticate(['PUT'], 'text'); header('Content-Type: text/plain; charset=UTF-8'); @@ -51,26 +51,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'PUT') { exit("405 Method Not Allowed\n"); } -if ($_SERVER['PATH_INFO'] === '/stat') { - if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW']) || $_SERVER['PHP_AUTH_USER'] !== 'elwig' || $_SERVER['PHP_AUTH_PW'] !== 'ganzGeheim123!') { - header('Status: 401'); - header('WWW-Authenticate: Basic realm="Elwig"'); - header('Content-Length: 0'); - exit; - } - - header("Content-Type: text/html; charset=UTF-8"); - echo "Activity Statistics - Elwig\n"; - echo "\n"; - passthru(<<:g' -EOF); - echo "
TimestampIP AddressMethodURIFormatUser Agent
:g;s:^:
:g;s:$:
\n"; - exit; -} - global $getProd; global $getVers; $getProd = null; @@ -94,7 +74,7 @@ $filesRaw = scandir('.'); usort($filesRaw, 'version_compare'); $files = []; foreach ($filesRaw as $file) { - if (str_starts_with($file, ".") || str_ends_with($file, ".php")) continue; + if (str_starts_with($file, ".") || str_ends_with($file, ".php") || !str_contains($file, ".")) continue; $files[$file] = [filesize($file), filemtime($file), filectime($file)]; } @@ -157,7 +137,7 @@ if ($format === 'json') { foreach ($entities as $name => [$prod, $vers, $url, $size, $mtime, $ctime, $mod, $cre]) { echo "$name\t" . number_format($size / 1024 / 1024, 1) . " MB\n"; } -} else if ($format === 'html') { +} else { if (isset($getProd) && isset($getVers) && sizeof($entities) === 1) { header('Status: 303'); header('Location: ' . $entities[array_key_first($entities)][2]); diff --git a/www/files/stat.php b/www/files/stat.php new file mode 100644 index 0000000..a7d8bbd --- /dev/null +++ b/www/files/stat.php @@ -0,0 +1,216 @@ + 'Windows 10 (1507)', + 'Microsoft Windows NT 10.0.10586.0' => 'Windows 10 (1511)', + 'Microsoft Windows NT 10.0.14393.0' => 'Windows 10 (1607)', + 'Microsoft Windows NT 10.0.15063.0' => 'Windows 10 (1703)', + 'Microsoft Windows NT 10.0.16299.0' => 'Windows 10 (1709)', + 'Microsoft Windows NT 10.0.17134.0' => 'Windows 10 (1803)', + 'Microsoft Windows NT 10.0.17763.0' => 'Windows 10 (1809)', + 'Microsoft Windows NT 10.0.18362.0' => 'Windows 10 (1903)', + 'Microsoft Windows NT 10.0.18363.0' => 'Windows 10 (1909)', + 'Microsoft Windows NT 10.0.19041.0' => 'Windows 10 (2004)', + 'Microsoft Windows NT 10.0.19042.0' => 'Windows 10 (20H2)', + 'Microsoft Windows NT 10.0.19043.0' => 'Windows 10 (21H1)', + 'Microsoft Windows NT 10.0.19044.0' => 'Windows 10 (21H2)', + 'Microsoft Windows NT 10.0.19045.0' => 'Windows 10 (22H2)', + 'Microsoft Windows NT 10.0.22000.0' => 'Windows 11 (21H2)', + 'Microsoft Windows NT 10.0.22621.0' => 'Windows 11 (22H2)', + 'Microsoft Windows NT 10.0.22631.0' => 'Windows 11 (23H2)', + 'Microsoft Windows NT 10.0.26100.0' => 'Windows 11 (24H2)', + 'Microsoft Windows NT 10.0.26200.0' => 'Windows 11 (25H2)', +]; + +$DEVICES ??= []; + +if ($_SERVER['PATH_INFO'] === '/log') { + header("Content-Type: text/html; charset=UTF-8"); + echo "Table - Activity Statistics - Elwig\n"; + echo "\n"; + if ($_SERVER['QUERY_STRING'] === 'full') { + passthru(<<:g' +EOF); + } else { + passthru(<<:g' +EOF); + } + echo "
TimestampIP AddressMethodURIFormatUser Agent
:g;s:^:
:g;s:$:
:g;s:^:
:g;s:$:
\n"; + exit; +} else if ($_SERVER['PATH_INFO'] === '') { + $format = get_fmt(); + $stat = []; + if (($file = fopen('.log.csv', 'r'))) { + while (($line = fgets($file)) !== false) { + $line = explode('|', $line); + if (sizeof($line) < 6) continue; + if (!str_starts_with($line[5], 'Elwig/')) continue; + if (str_contains($line[5], "PICARD") || str_contains($line[5], "ENTERPRISE") || str_contains($line[5], "GEORGIOU")) continue; + $timestamp = intval($line[0]); + $version = substr(explode(' ', $line[5], 2)[0], 6); + $comment = preg_match("/\((.*?), *(.*?), *(.*?), *(.*?)\)/", $line[5], $m); + $token = $m[1]; + $branch = $m[2]; + $device = $m[3]; + $win = $m[4]; + if (!isset($stat[$token])) $stat[$token] = []; + if (!isset($stat[$token][$device])) $stat[$token][$device] = []; + $addr = $line[1]; + if (str_contains($addr, ':')) { + $list = explode(':', $addr); + $addr = implode(':', array_splice($list, 0, 4)) . '::'; + } + $stat[$token][$device][$timestamp] = [$version, $branch, $win, $addr]; + } + fclose($file); + } + + if ($format === 'json') { + header('Content-Type: application/json; charset=UTF-8'); + echo "{\"clients\":[\n"; + $first1 = true; + foreach ($stat as $token => $devices) { + if (!$first1) echo ",\n"; + echo " {\"token\": \"$token\", \"devices\": [\n"; + $first2 = true; + foreach ($devices as $device => $data) { + if (!$first2) echo ",\n"; + echo " {"; + $timestamp = array_key_last($data); + $ref = $timestamp; + foreach (array_reverse(array_keys($data)) as $t) { + if ($t + 90 * 60 > $ref) { + $ref = $t; + } else { + break; + } + } + $addr = array_reverse(array_unique(array_map(function ($d) { + return "\"$d[3]\""; + }, array_values($data)))); + $d = $data[$timestamp]; + $name = $DEVICES[$token][$device] ?? $device; + $active = $timestamp + 90 * 60 > time(); + $activeStr = $active ? 'true' : 'false'; + $from = date('c', $ref); + $to = date('c', $timestamp); + $hours = intval((($active ? time() : $timestamp) - $ref) / 60 / 60 + 0.4); + $win = isset($osVersions[$d[2]]) ? '"' . $osVersions[$d[2]] . '"' : "null"; + echo "\"branch\": \"$d[1]\", \"description\": \"$name\", \"name\": \"$device\", \"isActive\": $activeStr, " . + "\"lastActivity\": {\"start\": \"$from\", \"end\": \"$to\", \"hours\": $hours}, " . + "\"elwigVersion\": \"$d[0]\", \"osVersion\": $win, \"osVersionFull\": \"$d[2]\", " . + "\"addresses\": [" . implode(",", $addr) . "]"; + echo "}"; + $first2 = false; + } + echo "\n ]}"; + $first1 = false; + } + echo "\n]}\n"; + } else if ($format === 'text') { + header('Content-Type: text/plain; charset=UTF-8'); + echo "Client Branch Device Device Name Last Activity Elwig Version OS Version IP Addresses\n"; + foreach ($stat as $token => $devices) { + foreach ($devices as $device => $data) { + echo "$token "; + $timestamp = array_key_last($data); + $ref = $timestamp; + foreach (array_reverse(array_keys($data)) as $t) { + if ($t + 90 * 60 > $ref) { + $ref = $t; + } else { + break; + } + } + $addr = array_reverse(array_unique(array_map(function ($d) { + return $d[3]; + }, array_values($data)))); + $d = $data[$timestamp]; + $name = $DEVICES[$token][$device] ?? $device; + echo mb_str_pad($d[1], 16) . " " . mb_str_pad($name, 20) . " " . mb_str_pad($device, 20) . " "; + if ($timestamp + 90 * 60 > time()) { + echo mb_str_pad(date('d.m.Y, H:i', $timestamp) . " (since " . intval((time() - $ref) / 60 / 60 + 0.4) . "h)", 28); + } else { + echo mb_str_pad(date('d.m.Y, H:i', $timestamp) . " (for " . intval(($timestamp - $ref) / 60 / 60 + 0.4) . "h)", 28); + } + echo " " . mb_str_pad($d[0], 13) . " "; + if (isset($osVersions[$d[2]])) { + echo mb_str_pad($osVersions[$d[2]], 33) . " "; + } else { + echo mb_str_pad($d[2], 33) . " "; + } + echo implode(", ", array_slice($addr, 0, 5)); + echo "\n"; + } + } + } else { + header('Content-Type: text/html; charset=UTF-8'); + echo "\n\n"; + echo "Activity Statistics - Elwig\n"; + echo "\n"; + echo "

Activity Statistics

\n"; + echo "\n"; + echo "\n"; + foreach ($stat as $token => $devices) { + $first = true; + foreach ($devices as $device => $data) { + echo ""; + if ($first) { + $n = sizeof($devices); + echo ""; + $first = false; + } + $timestamp = array_key_last($data); + $ref = $timestamp; + foreach (array_reverse(array_keys($data)) as $t) { + if ($t + 90 * 60 > $ref) { + $ref = $t; + } else { + break; + } + } + $addr = array_reverse(array_unique(array_map(function ($d) { + return $d[3]; + }, array_values($data)))); + $d = $data[$timestamp]; + $name = $DEVICES[$token][$device] ?? $device; + echo ""; + if ($timestamp + 90 * 60 > time()) { + echo ""; + echo ""; + echo ""; + } else { + echo ""; + echo ""; + echo ""; + } + echo ""; + if (isset($osVersions[$d[2]])) { + echo ""; + } else { + echo ""; + } + echo ""; + echo "\n"; + } + } + echo "
ClientBranchDeviceDevice NameLast ActivityElwig VersionOS VersionIP Addresses
$token$d[1]$name$device" . date('d.m.Y, H:i', $timestamp) . " (since " . intval((time() - $ref) / 60 / 60 + 0.4) . "h)$name$device" . date('d.m.Y, H:i', $timestamp) . " (for " . intval(($timestamp - $ref) / 60 / 60 + 0.4) . "h)$d[0]" . $osVersions[$d[2]] . "$d[2]" . implode("
", array_slice($addr, 0, 5)) . "
\n"; + echo "

Log Full Log

\n"; + echo "\n\n"; + } +} else { + header('Status: 404'); + header('Content-Length: 0'); + exit(); +}