diff --git a/app/recordings/recordings.php b/app/recordings/recordings.php index c4ee8cf7b0..9379c3844b 100644 --- a/app/recordings/recordings.php +++ b/app/recordings/recordings.php @@ -44,7 +44,7 @@ require_once "resources/check_auth.php"; $order_by = "recording_name"; $order = "asc"; } - + //download the recordings if ($_GET['a'] == "download" && (permission_exists('recording_play') || permission_exists('recording_download'))) { session_cache_limiter('public'); @@ -85,6 +85,11 @@ require_once "resources/check_auth.php"; } if (file_exists($full_recording_path)) { + //content-range + if (isset($_SERVER['HTTP_RANGE'])) { + range_download($full_recording_path); + } + $fd = fopen($full_recording_path, "rb"); if ($_GET['t'] == "bin") { header("Content-Type: application/force-download"); @@ -104,7 +109,7 @@ require_once "resources/check_auth.php"; header('Content-Disposition: attachment; filename="'.$recording_filename.'"'); header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1 header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past - header("Content-Length: " . filesize($full_recording_path)); + // header("Content-Length: " . filesize($full_recording_path)); ob_clean(); fpassthru($fd); } @@ -377,4 +382,101 @@ require_once "resources/check_auth.php"; //include the footer require_once "resources/footer.php"; + +function range_download($file) { + + $fp = @fopen($file, 'rb'); + + $size = filesize($file); // File size + $length = $size; // Content length + $start = 0; // Start byte + $end = $size - 1; // End byte + // Now that we've gotten so far without errors we send the accept range header + /* At the moment we only support single ranges. + * Multiple ranges requires some more work to ensure it works correctly + * and comply with the spesifications: http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2 + * + * Multirange support annouces itself with: + * header('Accept-Ranges: bytes'); + * + * Multirange content must be sent with multipart/byteranges mediatype, + * (mediatype = mimetype) + * as well as a boundry header to indicate the various chunks of data. + */ + header("Accept-Ranges: 0-$length"); + // header('Accept-Ranges: bytes'); + // multipart/byteranges + // http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2 + if (isset($_SERVER['HTTP_RANGE'])) { + + $c_start = $start; + $c_end = $end; + // Extract the range string + list(, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2); + // Make sure the client hasn't sent us a multibyte range + if (strpos($range, ',') !== false) { + + // (?) Shoud this be issued here, or should the first + // range be used? Or should the header be ignored and + // we output the whole content? + header('HTTP/1.1 416 Requested Range Not Satisfiable'); + header("Content-Range: bytes $start-$end/$size"); + // (?) Echo some info to the client? + exit; + } + // If the range starts with an '-' we start from the beginning + // If not, we forward the file pointer + // And make sure to get the end byte if spesified + if ($range0 == '-') { + + // The n-number of the last bytes is requested + $c_start = $size - substr($range, 1); + } + else { + + $range = explode('-', $range); + $c_start = $range[0]; + $c_end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $size; + } + /* Check the range and make sure it's treated according to the specs. + * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html + */ + // End bytes can not be larger than $end. + $c_end = ($c_end > $end) ? $end : $c_end; + // Validate the requested range and return an error if it's not correct. + if ($c_start > $c_end || $c_start > $size - 1 || $c_end >= $size) { + + header('HTTP/1.1 416 Requested Range Not Satisfiable'); + header("Content-Range: bytes $start-$end/$size"); + // (?) Echo some info to the client? + exit; + } + $start = $c_start; + $end = $c_end; + $length = $end - $start + 1; // Calculate new content length + fseek($fp, $start); + header('HTTP/1.1 206 Partial Content'); + } + // Notify the client the byte range we'll be outputting + header("Content-Range: bytes $start-$end/$size"); + header("Content-Length: $length"); + + // Start buffered download + $buffer = 1024 * 8; + while(!feof($fp) && ($p = ftell($fp)) <= $end) { + + if ($p + $buffer > $end) { + + // In case we're only outputtin a chunk, make sure we don't + // read past the length + $buffer = $end - $p + 1; + } + set_time_limit(0); // Reset time limit for big files + echo fread($fp, $buffer); + flush(); // Free up memory. Otherwise large files will trigger PHP's memory limit. + } + + fclose($fp); + +} ?> \ No newline at end of file diff --git a/themes/default/template.php b/themes/default/template.php index 32a494f771..93cf5e1cde 100644 --- a/themes/default/template.php +++ b/themes/default/template.php @@ -247,6 +247,16 @@ recording_audio.play(); document.getElementById('recording_button_'+recording_id).innerHTML = ""; audio_clock = setInterval(function () { update_progress(recording_id); }, 20); + + $("[id*=recording_button]").not("[id*=recording_button_"+recording_id+"]").html(""); + $("[id*=recording_progress_bar]").not("[id*=recording_progress_bar_"+recording_id+"]").css('display', 'none'); + + $('audio').each(function(){ + if ($(this).get(0) != recording_audio) { + $(this).get(0).pause(); // Stop playing + $(this).get(0).currentTime = 0; // Reset time + } + }); } else { recording_audio.pause();