Portions created by the Initial Developer are Copyright (C) 2008-2016 the Initial Developer. All Rights Reserved. Contributor(s): Mark J Crane James Rose */ //includes include "root.php"; require_once "resources/require.php"; require_once "resources/check_auth.php"; //add multi-lingual support $language = new text; $text = $language->get(); //set the max php execution time ini_set(max_execution_time,7200); //get the http get values and set them as php variables $order_by = $_GET["order_by"]; $order = $_GET["order"]; //set the default order if ($order_by == '') { $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'); if ($_GET['type'] = "rec") { //set the path for the directory $path = $_SESSION['switch']['recordings']['dir']."/".$_SESSION['domain_name']; //if from recordings, get recording details from db $recording_uuid = check_str($_GET['id']); //recordings if ($recording_uuid != '') { $sql = "select recording_filename, recording_base64 from v_recordings "; $sql .= "where domain_uuid = '".$domain_uuid."' "; $sql .= "and recording_uuid = '".$recording_uuid."' "; $prep_statement = $db->prepare(check_sql($sql)); $prep_statement->execute(); $result = $prep_statement->fetchAll(PDO::FETCH_ASSOC); if (count($result) > 0) { foreach($result as &$row) { $recording_filename = $row['recording_filename']; if ($_SESSION['recordings']['storage_type']['text'] == 'base64' && $row['recording_base64'] != '') { $recording_decoded = base64_decode($row['recording_base64']); file_put_contents($path.'/'.$recording_filename, $recording_decoded); } break; } } unset ($sql, $prep_statement, $result, $recording_decoded); } // build full path if(substr($recording_filename,0,1) == '/'){ $full_recording_path = $path . $recording_filename; } else { $full_recording_path = $path . '/' . $recording_filename; } //send the headers and then the data stream 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"); header("Content-Type: application/octet-stream"); header("Content-Type: application/download"); header("Content-Description: File Transfer"); } else { $file_ext = substr($recording_filename, -3); if ($file_ext == "wav") { header("Content-Type: audio/x-wav"); } if ($file_ext == "mp3") { header("Content-Type: audio/mpeg"); } } 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)); ob_clean(); fpassthru($fd); } //if base64, remove temp recording file if ($_SESSION['recordings']['storage_type']['text'] == 'base64' && $row['recording_base64'] != '') { @unlink($full_recording_path); } } exit; } //upload the recording if (permission_exists('recording_upload')) { if ($_POST['submit'] == $text['button-upload'] && $_POST['type'] == 'rec' && is_uploaded_file($_FILES['ulfile']['tmp_name'])) { //remove special characters $recording_filename = str_replace(" ", "_", $_FILES['ulfile']['name']); $recording_filename = str_replace("'", "", $recording_filename); //make sure the destination directory exists if (!is_dir($_SESSION['switch']['recordings']['dir'].'/'.$_SESSION['domain_name'])) { event_socket_mkdir($_SESSION['switch']['recordings']['dir'].'/'.$_SESSION['domain_name']); } //move the uploaded files move_uploaded_file($_FILES['ulfile']['tmp_name'], $_SESSION['switch']['recordings']['dir'].'/'.$_SESSION['domain_name'].'/'.$recording_filename); //set the message message::add($text['message-uploaded'].": ".htmlentities($recording_filename)); //set the file name to be inserted as the recording description $recording_description = base64_encode($_FILES['ulfile']['name']); header("Location: recordings.php?rd=".$recording_description); exit; } } //check the permission if (permission_exists('recording_view')) { //access granted } else { echo "access denied"; exit; } //get existing recordings $sql = "select recording_uuid, recording_filename, recording_base64 from v_recordings "; $sql .= "where domain_uuid = '".$domain_uuid."' "; $prep_statement = $db->prepare(check_sql($sql)); $prep_statement->execute(); $result = $prep_statement->fetchAll(PDO::FETCH_NAMED); foreach ($result as &$row) { $array_recordings[$row['recording_uuid']] = $row['recording_filename']; $array_base64_exists[$row['recording_uuid']] = ($row['recording_base64'] != '') ? true : false; //if not base64, convert back to local files and remove base64 from db if ($_SESSION['recordings']['storage_type']['text'] != 'base64' && $row['recording_base64'] != '') { if (!file_exists($_SESSION['switch']['recordings']['dir'].'/'.$_SESSION['domain_name'].'/'.$row['recording_filename'])) { $recording_decoded = base64_decode($row['recording_base64']); file_put_contents($_SESSION['switch']['recordings']['dir'].'/'.$_SESSION['domain_name'].'/'.$row['recording_filename'], $recording_decoded); $sql = "update v_recordings set recording_base64 = null where domain_uuid = '".$domain_uuid."' and recording_uuid = '".$row['recording_uuid']."' "; $db->exec(check_sql($sql)); unset($sql); } } } unset ($prep_statement); //add recordings to the database if (is_dir($_SESSION['switch']['recordings']['dir'].'/'.$_SESSION['domain_name'].'/')) { if ($dh = opendir($_SESSION['switch']['recordings']['dir'].'/'.$_SESSION['domain_name'].'/')) { while (($recording_filename = readdir($dh)) !== false) { if (filetype($_SESSION['switch']['recordings']['dir']."/".$_SESSION['domain_name']."/".$recording_filename) == "file") { if (!in_array($recording_filename, $array_recordings)) { //file not found in db, add it $recording_uuid = uuid(); $recording_name = ucwords(str_replace('_', ' ', pathinfo($recording_filename, PATHINFO_FILENAME))); $recording_description = check_str(base64_decode($_GET['rd'])); $sql = "insert into v_recordings "; $sql .= "("; $sql .= "domain_uuid, "; $sql .= "recording_uuid, "; $sql .= "recording_filename, "; $sql .= "recording_name, "; $sql .= "recording_description "; if ($_SESSION['recordings']['storage_type']['text'] == 'base64') { $sql .= ", recording_base64 "; } $sql .= ")"; $sql .= "values "; $sql .= "("; $sql .= "'".$domain_uuid."', "; $sql .= "'".$recording_uuid."', "; $sql .= "'".$recording_filename."', "; $sql .= "'".$recording_name."', "; $sql .= "'".$recording_description."' "; if ($_SESSION['recordings']['storage_type']['text'] == 'base64') { $recording_base64 = base64_encode(file_get_contents($_SESSION['switch']['recordings']['dir'].'/'.$_SESSION['domain_name'].'/'.$recording_filename)); $sql .= ", '".$recording_base64."' "; } $sql .= ")"; $db->exec(check_sql($sql)); unset($sql); } else { //file found in db, check if base64 present if ($_SESSION['recordings']['storage_type']['text'] == 'base64') { $found_recording_uuid = array_search($recording_filename, $array_recordings); if (!$array_base64_exists[$found_recording_uuid]) { $recording_base64 = base64_encode(file_get_contents($_SESSION['switch']['recordings']['dir'].'/'.$_SESSION['domain_name'].'/'.$recording_filename)); $sql = "update v_recordings set "; $sql .= "recording_base64 = '".$recording_base64."' "; $sql .= "where domain_uuid = '".$domain_uuid."' "; $sql .= "and recording_uuid = '".$found_recording_uuid."' "; $db->exec(check_sql($sql)); unset($sql); } } } //if base64, remove local file if ($_SESSION['recordings']['storage_type']['text'] == 'base64' && file_exists($_SESSION['switch']['recordings']['dir'].'/'.$_SESSION['domain_name'].'/'.$recording_filename)) { @unlink($_SESSION['switch']['recordings']['dir'].'/'.$_SESSION['domain_name'].'/'.$recording_filename); } } } //while closedir($dh); } //if } //if //add paging require_once "resources/paging.php"; //get total recordings from the database $sql = "select count(recording_uuid) as num_rows from v_recordings \n"; $sql = "where domain_uuid = '".$_SESSION['domain_uuid']."' "; $prep_statement = $db->prepare($sql); if ($prep_statement) { $prep_statement->execute(); $row = $prep_statement->fetch(PDO::FETCH_ASSOC); $num_rows = $row['num_rows']; } unset($prep_statement, $row); //prepare to page the results $rows_per_page = ($_SESSION['domain']['paging']['numeric'] != '') ? $_SESSION['domain']['paging']['numeric'] : 50; $param = "&order_by=".$order_by."&order=".$order; $page = $_GET['page']; if (strlen($page) == 0) { $page = 0; $_GET['page'] = 0; } list($paging_controls, $rows_per_page, $var_3) = paging($num_rows, $param, $rows_per_page); $offset = $rows_per_page * $page; //get the recordings from the database $sql = "select recording_uuid, domain_uuid, recording_filename, recording_name, recording_description from v_recordings "; $sql .= "where domain_uuid = '".$domain_uuid."' "; $sql .= "order by ".$order_by." ".$order." "; $sql .= "limit ".$rows_per_page." offset ".$offset." "; $prep_statement = $db->prepare(check_sql($sql)); $prep_statement->execute(); $recordings = $prep_statement->fetchAll(PDO::FETCH_NAMED); unset ($prep_statement, $sql); //set alternate row styles $c = 0; $row_style["0"] = "row_style0"; $row_style["1"] = "row_style1"; //include the header $document['title'] = $text['title']; require_once "resources/header.php"; //begin the content if (permission_exists('recording_upload')) { echo "\n"; echo " \n"; echo " \n"; echo " \n"; echo "
\n"; echo "
\n"; echo " \n"; echo " \n"; echo " \n"; echo "
"; echo "
"; } echo "".$text['title-recordings'].""; echo "

\n"; echo $text['description']."\n"; echo "

\n"; echo "\n"; echo "\n"; echo th_order_by('recording_name', $text['label-recording_name'], $order_by, $order); if ($_SESSION['recordings']['storage_type']['text'] != 'base64') { echo th_order_by('recording_filename', $text['label-file_name'], $order_by, $order); } echo "\n"; if ($_SESSION['recordings']['storage_type']['text'] != 'base64') { echo "\n"; echo "\n"; } echo th_order_by('recording_description', $text['label-description'], $order_by, $order); echo "\n"; echo "\n"; //calculate colspan for progress bar $colspan = 5; //max if ($_SESSION['recordings']['storage_type']['text'] == 'base64') { $colspan = $colspan - 2; } if (!(permission_exists('recording_edit') || permission_exists('recording_delete'))) { $colspan = $colspan - 1; } if (is_array($recordings)) { foreach($recordings as $row) { //playback progress bar if (permission_exists('recording_play')) { echo "\n"; } $tr_link = (permission_exists('recording_edit')) ? "href='recording_edit.php?id=".escape($row['recording_uuid'])."'" : null; echo "\n"; echo " \n"; if ($_SESSION['recordings']['storage_type']['text'] != 'base64') { echo " \n"; } if (permission_exists('recording_play') || permission_exists('recording_download')) { echo " \n"; } if ($_SESSION['recordings']['storage_type']['text'] != 'base64') { $file_name = $_SESSION['switch']['recordings']['dir'].'/'.$_SESSION['domain_name'].'/'.$row['recording_filename']; if (file_exists($file_name)) { $file_size = filesize($file_name); $file_size = byte_convert($file_size); $file_date = date("M d, Y H:i:s", filemtime($file_name)); } else { $file_size = ''; $file_date = ''; } echo " \n"; echo " \n"; } echo " \n"; echo " \n"; echo "\n"; $c = ($c) ? 0 : 1; } //end foreach unset($sql, $result, $row_count); } //end if results echo "
".$text['label-tools']."".$text['label-file-size']."".$text['label-uploaded']." 
".escape($row['recording_name'])."".str_replace('_', '_​', escape($row['recording_filename']))."".$file_size."".$file_date."".escape($row['recording_description'])." "; if (permission_exists('recording_edit')) { echo "$v_link_label_edit"; } if (permission_exists('recording_delete')) { echo "$v_link_label_delete"; } echo "
\n"; echo "
\n"; echo "
".$paging_controls."
\n"; echo "

\n"; //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); } ?>