diff --git a/app/ring_groups/ring_group_edit.php b/app/ring_groups/ring_group_edit.php index 99755816ba..995f88b29b 100644 --- a/app/ring_groups/ring_group_edit.php +++ b/app/ring_groups/ring_group_edit.php @@ -610,40 +610,35 @@ $document['title'] = $text['title-ring_group']; require_once "resources/header.php"; -//option to change select to text - if (if_group("superadmin")) { - echo "\n"; - echo "\n"; } -//show the content echo "
\n"; echo "
\n"; @@ -703,33 +698,102 @@ echo "\n"; echo "\n"; - echo "\n"; + echo "\n"; echo " ".$text['label-greeting']."\n"; echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; echo "\n"; - echo "\n"; echo " \n"; - foreach($sounds as $key => $value) { - echo "\n"; - $selected = false; + $found = false; + foreach ($sounds as $key => $value) { + echo "\n"; foreach ($value as $row) { if (!empty($ring_group_greeting) && $ring_group_greeting == $row["value"]) { - $selected = true; - echo " \n"; + $selected = "selected='selected'"; + if ($key == 'recordings') { + $playable_greeting = '../recordings/recordings.php?action=download&type=rec&filename='.$row["value"]; + } + else if ($key == 'sounds') { + $playable_greeting = '../switch/sounds.php?action=download&filename='.$row["value"]; + } + else { + $playable_greeting = false; + } + $found = true; } else { - echo " \n"; + unset($selected); } + echo " \n"; } echo "\n"; } - if (if_group("superadmin")) { - if (!$selected && !empty($ring_group_greeting)) { - echo " \n"; - } - unset($selected); + if (if_group("superadmin") && !empty($ring_group_greeting) && !$found) { + echo " \n"; } + unset($selected); echo " \n"; + if (if_group("superadmin")) { + echo ""; + unset($destination_id); + } + if ((permission_exists('recording_play') || permission_exists('recording_download')) && !empty($playable_greeting)) { + switch (pathinfo($playable_greeting, PATHINFO_EXTENSION)) { + case 'wav' : $audio_file_type = 'audio/wav'; break; + case 'mp3' : $audio_file_type = 'audio/mpeg'; break; + case 'ogg' : $audio_file_type = 'audio/ogg'; break; + } + } + echo ""; + echo button::create(['type'=>'button','title'=>$text['label-play'].' / '.$text['label-pause'],'icon'=>$_SESSION['theme']['button_icon_play'],'id'=>'recording_button_greeting','style'=>'display: '.(!empty($audio_file_type) ? 'inline' : 'none'),'onclick'=>"recording_play('greeting')"]); + unset($playable_greeting, $audio_file_type); echo "
\n"; echo $text['description-greeting']."\n"; echo "\n"; diff --git a/app/switch/sounds.php b/app/switch/sounds.php new file mode 100644 index 0000000000..a054c901f3 --- /dev/null +++ b/app/switch/sounds.php @@ -0,0 +1,191 @@ + + * Portions created by the Initial Developer are Copyright (C) 2023 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Mark J Crane + */ + +//set the max php execution time + ini_set('max_execution_time', 7200); + +//includes files + require_once dirname(__DIR__, 2) . "/resources/require.php"; + require_once "resources/check_auth.php"; + +//check the permission + if (permission_exists('recording_play') || permission_exists('recording_download')) { + //access granted + } + else { + echo "access denied"; + exit; + } + +//set additional variables + $action = $_REQUEST["action"] ?? ''; + +//download the sound + if ($action == "download") { + + //get first installed language (like en/us/callie) + $language_paths = glob($_SESSION["switch"]['sounds']['dir']."/*/*/*"); + foreach ($language_paths as $key => $path) { + $path = str_replace($_SESSION["switch"]['sounds']['dir'].'/', "", $path); + $path_array = explode('/', $path); + if (count($path_array) <> 3 || strlen($path_array[0]) <> 2 || strlen($path_array[1]) <> 2) { + unset($language_paths[$key]); + } + $language_paths[$key] = str_replace($_SESSION["switch"]['sounds']['dir']."/","",$language_paths[$key] ?? ''); + if (empty($language_paths[$key])) { + unset($language_paths[$key]); + } + } + $language_path = $language_paths[0]; + + //determine the path for sound file + $filename_parts = explode('/', str_replace('..', '', $_GET['filename'])); + if (!is_array($filename_parts) || @sizeof($filename_parts) != 2) { exit; } + $path = $_SESSION['switch']['sounds']['dir'].'/'.$language_path.'/'.$filename_parts[0].'/8000/'; + + //set sound filename + $sound_filename = $filename_parts[1]; + + //build full path + $full_sound_path = $path.$sound_filename; + + //send the headers and then the data stream + if (file_exists($full_sound_path)) { + + $fd = fopen($full_sound_path, "rb"); + switch (pathinfo($sound_filename, PATHINFO_EXTENSION)) { + case "wav" : header("Content-Type: audio/x-wav"); break; + case "mp3" : header("Content-Type: audio/mpeg"); break; + case "ogg" : header("Content-Type: audio/ogg"); break; + } + header('Content-Disposition: attachment; filename="'.$filename_parts[0].'_'.$filename_parts[1].'"'); + header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1 + header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past + + ob_clean(); + + //content-range + if (isset($_SERVER['HTTP_RANGE']) && (empty($_GET['t']) || $_GET['t'] != "bin")) { + range_download($full_sound_path); + } + + fpassthru($fd); + } + + } + +//define the download function (helps safari play audio sources) + 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 ($range == '-') { + // 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