Clone

Logroño
true, 'cookie_secure' => (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https'), 'use_strict_mode' => true, 'use_only_cookies' => true, 'cookie_samesite' => 'Strict' ]); ini_set('upload_max_filesize', '2G'); ini_set('post_max_size', '2G'); ini_set('memory_limit', '2G'); ini_set('max_execution_time', 0); error_reporting(E_ALL); ini_set('display_errors', 1); $db = new SQLite3(__DIR__ . '/db.sqlite'); $db->busyTimeout(30000); // Ensure required columns exist $cols = $db->query("PRAGMA table_info(content)"); $existing = []; while ($c = $cols->fetchArray(SQLITE3_ASSOC)) $existing[] = $c['name']; foreach (['content', 'thumbnail', 'ip_address', 'fingerprint'] as $col) { if (!in_array($col, $existing)) $db->exec("ALTER TABLE content ADD COLUMN $col TEXT"); } $db->exec("CREATE TABLE IF NOT EXISTS content ( id INTEGER PRIMARY KEY AUTOINCREMENT, type TEXT NOT NULL, title TEXT NOT NULL, description TEXT, content TEXT, filename TEXT, file_path TEXT, thumbnail TEXT, latitude REAL, longitude REAL, location_name TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, ip_address TEXT, fingerprint TEXT )"); function generateVideoThumbnail($video_path, $thumbnail_path) { if (!function_exists('exec')) return false; $cmd = "ffmpeg -i " . escapeshellarg($video_path) . " -ss 00:00:01 -vframes 1 -vf scale=320:-1 " . escapeshellarg($thumbnail_path) . " 2>&1"; exec($cmd, $output, $return); return ($return === 0 && file_exists($thumbnail_path)); } function combineChunks($chunkDir, $totalChunks, $finalTempPath) { $out = fopen($finalTempPath, 'wb'); if (!$out) return false; for ($i = 0; $i < $totalChunks; $i++) { $partPath = $chunkDir . '/part_' . $i; if (!file_exists($partPath)) { fclose($out); return false; } $part = fopen($partPath, 'rb'); while (!feof($part)) { fwrite($out, fread($part, 8192)); } fclose($part); } fclose($out); return true; } if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } // ------------------------------------------------------------------ // 1. HANDLE LIVE UPLOADS (chunked video + single image) // ------------------------------------------------------------------ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['media'])) { $title = $_POST['title'] ?? ''; $description = $_POST['description'] ?? ''; $latitude = isset($_POST['latitude']) && $_POST['latitude'] !== '' ? floatval($_POST['latitude']) : null; $longitude = isset($_POST['longitude']) && $_POST['longitude'] !== '' ? floatval($_POST['longitude']) : null; $location_name = $_POST['location_name'] ?? ''; $fingerprint = $_POST['fingerprint'] ?? ''; $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown'; $type = $_POST['type'] ?? ''; $isChunked = isset($_POST['chunk_index']) && isset($_POST['upload_id']) && isset($_POST['chunk_total']); if ($isChunked) { $chunkIndex = intval($_POST['chunk_index']); $chunkTotal = intval($_POST['chunk_total']); $uploadId = preg_replace('/[^a-zA-Z0-9_-]/', '', $_POST['upload_id']); if (empty($uploadId) || $chunkTotal <= 0 || $chunkIndex < 0 || $chunkIndex >= $chunkTotal) { http_response_code(400); echo json_encode(['error' => 'Invalid chunk parameters']); exit; } $chunkBaseDir = __DIR__ . '/uploads/chunks/' . $uploadId; if (!is_dir($chunkBaseDir)) mkdir($chunkBaseDir, 0755, true); $chunkPath = $chunkBaseDir . '/part_' . $chunkIndex; if (!move_uploaded_file($_FILES['media']['tmp_name'], $chunkPath)) { http_response_code(500); echo json_encode(['error' => 'Failed to save chunk']); exit; } if ($chunkIndex === 0) { $meta = [ 'title' => $title, 'description' => $description, 'type' => $type, 'latitude' => $latitude, 'longitude' => $longitude, 'location_name' => $location_name, 'fingerprint' => $fingerprint, 'ip' => $ip ]; file_put_contents($chunkBaseDir . '/meta.json', json_encode($meta)); } if ($chunkIndex === $chunkTotal - 1) { $metaFile = $chunkBaseDir . '/meta.json'; if (!file_exists($metaFile)) { http_response_code(400); echo json_encode(['error' => 'Metadata missing']); exit; } $meta = json_decode(file_get_contents($metaFile), true); if (!$meta) { http_response_code(400); echo json_encode(['error' => 'Invalid metadata']); exit; } $title = $meta['title']; $description = $meta['description']; $type = $meta['type']; $latitude = $meta['latitude']; $longitude = $meta['longitude']; $location_name = $meta['location_name']; $fingerprint = $meta['fingerprint']; $ip = $meta['ip']; $tempFinal = $chunkBaseDir . '/final_temp'; if (!combineChunks($chunkBaseDir, $chunkTotal, $tempFinal)) { http_response_code(500); echo json_encode(['error' => 'Failed to combine chunks']); exit; } $upload_dir = ''; $web_path = ''; $thumbnail = null; $filename = ''; if ($type === 'image') { $upload_dir = __DIR__ . '/uploads/images/'; $web_path = '/uploads/images/'; if (!is_dir($upload_dir)) mkdir($upload_dir, 0755, true); $ext = 'jpg'; $filename = uniqid('photo_') . '.' . $ext; $finalPath = $upload_dir . $filename; rename($tempFinal, $finalPath); $file_path = $web_path . $filename; } elseif ($type === 'video') { $upload_dir = __DIR__ . '/uploads/videos/'; $web_path = '/uploads/videos/'; if (!is_dir($upload_dir)) mkdir($upload_dir, 0755, true); $ext = 'mp4'; $filename = uniqid('live_') . '.' . $ext; $finalPath = $upload_dir . $filename; rename($tempFinal, $finalPath); $file_path = $web_path . $filename; if (function_exists('exec')) { $thumb_dir = __DIR__ . '/uploads/videos/thumbnails/'; if (!is_dir($thumb_dir)) mkdir($thumb_dir, 0755, true); $thumb_filename = uniqid() . '.jpg'; $thumbnail = '/uploads/videos/thumbnails/' . $thumb_filename; $cmd = "ffmpeg -i " . escapeshellarg($finalPath) . " -ss 00:00:01 -vframes 1 -vf scale=320:-1 " . escapeshellarg($thumb_dir . $thumb_filename) . " 2>&1"; exec($cmd); } } $stmt = $db->prepare("INSERT INTO content (type, title, description, filename, file_path, thumbnail, latitude, longitude, location_name, created_at, ip_address, fingerprint) VALUES (:type, :title, :description, :filename, :file_path, :thumbnail, :lat, :lng, :loc, datetime('now'), :ip, :fp)"); $stmt->bindValue(':type', $type); $stmt->bindValue(':title', $title); $stmt->bindValue(':description', $description); $stmt->bindValue(':filename', $filename); $stmt->bindValue(':file_path', $file_path); $stmt->bindValue(':thumbnail', $thumbnail); $stmt->bindValue(':lat', $latitude); $stmt->bindValue(':lng', $longitude); $stmt->bindValue(':loc', $location_name); $stmt->bindValue(':ip', $ip); $stmt->bindValue(':fp', $fingerprint); $stmt->execute(); array_map('unlink', glob($chunkBaseDir . '/*')); rmdir($chunkBaseDir); header('Content-Type: application/json'); echo json_encode(['success' => true, 'post_id' => $db->lastInsertRowID()]); exit; } else { header('Content-Type: application/json'); echo json_encode(['success' => true, 'chunk' => $chunkIndex, 'total' => $chunkTotal]); exit; } } // Single-file upload (for images from Go Live) if ($_FILES['media']['error'] !== UPLOAD_ERR_OK) { http_response_code(400); exit('Upload failed'); } $upload_dir = ''; $web_path = ''; $thumbnail = null; $filename = ''; $file_path = ''; if ($type === 'image') { $upload_dir = __DIR__ . '/uploads/images/'; $web_path = '/uploads/images/'; if (!is_dir($upload_dir)) mkdir($upload_dir, 0755, true); $ext = 'jpg'; $filename = uniqid('photo_') . '.' . $ext; $file_path = $web_path . $filename; move_uploaded_file($_FILES['media']['tmp_name'], $upload_dir . $filename); } elseif ($type === 'video') { $upload_dir = __DIR__ . '/uploads/videos/'; $web_path = '/uploads/videos/'; if (!is_dir($upload_dir)) mkdir($upload_dir, 0755, true); $ext = 'webm'; $filename = uniqid('live_') . '.' . $ext; $file_path = $web_path . $filename; move_uploaded_file($_FILES['media']['tmp_name'], $upload_dir . $filename); if (function_exists('exec')) { $thumb_dir = __DIR__ . '/uploads/videos/thumbnails/'; if (!is_dir($thumb_dir)) mkdir($thumb_dir, 0755, true); $thumb_filename = uniqid() . '.jpg'; $thumbnail = '/uploads/videos/thumbnails/' . $thumb_filename; $cmd = "ffmpeg -i " . escapeshellarg($upload_dir . $filename) . " -ss 00:00:01 -vframes 1 -vf scale=320:-1 " . escapeshellarg($thumb_dir . $thumb_filename) . " 2>&1"; exec($cmd); } } else { http_response_code(400); exit('Invalid media type'); } $stmt = $db->prepare("INSERT INTO content (type, title, description, filename, file_path, thumbnail, latitude, longitude, location_name, created_at, ip_address, fingerprint) VALUES (:type, :title, :description, :filename, :file_path, :thumbnail, :lat, :lng, :loc, datetime('now'), :ip, :fp)"); $stmt->bindValue(':type', $type); $stmt->bindValue(':title', $title); $stmt->bindValue(':description', $description); $stmt->bindValue(':filename', $filename); $stmt->bindValue(':file_path', $file_path); $stmt->bindValue(':thumbnail', $thumbnail); $stmt->bindValue(':lat', $latitude); $stmt->bindValue(':lng', $longitude); $stmt->bindValue(':loc', $location_name); $stmt->bindValue(':ip', $ip); $stmt->bindValue(':fp', $fingerprint); $stmt->execute(); header('Content-Type: application/json'); echo json_encode(['success' => true, 'post_id' => $db->lastInsertRowID()]); exit; } // ------------------------------------------------------------------ // 2. AUTHENTICATION (Evan@fiveo1.com is pre-set, password @Evan.Winter) // ------------------------------------------------------------------ $correct_password = '@Evan.Winter'; $admin_email = 'Evan@fiveo1.com'; // Pre-set, not visible to user if (isset($_POST['login'])) { if (hash_equals($correct_password, $_POST['password'] ?? '')) { session_regenerate_id(true); $_SESSION['logged_in'] = true; $_SESSION['admin_email'] = $admin_email; unset($_SESSION['login_blocked']); header('Location: admin.php'); exit; } else { $_SESSION['login_blocked'] = true; exit; } } if (isset($_SESSION['login_blocked']) && $_SESSION['login_blocked'] === true) { exit; } if (isset($_GET['logout'])) { session_destroy(); header('Location: admin.php'); exit; } $is_admin = isset($_SESSION['logged_in']) && $_SESSION['logged_in'] === true; // ------------------------------------------------------------------ // 3. ADD CONTENT (CRUD) // ------------------------------------------------------------------ if ($is_admin && isset($_POST['add_content'])) { if (!isset($_POST['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) die('CSRF failed'); $type = $_POST['type']; $title = trim($_POST['title'] ?? ''); $description = trim($_POST['description'] ?? ''); $content = trim($_POST['content'] ?? ''); $location_name = trim($_POST['location_name'] ?? ''); $latitude = !empty($_POST['latitude']) ? floatval($_POST['latitude']) : null; $longitude = !empty($_POST['longitude']) ? floatval($_POST['longitude']) : null; $created_at = null; if (!empty($_POST['created_at'])) { $dt = DateTime::createFromFormat('Y-m-d\TH:i', $_POST['created_at']); if ($dt) $created_at = $dt->format('Y-m-d H:i:s'); } $file_path = null; $filename = null; $thumbnail = null; if ($type === 'image' || $type === 'video') { if (isset($_FILES['file']) && $_FILES['file']['error'] === UPLOAD_ERR_OK) { $upload_dir = ($type === 'image') ? __DIR__ . '/uploads/images/' : __DIR__ . '/uploads/videos/'; $web_path = ($type === 'image') ? '/uploads/images/' : '/uploads/videos/'; if (!is_dir($upload_dir)) mkdir($upload_dir, 0755, true); $ext = strtolower(pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION)); $filename = uniqid() . '.' . $ext; $file_path = $web_path . $filename; if (move_uploaded_file($_FILES['file']['tmp_name'], $upload_dir . $filename)) { chmod($upload_dir . $filename, 0644); if ($type === 'video') { $thumb_dir = __DIR__ . '/uploads/videos/thumbnails/'; if (!is_dir($thumb_dir)) mkdir($thumb_dir, 0755, true); $thumb_filename = uniqid() . '.jpg'; $thumbnail = '/uploads/videos/thumbnails/' . $thumb_filename; generateVideoThumbnail($upload_dir . $filename, $thumb_dir . $thumb_filename); } } else { $_SESSION['add_error'] = 'File upload failed'; header('Location: admin.php?error=1'); exit; } } else { $_SESSION['add_error'] = 'Please select a file'; header('Location: admin.php?error=1'); exit; } } if ($created_at) $stmt = $db->prepare("INSERT INTO content (type, title, description, content, filename, file_path, thumbnail, latitude, longitude, location_name, created_at) VALUES (:type, :title, :description, :content, :filename, :file_path, :thumbnail, :lat, :lng, :loc, :created_at)"); else $stmt = $db->prepare("INSERT INTO content (type, title, description, content, filename, file_path, thumbnail, latitude, longitude, location_name) VALUES (:type, :title, :description, :content, :filename, :file_path, :thumbnail, :lat, :lng, :loc)"); $stmt->bindValue(':type', $type); $stmt->bindValue(':title', $title); $stmt->bindValue(':description', $description); $stmt->bindValue(':content', $content); $stmt->bindValue(':filename', $filename); $stmt->bindValue(':file_path', $file_path); $stmt->bindValue(':thumbnail', $thumbnail); $stmt->bindValue(':lat', $latitude); $stmt->bindValue(':lng', $longitude); $stmt->bindValue(':loc', $location_name); if ($created_at) $stmt->bindValue(':created_at', $created_at); $stmt->execute(); $_SESSION['add_success'] = 'Content added!'; header('Location: admin.php?success=added'); exit; } // ------------------------------------------------------------------ // 4. UPDATE CONTENT // ------------------------------------------------------------------ if ($is_admin && isset($_POST['update_content'])) { if (!isset($_POST['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) die('CSRF failed'); $id = intval($_POST['id']); $type = $_POST['type']; $title = trim($_POST['title']); $description = trim($_POST['description']); $content = trim($_POST['content'] ?? ''); $location_name = trim($_POST['location_name'] ?? ''); $latitude = !empty($_POST['latitude']) ? floatval($_POST['latitude']) : null; $longitude = !empty($_POST['longitude']) ? floatval($_POST['longitude']) : null; $created_at = null; if (!empty($_POST['created_at'])) { $dt = DateTime::createFromFormat('Y-m-d\TH:i', $_POST['created_at']); if ($dt) $created_at = $dt->format('Y-m-d H:i:s'); } // File replacement handling if (!empty($_FILES['file']['name']) && ($type === 'image' || $type === 'video')) { $stmt = $db->prepare("SELECT file_path, thumbnail FROM content WHERE id = :id"); $stmt->bindValue(':id', $id); $result = $stmt->execute(); $old = $result->fetchArray(SQLITE3_ASSOC); $upload_dir = ($type === 'image') ? __DIR__ . '/uploads/images/' : __DIR__ . '/uploads/videos/'; $web_path = ($type === 'image') ? '/uploads/images/' : '/uploads/videos/'; if (!is_dir($upload_dir)) mkdir($upload_dir, 0755, true); $ext = strtolower(pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION)); $filename = uniqid() . '.' . $ext; $file_path = $web_path . $filename; if (move_uploaded_file($_FILES['file']['tmp_name'], $upload_dir . $filename)) { if ($old && !empty($old['file_path'])) { $old_file = __DIR__ . $old['file_path']; if (file_exists($old_file)) unlink($old_file); } if ($old && !empty($old['thumbnail'])) { $old_thumb = __DIR__ . $old['thumbnail']; if (file_exists($old_thumb)) unlink($old_thumb); } $thumbnail = null; if ($type === 'video') { $thumb_dir = __DIR__ . '/uploads/videos/thumbnails/'; if (!is_dir($thumb_dir)) mkdir($thumb_dir, 0755, true); $thumb_filename = uniqid() . '.jpg'; $thumbnail = '/uploads/videos/thumbnails/' . $thumb_filename; generateVideoThumbnail($upload_dir . $filename, $thumb_dir . $thumb_filename); } $stmt = $db->prepare("UPDATE content SET type=:type, title=:title, description=:description, content=:content, filename=:filename, file_path=:file_path, thumbnail=:thumbnail, latitude=:lat, longitude=:lng, location_name=:loc, created_at=COALESCE(:created_at, created_at) WHERE id=:id"); $stmt->bindValue(':filename', $filename); $stmt->bindValue(':file_path', $file_path); $stmt->bindValue(':thumbnail', $thumbnail); } else { $stmt = $db->prepare("UPDATE content SET type=:type, title=:title, description=:description, content=:content, latitude=:lat, longitude=:lng, location_name=:loc, created_at=COALESCE(:created_at, created_at) WHERE id=:id"); } } else { $stmt = $db->prepare("UPDATE content SET type=:type, title=:title, description=:description, content=:content, latitude=:lat, longitude=:lng, location_name=:loc, created_at=COALESCE(:created_at, created_at) WHERE id=:id"); } $stmt->bindValue(':type', $type); $stmt->bindValue(':title', $title); $stmt->bindValue(':description', $description); $stmt->bindValue(':content', $content); $stmt->bindValue(':lat', $latitude); $stmt->bindValue(':lng', $longitude); $stmt->bindValue(':loc', $location_name); $stmt->bindValue(':created_at', $created_at); $stmt->bindValue(':id', $id); $stmt->execute(); header('Location: admin.php?success=updated'); exit; } // ------------------------------------------------------------------ // 5. DELETE CONTENT // ------------------------------------------------------------------ if ($is_admin && isset($_POST['delete_id'])) { if (!isset($_POST['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) die('CSRF failed'); $id = intval($_POST['delete_id']); $stmt = $db->prepare("SELECT file_path, thumbnail FROM content WHERE id = :id"); $stmt->bindValue(':id', $id); $result = $stmt->execute(); $item = $result->fetchArray(SQLITE3_ASSOC); if ($item) { if (!empty($item['file_path'])) { $full_path = __DIR__ . $item['file_path']; if (file_exists($full_path)) unlink($full_path); } if (!empty($item['thumbnail'])) { $thumb_path = __DIR__ . $item['thumbnail']; if (file_exists($thumb_path)) unlink($thumb_path); } } $del = $db->prepare("DELETE FROM content WHERE id = :id"); $del->bindValue(':id', $id); $del->execute(); header('Location: admin.php?success=deleted'); exit; } // Fetch all content $result = $db->query("SELECT id, title, type, location_name, created_at, file_path FROM content ORDER BY created_at DESC"); $all_content = []; while ($row = $result->fetchArray(SQLITE3_ASSOC)) $all_content[] = $row; $edit_item = null; if ($is_admin && isset($_GET['edit'])) { $id = intval($_GET['edit']); $stmt = $db->prepare("SELECT * FROM content WHERE id = :id"); $stmt->bindValue(':id', $id); $result = $stmt->execute(); $edit_item = $result->fetchArray(SQLITE3_ASSOC); } $success_msg = ''; if (isset($_GET['success'])) { if ($_GET['success'] === 'added') $success_msg = 'Content added!'; if ($_GET['success'] === 'updated') $success_msg = 'Content updated!'; if ($_GET['success'] === 'deleted') $success_msg = 'Content deleted!'; } if (isset($_SESSION['add_success'])) { $success_msg = $_SESSION['add_success']; unset($_SESSION['add_success']); } $error_msg = ''; if (isset($_GET['error']) && isset($_SESSION['add_error'])) { $error_msg = $_SESSION['add_error']; unset($_SESSION['add_error']); } ?> Fiveo1 · Admin Panel

Welcome, Evan. Logout →


✓
⚠️

✎ Edit Content ID:

Current:
Cancel

Add New Content


Existing Content · items

⚠️ Delete removes entry and files permanently
· · 📍
Edit
Recording...
← Back to Fiveo1
▼
▲