Code
3ra Calle Nor Este
|
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', 0); // set to 1 for debugging
// Helper: get base URL dynamically
function baseUrl() {
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https://' : 'http://';
$host = $_SERVER['HTTP_HOST'];
$script = $_SERVER['SCRIPT_NAME'];
$dir = dirname($script);
if ($dir == '\\' || $dir == '/') $dir = '';
return $protocol . $host . $dir;
}
$dbPath = __DIR__ . '/db.sqlite';
$db = new SQLite3($dbPath);
$db->busyTimeout(30000);
$db->exec("PRAGMA journal_mode=WAL");
$db->exec("PRAGMA synchronous=NORMAL");
// Create tables if not exist
$db->exec("CREATE TABLE IF NOT EXISTS content (
id INTEGER PRIMARY KEY AUTOINCREMENT,
type TEXT CHECK(type IN ('image','video','article')),
title TEXT,
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
)");
$db->exec("CREATE INDEX IF NOT EXISTS idx_content_created ON content(created_at DESC)");
$db->exec("CREATE INDEX IF NOT EXISTS idx_content_type ON content(type)");
$db->exec("CREATE INDEX IF NOT EXISTS idx_content_location ON content(latitude, longitude) WHERE latitude IS NOT NULL AND longitude IS NOT NULL");
$db->exec("CREATE INDEX IF NOT EXISTS idx_content_search ON content(title, description, content)");
$db->exec("PRAGMA optimize");
// Ensure upload directories exist
foreach (['uploads', 'uploads/images', 'uploads/videos', 'uploads/videos/thumbnails', 'uploads/chunks'] as $dir) {
if (!is_dir(__DIR__ . '/' . $dir)) mkdir(__DIR__ . '/' . $dir, 0755, true);
}
// ------------------------------------------------------------------
if (!function_exists('haversineDistance')) {
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;
}
}
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;
}
function cleanupOldChunks() {
$chunkBase = __DIR__ . '/uploads/chunks/';
if (!is_dir($chunkBase)) return;
$now = time();
foreach (glob($chunkBase . '*', GLOB_ONLYDIR) as $dir) {
if ($now - filemtime($dir) > 3600) {
array_map('unlink', glob($dir . '/*'));
rmdir($dir);
}
}
}
if (mt_rand(1, 100) === 1) cleanupOldChunks();
function getCachedGeoPoints($db, $cacheFile = __DIR__ . '/uploads/.geopoints.cache') {
$ttl = 300;
if (file_exists($cacheFile) && (time() - filemtime($cacheFile) < $ttl)) {
$data = file_get_contents($cacheFile);
if ($data !== false) {
$cached = unserialize($data);
if (is_array($cached)) return $cached;
}
}
$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);
$points = [];
while ($row = $geoResult->fetchArray(SQLITE3_ASSOC)) {
$points[] = [
'id' => $row['id'],
'title' => $row['title'],
'lat' => (float)$row['latitude'],
'lng' => (float)$row['longitude'],
'location_name' => $row['location_name'],
'created_at' => $row['created_at']
];
}
file_put_contents($cacheFile, serialize($points), LOCK_EX);
return $points;
}
function invalidateGeoCache() {
$cacheFile = __DIR__ . '/uploads/.geopoints.cache';
if (file_exists($cacheFile)) @unlink($cacheFile);
}
// Generate a filename and title from location and time
function generateMediaTitleAndFilename($location_name, $timestamp = null) {
if ($timestamp === null) $timestamp = time();
$dateTitle = date('n/j/Y, g:i:s A', $timestamp);
$title = '@' . $dateTitle;
if (!empty($location_name)) {
$title .= ' - ' . $location_name;
}
$dateFile = date('m-d-Y_H-i-s', $timestamp);
$filename = '@' . $dateFile;
if (!empty($location_name)) {
$slug = preg_replace('/[^a-z0-9]+/i', '_', trim($location_name));
$slug = trim($slug, '_');
if ($slug !== '') $filename .= '_' . $slug;
}
return ['title' => $title, 'filename' => $filename . '.jpg'];
}
// ------------------------------------------------------------------
// Handle POST requests (image, video chunked, article)
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$fingerprint = $_POST['fingerprint'] ?? session_id();
$ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
// --- ARTICLE CREATION ---
if (isset($_POST['article_title']) && isset($_POST['article_content'])) {
$title = trim($_POST['article_title']);
$content = trim($_POST['article_content']);
$description = $_POST['article_description'] ?? '';
if ($title !== '' && $content !== '') {
$stmt = $db->prepare("INSERT INTO content (type, title, description, content, ip_address, fingerprint) VALUES ('article', :title, :desc, :content, :ip, :fp)");
$stmt->bindValue(':title', $title);
$stmt->bindValue(':desc', $description);
$stmt->bindValue(':content', $content);
$stmt->bindValue(':ip', $ip);
$stmt->bindValue(':fp', $fingerprint);
$stmt->execute();
header('Content-Type: application/json');
echo json_encode(['success' => true, 'post_id' => $db->lastInsertRowID()]);
} else {
http_response_code(400);
echo json_encode(['error' => 'Title and content required']);
}
exit;
}
// --- IMAGE OR VIDEO UPLOAD ---
if (!isset($_FILES['media'])) {
http_response_code(400);
echo json_encode(['error' => 'No file uploaded']);
exit;
}
$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'] ?? '';
$type = $_POST['type'] ?? '';
$isChunked = isset($_POST['chunk_index']) && isset($_POST['upload_id']) && isset($_POST['chunk_total']);
// --- CHUNKED VIDEO UPLOAD ---
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;
}
// Store metadata on first chunk
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));
}
// On last chunk, reassemble and save
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'];
$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 = __DIR__ . '/uploads/videos/';
$web_path = '/uploads/videos/';
$filename = uniqid('video_') . '.mp4';
$finalPath = $upload_dir . $filename;
rename($tempFinal, $finalPath);
$file_path = $web_path . $filename;
// Generate thumbnail if ffmpeg available
$thumbnail = null;
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) . " > /dev/null 2>&1 &";
exec($cmd);
}
$stmt = $db->prepare("INSERT INTO content (type, title, description, filename, file_path, thumbnail, latitude, longitude, location_name, ip_address, fingerprint)
VALUES ('video', :title, :desc, :filename, :file_path, :thumb, :lat, :lng, :loc, :ip, :fp)");
$stmt->bindValue(':title', $title);
$stmt->bindValue(':desc', $description);
$stmt->bindValue(':filename', $filename);
$stmt->bindValue(':file_path', $file_path);
$stmt->bindValue(':thumb', $thumbnail);
$stmt->bindValue(':lat', $latitude);
$stmt->bindValue(':lng', $longitude);
$stmt->bindValue(':loc', $location_name);
$stmt->bindValue(':ip', $ip);
$stmt->bindValue(':fp', $fingerprint);
$stmt->execute();
if ($latitude && $longitude) invalidateGeoCache();
// Cleanup
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 IMAGE UPLOAD (non-chunked) ---
if ($type !== 'image') {
http_response_code(400);
echo json_encode(['error' => 'Only image uploads supported without chunking']);
exit;
}
if ($_FILES['media']['error'] !== UPLOAD_ERR_OK) {
http_response_code(400);
echo json_encode(['error' => 'Upload failed']);
exit;
}
$upload_dir = __DIR__ . '/uploads/images/';
$web_path = '/uploads/images/';
$serverTime = time();
$titleData = generateMediaTitleAndFilename($location_name, $serverTime);
$title = $titleData['title'];
$filename = $titleData['filename'];
$finalPath = $upload_dir . $filename;
$counter = 1;
$originalFilename = $filename;
while (file_exists($finalPath)) {
$info = pathinfo($originalFilename);
$filename = $info['filename'] . '_' . $counter . '.jpg';
$finalPath = $upload_dir . $filename;
$counter++;
}
if (!move_uploaded_file($_FILES['media']['tmp_name'], $finalPath)) {
http_response_code(500);
echo json_encode(['error' => 'Failed to save image']);
exit;
}
$file_path = $web_path . $filename;
$stmt = $db->prepare("INSERT INTO content (type, title, description, filename, file_path, latitude, longitude, location_name, ip_address, fingerprint)
VALUES ('image', :title, :desc, :filename, :file_path, :lat, :lng, :loc, :ip, :fp)");
$stmt->bindValue(':title', $title);
$stmt->bindValue(':desc', $description);
$stmt->bindValue(':filename', $filename);
$stmt->bindValue(':file_path', $file_path);
$stmt->bindValue(':lat', $latitude);
$stmt->bindValue(':lng', $longitude);
$stmt->bindValue(':loc', $location_name);
$stmt->bindValue(':ip', $ip);
$stmt->bindValue(':fp', $fingerprint);
$stmt->execute();
if ($latitude && $longitude) invalidateGeoCache();
header('Content-Type: application/json');
echo json_encode(['success' => true, 'post_id' => $db->lastInsertRowID()]);
exit;
}
// ------------------------------------------------------------------
// Handle article view (GET parameter article=ID)
if (isset($_GET['article']) && is_numeric($_GET['article'])) {
$articleId = intval($_GET['article']);
$stmt = $db->prepare("SELECT * FROM content WHERE id = :id AND type = 'article'");
$stmt->bindValue(':id', $articleId, SQLITE3_INTEGER);
$result = $stmt->execute();
$article = $result->fetchArray(SQLITE3_ASSOC);
if (!$article) {
header('Location: ' . baseUrl() . '/');
exit;
}
$geoPoints = getCachedGeoPoints($db);
$totalDistanceKm = 0;
$totalDistanceMiles = 0;
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 -
prepare($countSql);
foreach ($params as $key => $val) $countStmt->bindValue($key, $val);
$total = $countStmt->execute()->fetchArray(SQLITE3_ASSOC)['total'];
$totalPages = ceil($total / $limit);
$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;
$geoPoints = getCachedGeoPoints($db);
$totalDistanceKm = 0;
$totalDistanceMiles = 0;
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;
}
// Generate a session-based fingerprint
if (!isset($_SESSION['fp'])) {
$_SESSION['fp'] = 'fp_' . bin2hex(random_bytes(16));
}
$fingerprint = $_SESSION['fp'];
?>
Fiveo1 Social
🔴 Recording...
← Back to Fiveo1