151 lines
3.6 KiB
PHP
151 lines
3.6 KiB
PHP
<?php
|
|
/**
|
|
* Stream Video Protetto
|
|
*
|
|
* Serve i video in modo protetto, verificando i permessi dell'utente
|
|
* e impedendo il download diretto
|
|
*/
|
|
|
|
require_once 'includes/config.php';
|
|
require_once 'includes/functions.php';
|
|
|
|
session_start();
|
|
|
|
// Ottieni parametri
|
|
$lesson_id = isset($_GET['lesson_id']) && is_numeric($_GET['lesson_id']) ? (int)$_GET['lesson_id'] : 0;
|
|
|
|
if (!$lesson_id) {
|
|
http_response_code(404);
|
|
exit('Video non trovato');
|
|
}
|
|
|
|
// Ottieni lezione
|
|
$lesson = get_lesson_by_id($lesson_id);
|
|
|
|
if (!$lesson || !$lesson['is_active']) {
|
|
http_response_code(404);
|
|
exit('Video non trovato');
|
|
}
|
|
|
|
// Verifica permessi
|
|
$can_view = false;
|
|
|
|
// Se è demo, tutti possono vedere
|
|
if ($lesson['is_demo']) {
|
|
$can_view = true;
|
|
} elseif (is_logged_in()) {
|
|
// Verifica se l'utente possiede la lezione
|
|
$can_view = user_owns_lesson($_SESSION['user_id'], $lesson_id);
|
|
}
|
|
|
|
if (!$can_view) {
|
|
http_response_code(403);
|
|
exit('Non hai i permessi per visualizzare questo video');
|
|
}
|
|
|
|
// Verifica che sia un video locale
|
|
if (empty($lesson['video_url']) || $lesson['video_platform'] !== 'local') {
|
|
http_response_code(404);
|
|
exit('Video non disponibile');
|
|
}
|
|
|
|
// Costruisci il percorso del file
|
|
$video_path = ltrim($lesson['video_url'], '/');
|
|
$file = __DIR__ . '/' . $video_path;
|
|
|
|
if (!file_exists($file)) {
|
|
http_response_code(404);
|
|
exit('File video non trovato');
|
|
}
|
|
|
|
// Ottieni informazioni sul file
|
|
$file_size = filesize($file);
|
|
$file_name = basename($file);
|
|
$extension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
|
|
|
|
// Determina il tipo MIME
|
|
$mime_types = [
|
|
'mp4' => 'video/mp4',
|
|
'webm' => 'video/webm',
|
|
'ogg' => 'video/ogg',
|
|
'mov' => 'video/quicktime'
|
|
];
|
|
$mime_type = $mime_types[$extension] ?? 'video/mp4';
|
|
|
|
// Gestisci Range Request per supportare seek nel video
|
|
$start = 0;
|
|
$end = $file_size - 1;
|
|
$length = $file_size;
|
|
|
|
if (isset($_SERVER['HTTP_RANGE'])) {
|
|
$range = $_SERVER['HTTP_RANGE'];
|
|
if (preg_match('/bytes=(\d+)-(\d*)/', $range, $matches)) {
|
|
$start = intval($matches[1]);
|
|
if (!empty($matches[2])) {
|
|
$end = intval($matches[2]);
|
|
}
|
|
$length = $end - $start + 1;
|
|
http_response_code(206); // Partial Content
|
|
header("Content-Range: bytes $start-$end/$file_size");
|
|
} else {
|
|
http_response_code(200);
|
|
}
|
|
} else {
|
|
http_response_code(200);
|
|
}
|
|
|
|
// Pulisci output buffer per evitare corruzione
|
|
if (ob_get_level()) {
|
|
ob_end_clean();
|
|
}
|
|
|
|
// Invia header
|
|
header("Content-Type: $mime_type");
|
|
header("Accept-Ranges: bytes");
|
|
header("Content-Length: $length");
|
|
|
|
// Header per impedire il download
|
|
header("Content-Disposition: inline; filename=\"video.{$extension}\"");
|
|
header("X-Content-Type-Options: nosniff");
|
|
|
|
// Header di cache per migliorare le performance
|
|
header("Cache-Control: public, max-age=3600");
|
|
header("Pragma: public");
|
|
|
|
// Disabilita compressione per lo streaming
|
|
header("Content-Encoding: none");
|
|
|
|
// Apri e leggi il file
|
|
$fp = fopen($file, 'rb');
|
|
if ($fp === false) {
|
|
http_response_code(500);
|
|
exit('Impossibile aprire il file video');
|
|
}
|
|
|
|
fseek($fp, $start);
|
|
|
|
// Buffer più grande per migliore performance
|
|
$buffer = 1024 * 256; // 256KB buffer
|
|
$bytes_sent = 0;
|
|
|
|
while (!feof($fp) && ($bytes_sent < $length) && connection_status() == 0) {
|
|
$bytes_to_read = min($buffer, $length - $bytes_sent);
|
|
$data = fread($fp, $bytes_to_read);
|
|
|
|
if ($data === false) {
|
|
break;
|
|
}
|
|
|
|
echo $data;
|
|
$bytes_sent += strlen($data);
|
|
|
|
// Forza l'invio dei dati al browser
|
|
if (ob_get_level() > 0) {
|
|
ob_flush();
|
|
}
|
|
flush();
|
|
}
|
|
|
|
fclose($fp);
|
|
exit;
|