diff --git a/index.php b/index.php
new file mode 100644
index 0000000..6f2cad1
--- /dev/null
+++ b/index.php
@@ -0,0 +1,3844 @@
+ $latestTime) {
+ $latestTime = $mtime;
+ $latestVideo = $video;
+ }
+ }
+
+ if ($latestVideo) {
+ header('Content-Description: File Transfer');
+ header('Content-Type: application/octet-stream');
+ header('Content-Disposition: attachment; filename="'.basename($latestVideo).'"');
+ header('Expires: 0');
+ header('Cache-Control: must-revalidate');
+ header('Pragma: public');
+ header('Content-Length: ' . filesize($latestVideo));
+ readfile($latestVideo);
+ exit;
+ } else {
+ echo "Kein Video zum Herunterladen gefunden.";
+ exit;
+ }
+}
+
+
+
+
+// Funktion zur sicheren Umleitung
+function safeRedirect($url) {
+ if (!headers_sent()) {
+ header("HTTP/1.1 301 Moved Permanently");
+ header("Location: " . $url);
+ } else {
+ echo '';
+ }
+ exit();
+}
+
+// Hauptlogik
+$oldDomains = [
+ 'www.aurora-wetter-lifecam.ch',
+ 'www.aurora-wetter-livecam.ch'
+];
+$newDomain = 'www.aurora-weather-livecam.com';
+
+if (in_array($_SERVER['HTTP_HOST'], $oldDomains)) {
+ $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
+ $newUrl = $protocol . '://' . $newDomain . $_SERVER['REQUEST_URI'];
+
+ // Logging für Debugging
+ error_log("Umleitung von {$_SERVER['HTTP_HOST']} nach $newUrl");
+
+ if (!headers_sent()) {
+ header("HTTP/1.1 301 Moved Permanently");
+ header("Location: " . $newUrl);
+ } else {
+ echo '';
+ }
+ exit();
+}
+
+
+
+
+
+session_start();
+error_reporting(E_ALL);
+ini_set('display_errors', 1);
+$imageDir = "./image"; // Angepasst an das Ausgabeverzeichnis des Bash-Skripts
+$imageFiles = glob("$imageDir/screenshot_*.jpg");
+rsort($imageFiles); // Sortiert die Dateien in umgekehrter Reihenfolge (neueste zuerst)
+$imageFilesJson = json_encode($imageFiles);
+
+class WebcamManager {
+
+ private $videoSrc = 'test_video.m3u8';
+ private $logoPath = 'logo.png';
+
+ public function displayWebcam() {
+ return '
+ ';
+}
+
+
+
+ public function captureSnapshot() {
+
+ $outputFile = 'snapshot_' . date('YmdHis') . '.jpg';
+ $command = "ffmpeg -i {$this->videoSrc} -i {$this->logoPath} -filter_complex 'overlay=main_w-overlay_w-10:10' -vframes 1 -q:v 2 {$outputFile}";
+
+
+ exec($command, $output, $returnVar);
+
+ if ($returnVar !== 0) {
+ return "Fehler beim Erstellen des Snapshots.";
+ }
+
+ // Kopieren des Snapshots in den Uploads-Ordner
+ $uploadDir = "uploads/";
+ if (!file_exists($uploadDir)) {
+ mkdir($uploadDir, 0777, true);
+
+ }
+
+ $uploadFile = $uploadDir . $outputFile;
+ if (copy($outputFile, $uploadFile)) {
+
+ } else {
+
+ }
+
+
+
+ header('Content-Type: application/octet-stream');
+ header('Content-Disposition: attachment; filename="' . $outputFile . '"');
+ readfile($outputFile);
+ unlink($outputFile);
+ exit;
+ }
+// public function getImageFiles() {
+// // Nur JPG-Dateien aus uploads/, KEINE MP4-Dateien
+// $imageFiles = glob("uploads/*.{jpg,jpeg,png,gif}", GLOB_BRACE);
+
+// // Filtere unerwünschte Dateien aus
+// $imageFiles = array_filter($imageFiles, function($file) {
+// $basename = basename($file);
+// // Blockiere sequence_*.mp4 und andere unerwünschte Dateien
+// return pathinfo($file, PATHINFO_EXTENSION) !== 'mp4' &&
+// strpos($basename, 'sequence_') !== 0;
+// });
+
+// return json_encode(array_values($imageFiles));
+// }
+public function getImageFiles() {
+ // Screenshots aus dem image/ Ordner holen
+ $imageFiles = glob("image/screenshot_*.jpg");
+ sort($imageFiles); // Neueste zuerst
+ return json_encode($imageFiles);
+}
+
+
+
+
+
+ public function captureVideoSequence($duration = 10) {
+ $outputFile = 'sequence_' . date('YmdHis') . '.mp4';
+ $command = "ffmpeg -i {$this->videoSrc} -i {$this->logoPath} -filter_complex 'overlay=10:10' -t {$duration} -c:v libx264 -preset fast -crf 23 {$outputFile}";
+
+ exec($command, $output, $returnVar);
+
+ if ($returnVar !== 0) {
+ return "Fehler beim Erstellen der Video-Sequenz.";
+ }
+
+ // Kopieren des Videoclips in den Uploads-Ordner
+ $uploadDir = "uploads/";
+ if (!file_exists($uploadDir)) {
+ mkdir($uploadDir, 0777, true);
+ echo "Uploads-Ordner erstellt. ";
+ }
+
+ $uploadFile = $uploadDir . $outputFile;
+ if (copy($outputFile, $uploadFile)) {
+
+ } else {
+ echo "Fehler beim Kopieren des Videoclips in den Uploads-Ordner. ";
+ }
+
+
+
+ header('Content-Type: video/mp4');
+ header('Content-Disposition: attachment; filename="' . $outputFile . '"');
+ readfile($outputFile);
+ unlink($outputFile);
+ exit;
+ }
+public function getJavaScript() {
+ return "
+ document.addEventListener('DOMContentLoaded', function () {
+ var video = document.getElementById('webcam-player');
+ var videoSrc = '{$this->videoSrc}';
+
+ // Mobile Detection
+ var isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
+ var isIOS = /iPhone|iPad|iPod/i.test(navigator.userAgent);
+
+ // Controls NUR auf Desktop verstecken
+ video.controls = false;
+
+ if (isIOS) {
+ // iOS native HLS
+ video.src = videoSrc;
+ video.setAttribute('playsinline', '');
+ video.setAttribute('webkit-playsinline', '');
+ video.muted = true;
+
+ video.addEventListener('loadedmetadata', function() {
+ video.play().catch(function(e) {
+ console.log('iOS Autoplay blockiert');
+ });
+ });
+
+ } else if (Hls.isSupported()) {
+ var hls = new Hls({
+ // Mobile-optimierte Einstellungen
+ liveSyncDurationCount: isMobile ? 2 : 3,
+ liveMaxLatencyDurationCount: isMobile ? 5 : 10,
+ liveDurationInfinity: true,
+ enableWorker: !isMobile,
+ lowLatencyMode: false,
+ backBufferLength: isMobile ? 30 : 90,
+ maxBufferLength: isMobile ? 30 : 60,
+ maxMaxBufferLength: isMobile ? 60 : 120,
+ maxBufferSize: isMobile ? 60*1000*1000 : 120*1000*1000,
+
+ // Mobile-spezifische Timeouts
+ manifestLoadingTimeOut: isMobile ? 20000 : 10000,
+ manifestLoadingMaxRetry: 8,
+ levelLoadingTimeOut: isMobile ? 20000 : 10000,
+ levelLoadingMaxRetry: 8,
+ fragLoadingTimeOut: isMobile ? 20000 : 10000,
+ fragLoadingMaxRetry: 8,
+
+ // Qualität für Mobile
+ startLevel: isMobile ? 0 : -1,
+ abrEwmaDefaultEstimate: isMobile ? 500000 : 1000000
+ });
+
+ hls.loadSource(videoSrc);
+ hls.attachMedia(video);
+
+ hls.on(Hls.Events.MANIFEST_PARSED, function () {
+ console.log('Stream geladen');
+
+ if (isMobile) {
+ video.muted = true;
+ }
+
+ // Live-Position anpassen
+ if (hls.liveSyncPosition !== null) {
+ var targetPosition = hls.liveSyncPosition - 60;
+ console.log('Setze Position auf: ' + targetPosition);
+ video.currentTime = targetPosition;
+ }
+
+ video.play().catch(function(e) {
+ console.log('Autoplay blockiert');
+ });
+ });
+
+ // Fehlerbehandlung
+ hls.on(Hls.Events.ERROR, function(event, data) {
+ if (data.fatal) {
+ switch(data.type) {
+ case Hls.ErrorTypes.NETWORK_ERROR:
+ console.log('Netzwerkfehler - versuche erneut...');
+ setTimeout(function() {
+ hls.startLoad();
+ }, 3000);
+ break;
+ case Hls.ErrorTypes.MEDIA_ERROR:
+ console.log('Media-Fehler - Recovery...');
+ hls.recoverMediaError();
+ break;
+ default:
+ console.log('Kritischer Fehler - Neustart...');
+ hls.destroy();
+ location.reload();
+ break;
+ }
+ }
+ });
+
+ } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
+ // Fallback für andere Browser
+ video.src = videoSrc;
+ video.muted = true;
+ video.addEventListener('loadedmetadata', function () {
+ video.currentTime = Math.max(0, video.duration - 60);
+ video.play();
+ });
+ }
+ });
+ ";
+}
+
+
+
+
+
+
+
+ public function setVideoSrc($src) {
+ $this->videoSrc = $src;
+ }
+}
+
+
+
+
+
+
+
+
+
+
+class VisualCalendarManager {
+ private $videoDir;
+ private $monthNames;
+
+ public function __construct($videoDir = './videos/') {
+ $this->videoDir = $videoDir;
+ $this->monthNames = [
+ 1 => ['de' => 'Januar', 'en' => 'January', 'it' => 'Gennaio', 'fr' => 'Janvier', 'zh' => '一月'],
+ 2 => ['de' => 'Februar', 'en' => 'February', 'it' => 'Febbraio', 'fr' => 'Février', 'zh' => '二月'],
+ 3 => ['de' => 'März', 'en' => 'March', 'it' => 'Marzo', 'fr' => 'Mars', 'zh' => '三月'],
+ 4 => ['de' => 'April', 'en' => 'April', 'it' => 'Aprile', 'fr' => 'Avril', 'zh' => '四月'],
+ 5 => ['de' => 'Mai', 'en' => 'May', 'it' => 'Maggio', 'fr' => 'Mai', 'zh' => '五月'],
+ 6 => ['de' => 'Juni', 'en' => 'June', 'it' => 'Giugno', 'fr' => 'Juin', 'zh' => '六月'],
+ 7 => ['de' => 'Juli', 'en' => 'July', 'it' => 'Luglio', 'fr' => 'Juillet', 'zh' => '七月'],
+ 8 => ['de' => 'August', 'en' => 'August', 'it' => 'Agosto', 'fr' => 'Août', 'zh' => '八月'],
+ 9 => ['de' => 'September', 'en' => 'September', 'it' => 'Settembre', 'fr' => 'Septembre', 'zh' => '九月'],
+ 10 => ['de' => 'Oktober', 'en' => 'October', 'it' => 'Ottobre', 'fr' => 'Octobre', 'zh' => '十月'],
+ 11 => ['de' => 'November', 'en' => 'November', 'it' => 'Novembre', 'fr' => 'Novembre', 'zh' => '十一月'],
+ 12 => ['de' => 'Dezember', 'en' => 'December', 'it' => 'Dicembre', 'fr' => 'Décembre', 'zh' => '十二月']
+ ];
+ }
+
+ public function getVideosForDate($year, $month, $day) {
+ $videos = [];
+ $dateStr = sprintf('%04d%02d%02d', $year, $month, $day);
+
+ foreach (glob($this->videoDir . "daily_video_{$dateStr}_*.mp4") as $video) {
+ $videos[] = [
+ 'path' => $video,
+ 'filename' => basename($video),
+ 'filesize' => filesize($video),
+ 'time' => date('H:i', filemtime($video))
+ ];
+ }
+
+ return $videos;
+ }
+
+ public function hasVideosForDate($year, $month, $day) {
+ $dateStr = sprintf('%04d%02d%02d', $year, $month, $day);
+ $pattern = $this->videoDir . "daily_video_{$dateStr}_*.mp4";
+ return count(glob($pattern)) > 0;
+ }
+
+ public function displayVisualCalendar() {
+ $currentYear = isset($_GET['cal_year']) ? intval($_GET['cal_year']) : date('Y');
+ $currentMonth = isset($_GET['cal_month']) ? intval($_GET['cal_month']) : date('n');
+ $selectedDay = isset($_GET['cal_day']) ? intval($_GET['cal_day']) : null;
+
+ $output = '
';
+
+ // Navigation
+ $output .= '
';
+ $output .= '◀ ';
+ $output .= '
' . $this->monthNames[$currentMonth]['de'] . ' ' . $currentYear . ' ';
+ $output .= '▶ ';
+ $output .= '';
+
+ // Kalender-Grid
+ $output .= '
';
+
+ // Wochentage Header
+ $weekdays = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'];
+ foreach ($weekdays as $day) {
+ $output .= '
' . $day . '
';
+ }
+
+ // Tage des Monats
+ $firstDay = mktime(0, 0, 0, $currentMonth, 1, $currentYear);
+ $daysInMonth = date('t', $firstDay);
+ $dayOfWeek = date('N', $firstDay) - 1; // 0 = Montag
+
+ // Leere Zellen vor dem ersten Tag
+ for ($i = 0; $i < $dayOfWeek; $i++) {
+ $output .= '
';
+ }
+
+ // Tage mit Videos markieren
+ for ($day = 1; $day <= $daysInMonth; $day++) {
+ $hasVideos = $this->hasVideosForDate($currentYear, $currentMonth, $day);
+ $isSelected = ($selectedDay == $day);
+ $isToday = ($currentYear == date('Y') && $currentMonth == date('n') && $day == date('j'));
+
+ $classes = 'calendar-day';
+ if ($hasVideos) $classes .= ' has-video';
+ if ($isSelected) $classes .= ' selected';
+ if ($isToday) $classes .= ' today';
+
+ $output .= '
';
+ $output .= '' . $day . ' ';
+ if ($hasVideos) {
+ $output .= '📹 ';
+ }
+ $output .= '
';
+ }
+
+ $output .= '
'; // calendar-grid
+
+ // Video-Liste für ausgewählten Tag
+ if ($selectedDay) {
+ $videos = $this->getVideosForDate($currentYear, $currentMonth, $selectedDay);
+ if (!empty($videos)) {
+ $output .= '
';
+ $output .= '
Videos vom ' . sprintf('%02d.%02d.%04d', $selectedDay, $currentMonth, $currentYear) . ' ';
+ $output .= '
';
+
+ foreach ($videos as $video) {
+ $sizeInMb = round($video['filesize'] / (1024 * 1024), 2);
+ $token = hash_hmac('sha256', $video['path'], session_id());
+
+ $output .= '';
+ $output .= '🕐 ' . $video['time'] . ' Uhr ';
+ $output .= '' . $sizeInMb . ' MB ';
+ $output .= '';
+ $output .= '⬇️ Download';
+ $output .= ' ';
+ $output .= ' ';
+ }
+
+ $output .= ' ';
+ $output .= '
';
+ } else {
+ $output .= '
Keine Videos für diesen Tag verfügbar.
';
+ }
+ }
+
+ $output .= '
'; // visual-calendar-container
+
+ return $output;
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+class GuestbookManager {
+ private $entries = [];
+ private $dbFile = 'guestbook.json';
+
+ public function __construct() {
+ if (file_exists($this->dbFile)) {
+ $this->entries = json_decode(file_get_contents($this->dbFile), true);
+ }
+ }
+
+ public function handleFormSubmission() {
+ if (isset($_POST['guestbook'], $_POST['guest-name'], $_POST['guest-message'])) {
+ $this->addEntry($_POST['guest-name'], $_POST['guest-message']);
+ $this->saveEntries();
+ }
+ }
+
+ private function addEntry($name, $message) {
+ $this->entries[] = [
+ 'name' => $name,
+ 'message' => $message,
+ 'date' => date('Y-m-d H:i:s')
+ ];
+ }
+
+ public function deleteEntry($index) {
+ if (isset($this->entries[$index])) {
+ unset($this->entries[$index]);
+ $this->entries = array_values($this->entries); // Re-indizieren des Arrays
+ $this->saveEntries();
+ return true;
+ }
+ return false;
+ }
+
+
+
+ private function saveEntries() {
+ file_put_contents($this->dbFile, json_encode($this->entries));
+ }
+
+ public function displayForm() {
+ return '
+ ';
+ }
+public function displayEntries($isAdmin = false) {
+ $output = '';
+ foreach ($this->entries as $index => $entry) {
+ $output .= "
+
+
{$entry['name']}
+
{$entry['message']}
+
{$entry['date']}";
+ if ($isAdmin) {
+ $output .= "
+
+
+ Löschen
+ ";
+ }
+
+ }
+ $output .= '
';
+ return $output;
+}
+
+
+}
+
+
+class ContactManager {
+ //private $adminEmail = 'ingo.kohler.zh@gmail.com'; // ← Empfänger
+ private $adminEmail = 'metacube@gmail.com'; // ← Empfänger
+ private $feedbackFile = 'feedbacks.json';
+ private $gmailUser = 'metacube@gmail.com'; // ← DEINE GMAIL-ADRESSE
+ private $gmailAppPassword = 'qggk hsxz fdkq jgxa'; // ← APP-PASSWORT VON GMAIL
+
+ public function displayForm() {
+ return '
+
+
+
+ Name:
+
+
+
+
+ E-Mail:
+
+
+
+
+ Nachricht:
+
+
+
+
+ Nachricht senden
+
+
+
';
+ }
+
+ public function handleSubmission($name, $email, $message) {
+ // Validierung
+ if (empty($name) || empty($email) || empty($message)) {
+ return [
+ 'success' => false,
+ 'message' => 'Alle Felder sind erforderlich'
+ ];
+ }
+
+ if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
+ return [
+ 'success' => false,
+ 'message' => 'Ungültige E-Mail-Adresse'
+ ];
+ }
+
+ if (strlen($message) < 10) {
+ return [
+ 'success' => false,
+ 'message' => 'Nachricht zu kurz (mindestens 10 Zeichen)'
+ ];
+ }
+
+ // Sanitize
+ $name = htmlspecialchars(trim($name), ENT_QUOTES, 'UTF-8');
+ $email = filter_var(trim($email), FILTER_SANITIZE_EMAIL);
+ $message = htmlspecialchars(trim($message), ENT_QUOTES, 'UTF-8');
+
+ // Feedback speichern
+ $feedback = [
+ 'name' => $name,
+ 'email' => $email,
+ 'message' => $message,
+ 'date' => date('Y-m-d H:i:s'),
+ 'ip' => $_SERVER['REMOTE_ADDR'] ?? 'unknown',
+ 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'unknown'
+ ];
+
+ $feedbacks = file_exists($this->feedbackFile)
+ ? json_decode(file_get_contents($this->feedbackFile), true)
+ : [];
+
+ if (!is_array($feedbacks)) {
+ $feedbacks = [];
+ }
+
+ $feedbacks[] = $feedback;
+ file_put_contents($this->feedbackFile, json_encode($feedbacks, JSON_PRETTY_PRINT));
+
+ // E-MAIL SENDEN MIT GMAIL SMTP
+ $mailSent = $this->sendEmailViaGmail($name, $email, $message, $feedback['date'], $feedback['ip']);
+
+ if ($mailSent) {
+ return [
+ 'success' => true,
+ 'message' => 'Vielen Dank! Ihre Nachricht wurde gesendet.'
+ ];
+ } else {
+ error_log("Mail-Fehler: Nachricht von {$email} konnte nicht gesendet werden");
+ return [
+ 'success' => false,
+ 'message' => 'Nachricht wurde gespeichert, aber E-Mail konnte nicht gesendet werden.'
+ ];
+ }
+ }
+
+ private function sendEmailViaGmail($name, $email, $message, $date, $ip) {
+ $mail = new PHPMailer(true);
+
+
+ try {
+ // DEBUG-MODUS AKTIVIEREN
+ $mail->SMTPDebug = 2;
+ $mail->Debugoutput = function($str, $level) {
+ error_log("PHPMailer Debug: $str");
+ };
+
+ // SMTP Konfiguration
+ $mail->isSMTP();
+ $mail->Host = 'smtp.gmail.com';
+ $mail->SMTPAuth = true;
+ $mail->Username = $this->gmailUser; // metacube@gmail.com
+ $mail->Password = $this->gmailAppPassword; // qggk hsxz fdkq jgxa
+ $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
+ $mail->Port = 587;
+
+
+
+
+ // Absender & Empfänger
+ $mail->setFrom($this->gmailUser, 'Aurora Livecam');
+ $mail->addAddress($this->adminEmail); // admin@aurora-live-weathercam.com
+ $mail->addReplyTo($email, $name);
+
+ // Inhalt
+ $mail->isHTML(true);
+ $mail->CharSet = 'UTF-8';
+ $mail->Subject = '🔔 Neue Kontaktanfrage von ' . $name;
+ $mail->Body = $this->getEmailTemplate($name, $email, $message, $date, $ip);
+
+ $mail->send();
+ return true;
+ } catch (Exception $e) {
+ error_log("PHPMailer Error: {$mail->ErrorInfo}");
+ return false;
+ }
+ }
+
+ private function getEmailTemplate($name, $email, $message, $date, $ip) {
+ return "
+
+
+
+
+
+
+
+
+
+
+
+
+ 👤 Name:
+ {$name}
+
+
+
+
+
+ 💬 Nachricht:
+
+
+
+ " . nl2br($message) . "
+
+
+
+
+
+
+
+
+
+ ";
+ }
+}
+
+class AdminManager {
+ public function isAdmin() {
+ return isset($_SESSION['admin']) && $_SESSION['admin'] === true;
+ }
+ public function handleLogin($username, $password) {
+ echo "Login-Versuch: Username = $username, Passwort = $password"; // Debugging
+ if ($username === 'admin' && $password === 'sonne4000$$$$Q') {
+ $_SESSION['admin'] = true;
+ return true;
+ }
+ return false;
+ }
+
+ public function handleImageUpload($file) {
+ if (!$this->isAdmin()) {
+ return false; // Nur Admins dürfen Bilder hochladen
+ }
+
+ if (!isset($file['tmp_name']) || empty($file['tmp_name'])) {
+ echo "Keine Datei hochgeladen.";
+ return false;
+ }
+
+ $target_dir = "uploads/";
+ if (!file_exists($target_dir)) {
+ mkdir($target_dir, 0777, true);
+ }
+
+ $target_file = $target_dir . basename($file["name"]);
+ $uploadOk = 1;
+ $imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
+
+
+ $check = @getimagesize($file["tmp_name"]);
+ if($check === false) {
+ echo "Die Datei ist kein Bild.";
+ return false;
+ }
+
+
+ if ($file["size"] > 5000000) { // 5MB Limit
+ echo "Die Datei ist zu groß.";
+ return false;
+ }
+
+ // Erlauben Sie nur bestimmte Dateiformate
+ if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
+ && $imageFileType != "gif" ) {
+ echo "Nur JPG, JPEG, PNG & GIF Dateien sind erlaubt.";
+ return false;
+ }
+
+ // Wenn alles in Ordnung ist, versuchen Sie, die Datei hochzuladen
+ if (move_uploaded_file($file["tmp_name"], $target_file)) {
+ echo "Die Datei ". basename( $file["name"]). " wurde hochgeladen.";
+ return true;
+ } else {
+ echo "Es gab einen Fehler beim Hochladen der Datei.";
+ return false;
+ }
+ }
+
+
+ public function displayLoginForm() {
+ return '
+
+
+ Benutzername:
+
+ Passwort:
+
+ Einloggen
+ ';
+ }
+
+ public function displayAdminContent() {
+ $feedbacks = json_decode(file_get_contents('feedbacks.json') ?: '[]', true);
+ $output = '
Admin-Bereich ';
+ foreach ($feedbacks as $feedback) {
+ $output .= "
";
+ $output .= "
{$feedback['name']} ({$feedback['email']}) ";
+ $output .= "
{$feedback['message']}
";
+ $output .= "
{$feedback['date']} ";
+ $output .= "
";
+ }
+ $output .= '
';
+
+ $output .= '
+
Social Media Links verwalten
+
+
+
+ Facebook
+ Instagram
+ TikTok
+
+
+ Aktualisieren
+ ';
+ $output .= '
+
Bild hochladen
+
+
+
+ ';
+ return $output;
+ }
+
+ public function displayGalleryImages() {
+ $output = '
';
+ $files = glob("uploads/*.*");
+ foreach($files as $file) {
+ $filename = basename($file);
+ $extension = pathinfo($file, PATHINFO_EXTENSION);
+
+ // NUR Bilddateien anzeigen, KEINE Videos
+ if (in_array(strtolower($extension), ['jpg', 'jpeg', 'png', 'gif'])) {
+ $output .= '
';
+ }
+ }
+ $output .= '
';
+ return $output;
+}
+
+
+
+
+ public function handleSocialMediaUpdate($platform, $url) {
+ $socialLinks = json_decode(file_get_contents('social_links.json') ?: '{}', true);
+ $socialLinks[$platform] = $url;
+ file_put_contents('social_links.json', json_encode($socialLinks));
+ }
+}
+
+
+
+// Weather Bingo Manager
+//require_once 'weather_bingo.php';
+//$weatherBingo = new WeatherBingo();
+
+
+
+
+
+
+// Neue VideoArchiveManager Klasse
+
+
+class VideoArchiveManager {
+ private $videoDir;
+ private $monthNames;
+
+ public function __construct($videoDir = './videos/') {
+ $this->videoDir = $videoDir;
+ $this->monthNames = [
+ '01' => 'Januar',
+ '02' => 'Februar',
+ '03' => 'März',
+ '04' => 'April',
+ '05' => 'Mai',
+ '06' => 'Juni',
+ '07' => 'Juli',
+ '08' => 'August',
+ '09' => 'September',
+ '10' => 'Oktober',
+ '11' => 'November',
+ '12' => 'Dezember'
+ ];
+ }
+
+ public function getVideosGroupedByDate() {
+ $videos = [];
+
+ foreach (glob($this->videoDir . 'daily_video_*.mp4') as $video) {
+ // Dateinamenformat: daily_video_YYYYMMDD_HHMMSS.mp4
+ if (preg_match('/daily_video_(\d{8})_\d{6}\.mp4/', basename($video), $matches)) {
+ $dateStr = $matches[1]; // YYYYMMDD
+ $year = substr($dateStr, 0, 4);
+ $month = substr($dateStr, 4, 2);
+ $day = substr($dateStr, 6, 2);
+
+ // Gruppiere nach Jahr und Monat
+ $videos[$year][$month][] = [
+ 'path' => $video,
+ 'filename' => basename($video),
+ 'day' => $day,
+ 'filesize' => filesize($video),
+ 'modified' => filemtime($video)
+ ];
+ }
+ }
+
+ // Nach Tag sortieren
+ foreach ($videos as $year => $months) {
+ foreach ($months as $month => $days) {
+ usort($videos[$year][$month], function($a, $b) {
+ return $b['day'] - $a['day']; // Absteigend sortieren (neueste zuerst)
+ });
+ }
+ }
+
+ return $videos;
+ }
+
+ public function getAvailableYearsAndMonths() {
+ $videos = $this->getVideosGroupedByDate();
+ $result = [];
+
+ foreach ($videos as $year => $months) {
+ $result[$year] = array_keys($months);
+ }
+
+ return $result;
+ }
+
+ public function getVideosForYearAndMonth($year, $month) {
+ $videos = $this->getVideosGroupedByDate();
+ return isset($videos[$year][$month]) ? $videos[$year][$month] : [];
+ }
+
+ public function displayCalendarInterface() {
+ $yearsAndMonths = $this->getAvailableYearsAndMonths();
+
+ $output = '
';
+ $output .= '
Video-Archiv ';
+
+ if (empty($yearsAndMonths)) {
+ $output .= '
Keine Videos verfügbar.
';
+ } else {
+ $output .= '
';
+ $output .= '
';
+
+ // Jahr-Auswahl
+ $output .= 'Jahr: ';
+ $output .= '';
+
+ foreach ($yearsAndMonths as $year => $months) {
+ $selected = (isset($_GET['calendar_year']) && $_GET['calendar_year'] == $year) ? 'selected' : '';
+ $output .= "$year ";
+ }
+
+ $output .= ' ';
+
+ // Monats-Auswahl
+ $output .= 'Monat: ';
+ $output .= '';
+
+ // Wenn ein Jahr ausgewählt wurde, zeige die verfügbaren Monate
+ if (isset($_GET['calendar_year']) && isset($yearsAndMonths[$_GET['calendar_year']])) {
+ foreach ($yearsAndMonths[$_GET['calendar_year']] as $month) {
+ $selected = (isset($_GET['calendar_month']) && $_GET['calendar_month'] == $month) ? 'selected' : '';
+ $output .= "{$this->monthNames[$month]} ";
+ }
+ }
+
+ $output .= ' ';
+ $output .= 'Anzeigen ';
+ $output .= ' ';
+ $output .= '';
+
+ // Wenn Jahr und Monat ausgewählt wurden, zeige die Videos
+ if (isset($_GET['calendar_year']) && isset($_GET['calendar_month'])) {
+ $year = $_GET['calendar_year'];
+ $month = $_GET['calendar_month'];
+ $videos = $this->getVideosForYearAndMonth($year, $month);
+
+ if (!empty($videos)) {
+ $output .= '
';
+ $output .= "
Videos für {$this->monthNames[$month]} $year ";
+ $output .= '
';
+ $output .= '
';
+ } else {
+ $output .= "
Keine Videos für {$this->monthNames[$month]} $year gefunden.
";
+ }
+ }
+ }
+
+ $output .= '
';
+ return $output;
+ }
+
+ public function handleSpecificVideoDownload() {
+ if (isset($_GET['download_specific_video']) && isset($_GET['token'])) {
+ $videoPath = $_GET['download_specific_video'];
+ $token = $_GET['token'];
+
+ // Token-Validierung
+ $expectedToken = hash_hmac('sha256', $videoPath, session_id());
+ if (!hash_equals($expectedToken, $token)) {
+ echo "Ungültiger Token. Zugriff verweigert.";
+ exit;
+ }
+
+ // Sicherheitsüberprüfung: Stelle sicher, dass das Video im erlaubten Verzeichnis liegt
+ $videoDir = realpath($this->videoDir);
+ $requestedPath = realpath($videoPath);
+
+ if ($requestedPath && strpos($requestedPath, $videoDir) === 0 && file_exists($requestedPath)) {
+ // Nur MP4-Dateien erlauben
+ $extension = pathinfo($requestedPath, PATHINFO_EXTENSION);
+ if (strtolower($extension) !== 'mp4') {
+ echo "Nur MP4-Dateien können heruntergeladen werden.";
+ exit;
+ }
+
+ header('Content-Description: File Transfer');
+ header('Content-Type: video/mp4');
+ header('Content-Disposition: attachment; filename="'.basename($requestedPath).'"');
+ header('Expires: 0');
+ header('Cache-Control: must-revalidate');
+ header('Pragma: public');
+ header('Content-Length: ' . filesize($requestedPath));
+ readfile($requestedPath);
+ exit;
+ } else {
+ echo "Datei nicht gefunden oder ungültiger Dateipfad.";
+ exit;
+ }
+ }
+ }
+}
+
+
+
+
+
+
+
+$webcamManager = new WebcamManager();
+$imageFilesJson = $webcamManager->getImageFiles();
+$guestbookManager = new GuestbookManager();
+$contactManager = new ContactManager();
+$adminManager = new AdminManager();
+
+// Nach den anderen Manager-Instanzen hinzufügen
+$videoArchiveManager = new VideoArchiveManager('./videos/');
+
+// Video-Download-Handler nach dem existierenden Download-Handler hinzufügen
+$videoArchiveManager->handleSpecificVideoDownload();
+
+
+if (isset($_GET['action'])) {
+ switch ($_GET['action']) {
+ case 'snapshot':
+ $webcamManager->captureSnapshot();
+
+ break;
+ case 'sequence':
+ $webcamManager->captureVideoSequence();
+
+ break;
+
+ }
+
+}
+
+
+if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'delete_guestbook') {
+ if ($adminManager->isAdmin() && isset($_POST['delete_entry'])) {
+ $index = $_POST['delete_entry'];
+ if ($guestbookManager->deleteEntry($index)) {
+ $_SESSION['message'] = "Eintrag erfolgreich gelöscht.";
+ } else {
+ $_SESSION['error'] = "Fehler beim Löschen des Eintrags.";
+ }
+ // Umleitung zur gleichen Seite, um Neuladen des Formulars zu verhindern
+ header("Location: " . $_SERVER['PHP_SELF'] . "#guestbook");
+ exit();
+ }
+}
+
+
+if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+ if (isset($_POST['guestbook'])) {
+ $guestbookManager->handleFormSubmission();
+ } elseif (isset($_POST['contact'])) {
+ $result = $contactManager->handleSubmission($_POST['name'], $_POST['email'], $_POST['message']);
+
+ // JSON-Response für AJAX
+ if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) &&
+ strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') {
+ header('Content-Type: application/json');
+ echo json_encode($result);
+ exit;
+ }
+
+ // Normale Formular-Submission
+ $_SESSION['contact_result'] = $result;
+ header('Location: ' . $_SERVER['PHP_SELF'] . '#kontakt');
+ exit;
+
+ } elseif (isset($_POST['admin-login'])) {
+ $adminManager->handleLogin($_POST['username'], $_POST['password']);
+ } elseif (isset($_POST['update-social-media'])) {
+ $adminManager->handleSocialMediaUpdate($_POST['social-platform'], $_POST['social-url']);
+
+
+ } elseif (isset($_FILES["fileToUpload"]) && $adminManager->isAdmin()) {
+ $adminManager->handleImageUpload($_FILES["fileToUpload"]);
+}}
+?>
+
+
+
+
+
+
+
+
+
+
Aurora Livecam - Einzigartige Live-Webcam und Wetter>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Willkommen bei Aurora Wetter Livecam
+
+
+
+
+
+
+ Erleben Sie faszinierende Ausblicke der Züricher Region - in Echtzeit!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ displayWebcam(); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Videoarchiv (Tagesvideos)
+
+ displayVisualCalendar();
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Folge uns und kopiere den Code und sende es deinen Freunden in Tiktok, Facebook, Instagram usw.
+
+
+
+
+
+ Klicke auf den QR-Code, um die URL zu kopieren
+
+
+
+
+
+
+
+
📋 Nutzungsbedingungen & Chat-Regeln
+
+
+
⚠️ Wichtige Verhaltensregeln:
+
+ Keine sexuellen, pornografischen oder anzüglichen Inhalte
+ Keine Gewaltdarstellungen oder -androhungen
+ Kein Rassismus, Diskriminierung oder Hassrede
+ Keine persönlichen Daten (Telefonnummern, Adressen) teilen
+ Keine Werbung oder Spam
+ Respektvoller Umgang miteinander
+ Keine illegalen Aktivitäten oder Inhalte
+
+
+
+
+
📸 Webcam-Nutzung:
+
Die Webcam zeigt öffentlichen Raum. Es werden keine Personen gezielt aufgenommen. Die Nutzung erfolgt auf eigene Verantwortung.
+
+
+
+
💬 Chat-Nutzung:
+
Mit der Nutzung des Chats akzeptieren Sie diese Regeln. Verstöße führen zur sofortigen Sperrung. Chat-Nachrichten werden 24 Stunden gespeichert.
+
+
+
+
⚖️ Rechtliches:
+
Haftungsausschluss: Der Betreiber übernimmt keine Haftung für Inhalte von Nutzern. Jeder Nutzer ist für seine Beiträge selbst verantwortlich.
+
Datenschutz: Es werden nur technisch notwendige Daten gespeichert (IP-Adresse für 24h zur Missbrauchsprävention).
+
+
+
+
+
+ Ich akzeptiere die Nutzungsbedingungen
+
+
+
+
+
+ Akzeptieren & Chat nutzen
+
+
+ Ablehnen
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Gästebuch
+ {$_SESSION['message'][$currentLang]}";
+ unset($_SESSION['message']);
+ }
+ if (isset($_SESSION['error'])) {
+ echo "
{$_SESSION['error'][$currentLang]}
";
+ unset($_SESSION['error']);
+ }
+
+ echo $guestbookManager->displayForm();
+ echo $guestbookManager->displayEntries($adminManager->isAdmin());
+ ?>
+
+
+
+
+
+
+
+
+
+
+
Kontakt
+
Haben Sie Fragen, Anregungen oder möchten uns unterstützen? Wir freuen uns auf Ihre Nachricht!
+
+
+
+
+
+ displayForm(); ?>
+
+
+
+
+
+
+
+
+ displayGalleryImages(); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+ Aurora Wetter Livecam ist ein Herzensprojekt von Wetterbegeisterten. Wir möchten Ihnen die Schönheit der Natur und Faszination des Wetters näher bringen.
+
+
+ Dazu betreiben wir seit 2010 rund um die Uhr hochauflösende Webcams. Besonders stolz sind wir auf einzigartige Einblicke, wie z.B. die Trainingsflüge der Patrouille Suisse jeden Montagmorgen.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ isAdmin()): ?>
+
+
+
Admin-Bereich
+ displayAdminContent(); ?>
+
+
+
+
+
+
Admin Login
+ displayLoginForm(); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Impressum
+
+
Aurora Wetter Livecam
+
M. Kessler
+
Dürnten
+
Schweiz
+
+ Anfragen per Kontaktformular
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+