parent
3d73eca6f7
commit
82458df080
@ -0,0 +1,159 @@ |
||||
<?php |
||||
session_start(); |
||||
|
||||
define('PASSWORD', 'cttue_avj2305_44'); |
||||
define('FILES_DIR', __DIR__ . '/avj2305'); |
||||
define('ACTIVE_FILE', __DIR__ . '/active.txt'); |
||||
|
||||
// -- helpers ------------------------------------------------------------------ |
||||
|
||||
function is_authed(): bool { |
||||
return !empty($_SESSION['auth']); |
||||
} |
||||
|
||||
function require_auth(): void { |
||||
if (!is_authed()) { |
||||
header('Location: ?login'); |
||||
exit; |
||||
} |
||||
} |
||||
|
||||
function get_active(): string { |
||||
if (file_exists(ACTIVE_FILE)) { |
||||
$v = trim(file_get_contents(ACTIVE_FILE)); |
||||
if ($v !== '') return $v; |
||||
} |
||||
return ''; |
||||
} |
||||
|
||||
function set_active(string $filename): void { |
||||
file_put_contents(ACTIVE_FILE, $filename); |
||||
} |
||||
|
||||
function get_bin_files(): array { |
||||
$files = glob(FILES_DIR . '/*.bin'); |
||||
if (!$files) return []; |
||||
return array_map('basename', $files); |
||||
} |
||||
|
||||
function safe_filename(string $name): bool { |
||||
// basename only, no path traversal, must end in .bin |
||||
return $name === basename($name) |
||||
&& str_ends_with($name, '.bin') |
||||
&& !str_contains($name, "\0"); |
||||
} |
||||
|
||||
// -- routing ------------------------------------------------------------------ |
||||
|
||||
$q = array_key_first($_GET) ?? ''; // first query param key |
||||
|
||||
// POST: login |
||||
if ($q === 'login' && $_SERVER['REQUEST_METHOD'] === 'POST') { |
||||
if (hash_equals(PASSWORD, $_POST['password'] ?? '')) { |
||||
$_SESSION['auth'] = true; |
||||
header('Location: ?edit'); |
||||
} else { |
||||
header('Location: ?login&err=1'); |
||||
} |
||||
exit; |
||||
} |
||||
|
||||
// POST: set active file |
||||
if ($q === 'edit' && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['file'])) { |
||||
require_auth(); |
||||
$f = $_POST['file']; |
||||
if (safe_filename($f) && file_exists(FILES_DIR . '/' . $f)) { |
||||
set_active($f); |
||||
} |
||||
header('Location: ?edit'); |
||||
exit; |
||||
} |
||||
|
||||
// GET: login page |
||||
if ($q === 'login') { ?> |
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head><meta charset="utf-8"><title>Login</title> |
||||
<style> |
||||
body{font:14px monospace;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;background:#111;color:#eee} |
||||
form{display:flex;flex-direction:column;gap:8px;width:220px} |
||||
input[type=password]{padding:6px;background:#222;border:1px solid #555;color:#eee} |
||||
button{padding:6px;background:#444;border:none;color:#eee;cursor:pointer} |
||||
button:hover{background:#555} |
||||
.err{color:#f66;font-size:12px} |
||||
</style> |
||||
</head> |
||||
<body> |
||||
<form method="post" action="?login"> |
||||
<label>Password</label> |
||||
<input type="password" name="password" autofocus> |
||||
<button type="submit">Login</button> |
||||
<?php if (!empty($_GET['err'])): ?><span class="err">Wrong password.</span><?php endif; ?> |
||||
</form> |
||||
</body></html> |
||||
<?php exit; } |
||||
|
||||
// GET: edit page |
||||
if ($q === 'edit') { |
||||
require_auth(); |
||||
$files = get_bin_files(); |
||||
$active = get_active(); |
||||
?> |
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head><meta charset="utf-8"><title>Select File</title> |
||||
<style> |
||||
body{font:14px monospace;background:#111;color:#eee;padding:24px;margin:0} |
||||
h2{margin:0 0 16px} |
||||
ul{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:6px} |
||||
li form{margin:0} |
||||
button{padding:6px 12px;background:#333;border:1px solid #555;color:#eee;cursor:pointer;width:100%;text-align:left} |
||||
button:hover{background:#444} |
||||
button.active{border-color:#6af;color:#6af} |
||||
.none{color:#888} |
||||
</style> |
||||
</head> |
||||
<body> |
||||
<h2>Live file selector</h2> |
||||
<p>Active: <strong><?= $active !== '' ? htmlspecialchars($active) : '<span class="none">none</span>' ?></strong></p>
|
||||
<?php if ($files): ?> |
||||
<ul> |
||||
<?php foreach ($files as $f): ?> |
||||
<li> |
||||
<form method="post" action="?edit"> |
||||
<input type="hidden" name="file" value="<?= htmlspecialchars($f) ?>">
|
||||
<button type="submit" <?= $f === $active ? 'class="active"' : '' ?>><?= htmlspecialchars($f) ?></button>
|
||||
</form> |
||||
</li> |
||||
<?php endforeach; ?> |
||||
</ul> |
||||
<?php else: ?> |
||||
<p class="none">No .bin files found in avj2305/</p> |
||||
<?php endif; ?> |
||||
</body></html> |
||||
<?php exit; } |
||||
|
||||
// DEFAULT: serve active .bin file |
||||
$active = get_active(); |
||||
|
||||
if ($active === '') { |
||||
http_response_code(404); |
||||
exit('No active file set.'); |
||||
} |
||||
|
||||
if (!safe_filename($active)) { |
||||
http_response_code(500); |
||||
exit('Invalid filename.'); |
||||
} |
||||
|
||||
$path = FILES_DIR . '/' . $active; |
||||
|
||||
if (!file_exists($path)) { |
||||
http_response_code(404); |
||||
exit('File not found.'); |
||||
} |
||||
|
||||
header('Content-Type: application/octet-stream'); |
||||
header('Content-Disposition: inline; filename="' . addslashes($active) . '"'); |
||||
header('Content-Length: ' . filesize($path)); |
||||
readfile($path); |
||||
Loading…
Reference in new issue