false, 'message' => 'Nicht eingeloggt.'], 401);
}
}
function ensure_storage(): void {
if (!is_dir(dirname(PUBLIC_JSON_FILE))) {
@mkdir(dirname(PUBLIC_JSON_FILE), 0775, true);
}
if (!is_dir(IMAGE_DIR)) {
@mkdir(IMAGE_DIR, 0775, true);
}
if (!file_exists(PUBLIC_JSON_FILE)) {
file_put_contents(PUBLIC_JSON_FILE, json_encode([], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
}
}
function read_events(): array {
ensure_storage();
$raw = @file_get_contents(PUBLIC_JSON_FILE);
if ($raw === false || trim($raw) === '') {
return [];
}
$data = json_decode($raw, true);
if (is_array($data)) {
if (isset($data['events']) && is_array($data['events'])) {
return array_values($data['events']);
}
return array_values($data);
}
return [];
}
function write_events(array $events): bool {
ensure_storage();
usort($events, static function(array $a, array $b): int {
$aDate = ($a['startDate'] ?? $a['date'] ?? '') . ' ' . ($a['startTime'] ?? '00:00');
$bDate = ($b['startDate'] ?? $b['date'] ?? '') . ' ' . ($b['startTime'] ?? '00:00');
return strcmp(trim($aDate), trim($bDate));
});
$json = json_encode(array_values($events), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
return file_put_contents(PUBLIC_JSON_FILE, $json) !== false;
}
function sanitize_text($value): string {
return trim((string)$value);
}
function normalize_filename(string $name): string {
$name = preg_replace('/[^a-zA-Z0-9\-_\.]+/u', '-', $name) ?? 'bild';
$name = trim($name, '-.');
return $name !== '' ? $name : 'bild';
}
function make_event_id(): string {
return 'evt_' . date('Ymd_His') . '_' . bin2hex(random_bytes(3));
}
ensure_storage();
if (isset($_GET['logout'])) {
session_destroy();
header('Location: ' . strtok($_SERVER['REQUEST_URI'], '?'));
exit;
}
if (isset($_POST['login_action'])) {
$username = (string)($_POST['username'] ?? '');
$password = (string)($_POST['password'] ?? '');
if ($username === ADMIN_USERNAME && $password === ADMIN_PASSWORD) {
$_SESSION['kalender_admin_logged_in'] = true;
header('Location: ' . strtok($_SERVER['REQUEST_URI'], '?'));
exit;
}
$login_error = 'Benutzername oder Passwort ist nicht korrekt.';
}
if (isset($_GET['api'])) {
$api = (string)$_GET['api'];
if ($api === 'load') {
require_login_json();
send_json(['ok' => true, 'events' => read_events()]);
}
if ($api === 'save') {
require_login_json();
$input = json_decode(file_get_contents('php://input'), true);
if (!is_array($input) || !isset($input['events']) || !is_array($input['events'])) {
send_json(['ok' => false, 'message' => 'Ungültige Daten.'], 400);
}
$events = [];
foreach ($input['events'] as $item) {
if (!is_array($item)) continue;
$event = [
'id' => sanitize_text($item['id'] ?? '') ?: make_event_id(),
'title' => sanitize_text($item['title'] ?? ''),
'startDate' => sanitize_text($item['startDate'] ?? ''),
'endDate' => sanitize_text($item['endDate'] ?? ''),
'date' => sanitize_text($item['date'] ?? ''),
'startTime' => sanitize_text($item['startTime'] ?? ''),
'endTime' => sanitize_text($item['endTime'] ?? ''),
'category' => sanitize_text($item['category'] ?? ''),
'location' => sanitize_text($item['location'] ?? ''),
'venue' => sanitize_text($item['venue'] ?? ''),
'description' => sanitize_text($item['description'] ?? ''),
'image' => sanitize_text($item['image'] ?? ''),
'link' => sanitize_text($item['link'] ?? ''),
'price' => sanitize_text($item['price'] ?? ''),
'isPaid' => !empty($item['isPaid']),
'source' => sanitize_text($item['source'] ?? 'redaktion'),
'createdAt' => sanitize_text($item['createdAt'] ?? date('c')),
'updatedAt' => date('c'),
];
if ($event['startDate'] === '' && $event['date'] !== '') {
$event['startDate'] = $event['date'];
}
if ($event['date'] === '' && $event['startDate'] !== '') {
$event['date'] = $event['startDate'];
}
if ($event['endDate'] === '') {
$event['endDate'] = $event['startDate'];
}
$events[] = $event;
}
if (!write_events($events)) {
send_json(['ok' => false, 'message' => 'Speichern fehlgeschlagen.'], 500);
}
send_json(['ok' => true, 'message' => 'Kalender gespeichert.', 'events' => $events]);
}
if ($api === 'upload') {
require_login_json();
if (empty($_FILES['image']) || !is_array($_FILES['image'])) {
send_json(['ok' => false, 'message' => 'Keine Datei empfangen.'], 400);
}
$file = $_FILES['image'];
if (($file['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) {
send_json(['ok' => false, 'message' => 'Upload-Fehler: ' . (string)$file['error']], 400);
}
$tmpPath = (string)$file['tmp_name'];
$originalName = (string)$file['name'];
$info = @getimagesize($tmpPath);
if ($info === false) {
send_json(['ok' => false, 'message' => 'Die Datei ist kein gültiges Bild.'], 400);
}
$mime = $info['mime'] ?? '';
$ext = match ($mime) {
'image/jpeg' => 'jpg',
'image/png' => 'png',
'image/webp' => 'webp',
'image/gif' => 'gif',
default => '',
};
if ($ext === '') {
send_json(['ok' => false, 'message' => 'Erlaubt sind JPG, PNG, WEBP oder GIF.'], 400);
}
$baseName = pathinfo($originalName, PATHINFO_FILENAME);
$baseName = normalize_filename($baseName);
$targetName = $baseName . '-' . date('Ymd-His') . '.' . $ext;
$targetPath = IMAGE_DIR . $targetName;
if (!move_uploaded_file($tmpPath, $targetPath)) {
send_json(['ok' => false, 'message' => 'Datei konnte nicht gespeichert werden.'], 500);
}
@chmod($targetPath, 0664);
send_json([
'ok' => true,
'message' => 'Bild erfolgreich hochgeladen.',
'filename' => $targetName,
'path' => IMAGE_WEB_BASE . $targetName
]);
}
send_json(['ok' => false, 'message' => 'Unbekannte API-Aktion.'], 404);
}
?>
Kalender Admin – Schaufensterbummel.online
🔐 Geschützter Bereich
Kalender Admin
Bitte mit den Admin-Zugangsdaten anmelden, um Veranstaltungen zu verwalten, Bilder hochzuladen und den Kalender zu speichern.
= htmlspecialchars($login_error, ENT_QUOTES, 'UTF-8') ?>
📅 Schaufensterbummel.online – Kalender Verwaltung
Veranstaltungen pflegen, Bilder hochladen und direkt veröffentlichen
Hier kannst du neue Veranstaltungen anlegen, bestehende Termine bearbeiten, Bilder per Upload oder Drag-and-Drop speichern und vergangene Einträge bei Bedarf in der Übersicht ausblenden.
Auf einen Blick
Veranstaltungen gesamt–
Demnächst–
Vergangen–