index.php
Colombo
|
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);
$db = new SQLite3(__DIR__ . '/db.sqlite');
$db->busyTimeout(30000);
$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");
}
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;
}
// ------------------------------------------------------------------
// HANDLE UPLOADS (single image from PHOTO, chunked video from GO LIVE)
// ------------------------------------------------------------------
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 === '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);
}
} else {
http_response_code(400);
echo json_encode(['error' => 'Invalid media type for chunked upload']);
exit;
}
$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;
}
}
if ($_FILES['media']['error'] !== UPLOAD_ERR_OK) {
http_response_code(400);
exit('Upload failed');
}
if ($type !== 'image') {
http_response_code(400);
exit('Invalid media type for single upload');
}
$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);
$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', null);
$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;
}
// ------------------------------------------------------------------
// MAIN FEED WITH PAGINATION
// ------------------------------------------------------------------
$search = isset($_GET['q']) ? trim($_GET['q']) : '';
$type = isset($_GET['type']) ? $_GET['type'] : 'all';
$page = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
$limit = 60;
$offset = ($page - 1) * $limit;
// Count total matching records
$countSql = "SELECT COUNT(*) as total FROM content WHERE 1=1";
$params = [];
if (!empty($search)) {
$countSql .= " AND (title LIKE :search OR description LIKE :search OR content LIKE :search)";
$params[':search'] = "%$search%";
}
if ($type !== 'all') {
$countSql .= " AND type = :type";
$params[':type'] = $type;
}
$countStmt = $db->prepare($countSql);
foreach ($params as $key => $val) $countStmt->bindValue($key, $val);
$total = $countStmt->execute()->fetchArray(SQLITE3_ASSOC)['total'];
$totalPages = ceil($total / $limit);
// Fetch current page
$sql = "SELECT * FROM content WHERE 1=1";
if (!empty($search)) {
$sql .= " AND (title LIKE :search OR description LIKE :search OR content LIKE :search)";
}
if ($type !== 'all') {
$sql .= " AND type = :type";
}
$sql .= " ORDER BY created_at DESC LIMIT $limit OFFSET $offset";
$stmt = $db->prepare($sql);
foreach ($params as $key => $val) $stmt->bindValue($key, $val);
$result = $stmt->execute();
$contents = [];
while ($row = $result->fetchArray(SQLITE3_ASSOC)) $contents[] = $row;
// ------------------------------------------------------------------
// FOOTER MAP & JOURNEY STATS (standalone)
// ------------------------------------------------------------------
$geoQuery = "SELECT id, title, latitude, longitude, location_name, created_at
FROM content
WHERE latitude IS NOT NULL AND longitude IS NOT NULL
ORDER BY created_at ASC";
$geoResult = $db->query($geoQuery);
$geoPoints = [];
$totalDistanceKm = 0;
$totalDistanceMiles = 0;
while ($row = $geoResult->fetchArray(SQLITE3_ASSOC)) {
$geoPoints[] = [
'id' => $row['id'],
'title' => $row['title'],
'lat' => (float)$row['latitude'],
'lng' => (float)$row['longitude'],
'location_name' => $row['location_name'],
'created_at' => $row['created_at']
];
}
function haversineDistance($lat1, $lon1, $lat2, $lon2) {
$earthRadiusKm = 6371;
$dLat = deg2rad($lat2 - $lat1);
$dLon = deg2rad($lon2 - $lon1);
$a = sin($dLat/2) * sin($dLat/2) +
cos(deg2rad($lat1)) * cos(deg2rad($lat2)) *
sin($dLon/2) * sin($dLon/2);
$c = 2 * atan2(sqrt($a), sqrt(1-$a));
return $earthRadiusKm * $c;
}
if (count($geoPoints) >= 2) {
for ($i = 0; $i < count($geoPoints) - 1; $i++) {
$distKm = haversineDistance(
$geoPoints[$i]['lat'], $geoPoints[$i]['lng'],
$geoPoints[$i+1]['lat'], $geoPoints[$i+1]['lng']
);
$totalDistanceKm += $distKm;
}
$totalDistanceMiles = $totalDistanceKm * 0.621371;
}
?>
Fiveo1 · Evan Winter
= 1): ?>
1): ?>
Recording...
= 1): ?>
← Back to Fiveo1
▼
▲