From afaf31c3a25cde38e51283c090a94bb1709780b8 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Fri, 20 Dec 2024 11:07:05 -0700 Subject: [PATCH 01/32] Sanitize the caller ID name and number --- app/xml_cdr/resources/classes/xml_cdr.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/app/xml_cdr/resources/classes/xml_cdr.php b/app/xml_cdr/resources/classes/xml_cdr.php index 8a5e20bb98..6980a5d534 100644 --- a/app/xml_cdr/resources/classes/xml_cdr.php +++ b/app/xml_cdr/resources/classes/xml_cdr.php @@ -614,6 +614,10 @@ if (!class_exists('xml_cdr')) { $domain_name = urldecode($xml->variables->domain_name); $domain_uuid = urldecode($xml->variables->domain_uuid); + //sanitize the caller ID + $caller_id_name = preg_replace('#[^a-zA-Z 0-9\-\.]#', '', $caller_id_name); + $caller_id_number = preg_replace('#[^0-9\-]#', '', $caller_id_number); + //misc $this->array[$key][0]['ring_group_uuid'] = urldecode($xml->variables->ring_group_uuid); $this->array[$key][0]['xml_cdr_uuid'] = $uuid; @@ -1729,7 +1733,7 @@ if (!class_exists('xml_cdr')) { $sql .= "filter ( \n"; $sql .= " where c.extension_uuid = e.extension_uuid \n"; $sql .= " and status = 'answered' \n"; - if (!$this->include_internal) { + if (!$this->include_internal) { $sql .= "and (direction = 'inbound' or direction = 'outbound') \n"; } $sql .= ") \n"; @@ -1741,7 +1745,7 @@ if (!class_exists('xml_cdr')) { $sql .= " where c.extension_uuid = e.extension_uuid \n"; $sql .= " and status = 'missed' \n"; $sql .= " and (cc_side is null or cc_side != 'agent') \n"; - if (!$this->include_internal) { + if (!$this->include_internal) { $sql .= "and (direction = 'inbound' or direction = 'outbound') \n"; } $sql .= ") \n"; @@ -1752,7 +1756,7 @@ if (!class_exists('xml_cdr')) { $sql .= "filter ( \n"; $sql .= " where c.extension_uuid = e.extension_uuid \n"; $sql .= " and status = 'voicemail' \n"; - if (!$this->include_internal) { + if (!$this->include_internal) { $sql .= "and (direction = 'inbound' or direction = 'outbound') \n"; } $sql .= ") \n"; @@ -2252,5 +2256,3 @@ if (!class_exists('xml_cdr')) { } //class } - -?> From 2b22a15bf924aa6585ba577e567d55e37d546b90 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Sat, 21 Dec 2024 10:56:15 -0700 Subject: [PATCH 02/32] Update permission to hide hangup cause by default This call detail records permission was assigned to the superadmin group by default. The Status replaces it with a simpler message. The hangup cause status will remain as an option for those that want it. --- app/xml_cdr/app_config.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/xml_cdr/app_config.php b/app/xml_cdr/app_config.php index a15d65479a..98f5944920 100644 --- a/app/xml_cdr/app_config.php +++ b/app/xml_cdr/app_config.php @@ -214,7 +214,6 @@ $apps[$x]['permissions'][$y]['groups'][] = "superadmin"; $y++; $apps[$x]['permissions'][$y]['name'] = "xml_cdr_hangup_cause"; - $apps[$x]['permissions'][$y]['groups'][] = "superadmin"; $y++; $apps[$x]['permissions'][$y]['name'] = "xml_cdr_details"; $apps[$x]['permissions'][$y]['groups'][] = "superadmin"; @@ -231,7 +230,6 @@ $apps[$x]['permissions'][$y]['groups'][] = "superadmin"; $y++; $apps[$x]['permissions'][$y]['name'] = "xml_cdr_archive"; - //$apps[$x]['permissions'][$y]['groups'][] = "superadmin"; $y++; $apps[$x]['permissions'][$y]['name'] = "xml_cdr_statistics"; $apps[$x]['permissions'][$y]['groups'][] = "superadmin"; From eab081e25392b0b54bf2a4e9c86f9210f78be69c Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Sat, 21 Dec 2024 11:32:15 -0700 Subject: [PATCH 03/32] Fix log viewer overflow for log content using word wrap --- app/log_viewer/log_viewer.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/log_viewer/log_viewer.php b/app/log_viewer/log_viewer.php index 601f0f68dc..2ca3b01911 100644 --- a/app/log_viewer/log_viewer.php +++ b/app/log_viewer/log_viewer.php @@ -152,9 +152,9 @@ echo "
\n"; echo "\n"; - echo "\n"; + echo "
\n"; echo " \n"; - echo " \n"; $col_count++; } - echo "\n"; + echo "\n"; $col_count++; echo "\n"; @@ -489,7 +516,7 @@ echo th_order_by('recording_description', $text['label-description'], $order_by, $order, null, "class='hide-sm-dn pct-25'"); $col_count++; - if (permission_exists('recording_edit') && !empty($_SESSION['theme']['list_row_edit_button']['boolean']) && $_SESSION['theme']['list_row_edit_button']['boolean'] == 'true') { + if (permission_exists('recording_edit') && $theme_list_row_edit_button == true) { echo " \n"; } echo "\n"; @@ -513,8 +540,8 @@ echo " \n"; } if ($show == "all" && permission_exists('recording_all')) { - if (!empty($_SESSION['domains'][$row['domain_uuid']]['domain_name'])) { - $domain = $_SESSION['domains'][$row['domain_uuid']]['domain_name']; + if (!empty($domains[$row['domain_uuid']]['domain_name'])) { + $domain = $domains[$row['domain_uuid']]['domain_name']; } else { $domain = $text['label-global']; @@ -529,7 +556,7 @@ echo escape($row['recording_name']); } echo " \n"; - if (!empty($_SESSION['recordings']['storage_type']['text']) && $_SESSION['recordings']['storage_type']['text'] != 'base64') { + if ($recording_storage_type != 'base64') { echo " \n"; } if (permission_exists('recording_play') || permission_exists('recording_download')) { @@ -544,19 +571,19 @@ case "ogg" : $recording_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_'.escape($row['recording_uuid']),'onclick'=>"recording_play('".escape($row['recording_uuid'])."')"]); + echo button::create(['type'=>'button','title'=>$text['label-play'].' / '.$text['label-pause'],'icon'=>$theme_button_icon_play,'id'=>'recording_button_'.escape($row['recording_uuid']),'onclick'=>"recording_play('".escape($row['recording_uuid'])."')"]); } if (permission_exists('recording_download')) { - echo button::create(['type'=>'button','title'=>$text['label-download'],'icon'=>$_SESSION['theme']['button_icon_download'],'link'=>"recordings.php?action=download&type=rec&t=bin&id=".urlencode($row['recording_uuid'])]); + echo button::create(['type'=>'button','title'=>$text['label-download'],'icon'=>$theme_button_icon_download,'link'=>"recordings.php?action=download&type=rec&t=bin&id=".urlencode($row['recording_uuid'])]); } echo " \n"; } - if (!empty($_SESSION['recordings']['storage_type']['text']) && $_SESSION['recordings']['storage_type']['text'] == 'base64') { + if ($recording_storage_type == 'base64') { $file_size = byte_convert($row['recording_size']); echo " \n"; } else { - $file_name = $_SESSION['switch']['recordings']['dir'].'/'.$_SESSION['domains'][$row['domain_uuid']]['domain_name'].'/'.$row['recording_filename']; + $file_name = $switch_recordings.'/'.$domains[$row['domain_uuid']]['domain_name'].'/'.$row['recording_filename']; if (file_exists($file_name)) { $file_size = filesize($file_name); $file_size = byte_convert($file_size); @@ -566,18 +593,17 @@ unset($file_size, $file_date); } echo " \n"; - echo " \n"; } + echo " \n"; echo " \n"; - if (permission_exists('recording_edit') && !empty($_SESSION['theme']['list_row_edit_button']['boolean']) && $_SESSION['theme']['list_row_edit_button']['boolean'] == 'true') { + if (permission_exists('recording_edit') && $theme_list_row_edit_button == true) { echo " \n"; } echo "\n"; $x++; } - unset($recordings); } echo "
"; + echo " "; if (permission_exists('log_view')) { @@ -348,4 +348,4 @@ fclose($file); } -?> \ No newline at end of file +?> From aecf84c6b67f2b573587762c3f194298cb64f9ad Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Sat, 21 Dec 2024 14:35:26 -0700 Subject: [PATCH 04/32] Allow wrap on the action bar This is needed to fit better on tablets and mobile screens. --- themes/default/css.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/themes/default/css.php b/themes/default/css.php index 0be2dc295c..24a1760404 100644 --- a/themes/default/css.php +++ b/themes/default/css.php @@ -3259,7 +3259,9 @@ else { //default: white div.action_bar > div.actions { float: right; - white-space: nowrap; + white-space: normal; + overflow-wrap: break-word; + overflow: hidden; } div.action_bar > div.actions > div.unsaved { From fb719cf331293a3217495a632b83171d0792fd0c Mon Sep 17 00:00:00 2001 From: shing6326 <42719827+shing6326@users.noreply.github.com> Date: Sun, 22 Dec 2024 05:37:50 +0800 Subject: [PATCH 05/32] Add grandstream wp826 template (#7201) --- .../provision/grandstream/wp826/phonebook.xml | 151 +++++++++++++++++ .../provision/grandstream/wp826/{$mac}.xml | 156 ++++++++++++++++++ 2 files changed, 307 insertions(+) create mode 100644 resources/templates/provision/grandstream/wp826/phonebook.xml create mode 100644 resources/templates/provision/grandstream/wp826/{$mac}.xml diff --git a/resources/templates/provision/grandstream/wp826/phonebook.xml b/resources/templates/provision/grandstream/wp826/phonebook.xml new file mode 100644 index 0000000000..deb211d001 --- /dev/null +++ b/resources/templates/provision/grandstream/wp826/phonebook.xml @@ -0,0 +1,151 @@ + + + + + + 1 + Users + default ringtone + + + 2 + Groups + default ringtone + + + 3 + Extensions + system + + + {$start_id=0} + {foreach $contacts as $row} + {if $row.category == "users"} + + {$start_id++} + {if $row.contact_name_given != ""} + {if $row.contact_organization != ""} + {$row.contact_name_given} {$row.contact_name_family} + {$row.contact_name_given} {$row.contact_name_family} + {$row.contact_organization} + {else} + {$row.contact_name_given} + {$row.contact_name_family} + {/if} + {else} + {$row.effective_caller_id_name} + {/if} + + 0 + {foreach $row.numbers as $number} + {if $number.phone_number != ""} + {if $number.phone_label == "work"} + + {$number.phone_number} + 0 + + {/if} + {if $number.phone_label == "home"} + + {$number.phone_number} + 0 + + {/if} + {if $number.phone_label == "mobile"} + + {$number.phone_number} + 0 + + {/if} + {/if} + {/foreach} + 1 + 0 + + + + + {elseif $row.category == "groups"} + + {$start_id++} + {if $row.contact_name_given != ""} + {if $row.contact_organization != ""} + {$row.contact_name_given} {$row.contact_name_family} + {$row.contact_name_given} {$row.contact_name_family} + {$row.contact_organization} + {else} + {$row.contact_name_given} + {$row.contact_name_family} + {/if} + {else} + {$row.effective_caller_id_name} + {/if} + + + 0 + {foreach $row.numbers as $number} + {if $number.phone_number != ""} + {if $number.phone_label == "work"} + + {$number.phone_number} + 0 + + {/if} + {if $number.phone_label == "home"} + + {$number.phone_number} + 0 + + {/if} + {if $number.phone_label == "mobile"} + + {$number.phone_number} + 0 + + {/if} + {/if} + {/foreach} + 2 + 0 + + + + + {elseif $row.category == "extensions"} + + {$start_id++} + {if $row.contact_name_given != ""} + {if $row.contact_organization != ""} + {$row.contact_name_given} {$row.contact_name_family} + {$row.contact_name_given} {$row.contact_name_family} + {$row.contact_organization} + {else} + {$row.contact_name_given} + {$row.contact_name_family} + {/if} + {else} + {$row.effective_caller_id_name} + {/if} + + 0 + {if $row.phone_number != ""} + + {$row.phone_number} + 0 + + {else} + + {$row.phone_extension} + 0 + + {/if} + 3 + 0 + + + + + {/if} + {/foreach} + + diff --git a/resources/templates/provision/grandstream/wp826/{$mac}.xml b/resources/templates/provision/grandstream/wp826/{$mac}.xml new file mode 100644 index 0000000000..33ef8d4791 --- /dev/null +++ b/resources/templates/provision/grandstream/wp826/{$mac}.xml @@ -0,0 +1,156 @@ + + + + + {for $line=1 to 3} + {$row=$lines.$line} + + + {if filter_var($row.enabled, FILTER_VALIDATE_BOOLEAN)} + Yes + + + {$row.display_name} + + + {$row.server_address} + + + {$row.user_id} + + + {$row.auth_id} + + + {$row.password} + + {$row.display_name} + + {$voicemail_number} + + + PCMU + PCMA + G.722 + OPUS + OPUS + OPUS + OPUS + OPUS + + + {$grandstream_dial_plan} + {else} + No + {/if} + {/for} + + + + + + {if $grandstream_ipv_mode=='0'} + BothAndPreferIPv4 + {elseif $grandstream_ipv_mode=='1'} + BothAndPreferIPv6 + {elseif $grandstream_ipv_mode=='2'} + IPv4Only + {elseif $grandstream_ipv_mode=='3'} + IPv6Only + {else} + BothAndPreferIPv4 + {/if} + + + {if isset($grandstream_wifi_enable)} + + {if filter_var($grandstream_wifi_enable, FILTER_VALIDATE_BOOLEAN)}Yes{else}No{/if} + + {if isset($grandstream_wifi_essid)} + {$grandstream_wifi_essid} + + {$grandstream_wifi_password} + + + {$grandstream_wifi_hidden_security} + {/if} + + 0 + {/if} + + + {if isset($ntp_server_primary)} + {$ntp_server_primary} + {else} + pool.ntp.org + {/if} + + + + {if isset($ntp_server_secondary)} + {$ntp_server_secondary} + {else} + 2.us.pool.ntp.org + {/if} + + {if isset($grandstream_time_zone) } + {$grandstream_time_zone} + {elseif isset($grandstream_gxp_time_zone) } + {$grandstream_gxp_time_zone} + {/if} + + {if isset($admin_password)} + {$admin_password} + {/if} + + {if isset($device_password)} + {$device_password} + {/if} + + + {$mac|replace:'-':''|upper} + https://acsguestb.gdms.cloud + + + + {if isset($grandstream_firmware_upgrade_protocol) } + {if $grandstream_firmware_upgrade_protocol=="0"}TFTP{/if} + {if $grandstream_firmware_upgrade_protocol=="1"}HTTP{/if} + {if $grandstream_firmware_upgrade_protocol=="2"}HTTPS{/if} + {else} + HTTP + {/if} + + {if isset($grandstream_firmware_path) && isset($firmware_version)} + {$grandstream_firmware_path}/{$firmware_version} + {elseif isset($grandstream_firmware_path)} + {$grandstream_firmware_path} + {else} + {$domain_name}{$project_path}/app/provision/resources/firmware/ + {$http_auth_username} + {$http_auth_password} + {/if} + + HTTPS + + {if $grandstream_config_server_path=="none"} + + {elseif isset($grandstream_config_server_path)} + {$grandstream_config_server_path} + {else} + {$domain_name}{$project_path}/app/provision + {$http_auth_username} + {$http_auth_password} + {/if} + + + {if isset($grandstream_phonebook_download)} + {if $grandstream_phonebook_download=="0"}Disabled{elseif $grandstream_phonebook_download=="1"}Enabled Use TFTP{elseif $grandstream_phonebook_download=="2"}Enabled Use HTTP{elseif $grandstream_phonebook_download=="3"}Enabled Use HTTPS{/if} + {/if} + {$grandstream_phonebook_xml_server_path}{$mac} + {$grandstream_phonebook_download_interval} + {$http_auth_username} + {$http_auth_password} + + + From 67582a0f901f9166ffc7d8e635af00abc1ab7ca2 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Sun, 22 Dec 2024 10:13:18 -0700 Subject: [PATCH 06/32] Update presence.php --- app/switch/resources/classes/presence.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/switch/resources/classes/presence.php b/app/switch/resources/classes/presence.php index 014c04771e..b455c24a6d 100644 --- a/app/switch/resources/classes/presence.php +++ b/app/switch/resources/classes/presence.php @@ -100,7 +100,7 @@ if (!class_exists('presence')) { echo "active: false\n"; } //show active the presence - $presence = new permissions; + $presence = new presence; $array = $presence->show(); */ From 640b9f3184be00a84c524993c1a0fb8030901f82 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Sun, 22 Dec 2024 10:40:41 -0700 Subject: [PATCH 07/32] Update the contacts path Moved contacts from app to core --- core/contacts/contact_import.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/contacts/contact_import.php b/core/contacts/contact_import.php index 55984a97e8..59fa99964a 100644 --- a/core/contacts/contact_import.php +++ b/core/contacts/contact_import.php @@ -92,7 +92,7 @@ //get the schema $x = 0; - include "app/contacts/app_config.php"; + include "core/contacts/app_config.php"; $i = 0; foreach ($apps[0]['db'] as $table) { //get the table name and parent name @@ -149,7 +149,6 @@ } //create token - $object = new token; $token = $object->create($_SERVER['PHP_SELF']); //include header From b6e1a2f775a0872fc1b9316c67a32d5d4e2d7f1f Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Mon, 23 Dec 2024 12:15:38 -0700 Subject: [PATCH 08/32] Fix greeting when using phrases After saving a phrase for the greeting it would save but it wouldn't show the correct label. It would continue to play the phrase but show the UUID. --- app/ivr_menus/ivr_menu_edit.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/app/ivr_menus/ivr_menu_edit.php b/app/ivr_menus/ivr_menu_edit.php index 68b076b4c2..80f658a42f 100644 --- a/app/ivr_menus/ivr_menu_edit.php +++ b/app/ivr_menus/ivr_menu_edit.php @@ -873,6 +873,16 @@ unset($selected); } } + else if ($key == 'phrases') { + if (!empty($instance_value) && $instance_value == $row["value"]) { + $selected = "selected='selected'"; + $playable = ''; + $found = true; + } + else { + unset($selected); + } + } else { unset($selected); } @@ -946,6 +956,16 @@ unset($selected); } } + else if ($key == 'phrases') { + if (!empty($instance_value) && $instance_value == $row["value"]) { + $selected = "selected='selected'"; + $playable = ''; + $found = true; + } + else { + unset($selected); + } + } else { unset($selected); } From 6524cdcd0b02b5dc2966729f89629feaf6fdd509 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Mon, 23 Dec 2024 12:22:44 -0700 Subject: [PATCH 09/32] Fix greeting when using phrases After saving a phrase for the greeting it would save but it wouldn't show the correct label. It would continue to play the phrase but show the UUID. --- app/ring_groups/ring_group_edit.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/ring_groups/ring_group_edit.php b/app/ring_groups/ring_group_edit.php index 4da6c44602..647ebb4e18 100644 --- a/app/ring_groups/ring_group_edit.php +++ b/app/ring_groups/ring_group_edit.php @@ -849,6 +849,16 @@ unset($selected); } } + else if ($key == 'phrases') { + if (!empty($instance_value) && $instance_value == $row["value"]) { + $selected = "selected='selected'"; + $playable = ''; + $found = true; + } + else { + unset($selected); + } + } else { unset($selected); } From 803b8755b29ed9737949eb4c13801967d762b507 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Wed, 25 Dec 2024 22:08:10 -0700 Subject: [PATCH 10/32] Use the settings class and change date and time handling - Use the settings class - Fix the date and time --- app/recordings/recordings.php | 120 +++++++++++++++++++++------------- 1 file changed, 73 insertions(+), 47 deletions(-) diff --git a/app/recordings/recordings.php b/app/recordings/recordings.php index 3e73034d64..cc7b5d65ff 100644 --- a/app/recordings/recordings.php +++ b/app/recordings/recordings.php @@ -40,9 +40,33 @@ //initialize the database connection $database = database::new(); -//add the settings object - $settings = new settings(["domain_uuid" => $_SESSION['domain_uuid'], "user_uuid" => $_SESSION['user_uuid']]); - $speech_enabled = $settings->get('speech', 'enabled'); +//get the session settings + $domain_uuid = $_SESSION['domain_uuid']; + $domain_name = $_SESSION['domain_name']; + $user_uuid = $_SESSION['user_uuid']; + $domains = $_SESSION['domains']; + +//initialize the settings object + $settings = new settings(["domain_uuid" => $domain_uuid, "user_uuid" => $user_uuid]); + +//get the settings + $time_zone = $settings->get('domain', 'time_zone', date_default_timezone_get()); + $speech_enabled = $settings->get('speech', 'enabled', false); + $recording_storage_type = $settings->get('recordings','storage_type'); + $recording_password = $settings->get('recordings','recording_password'); + $domain_paging = $settings->get('domain','paging'); + $domain_paging = $settings->get('domain','paging', ); + $theme_button_icon_edit = $settings->get('theme','button_icon_edit'); + $theme_button_icon_add = $settings->get('theme','button_icon_add'); + $theme_button_icon_upload = $settings->get('theme','button_icon_upload'); + $theme_button_icon_cancel = $settings->get('theme','button_icon_cancel'); + $theme_button_icon_delete = $settings->get('theme','button_icon_delete'); + $theme_button_icon_all = $settings->get('theme','button_icon_all'); + $theme_button_icon_search = $settings->get('theme','button_icon_search'); + $theme_list_row_edit_button = $settings->get('theme','list_row_edit_button'); + $theme_button_icon_download = $settings->get('theme','button_icon_download'); + $theme_button_icon_play = $settings->get('theme','button_icon_play'); + $theme_button_icon_reset = $settings->get('theme','button_icon_reset'); //set additional variables $action = $_REQUEST["action"] ?? ''; @@ -53,7 +77,7 @@ if ($action == "download" && (permission_exists('recording_play') || permission_exists('recording_download'))) { if ($_GET['type'] == "rec") { //set the path for the directory - $path = $_SESSION['switch']['recordings']['dir']."/".$_SESSION['domain_name']; + $path = $switch_recordings."/".$domain_name; //if from recordings, get recording details from db $recording_uuid = $_GET['id']; //recordings @@ -67,7 +91,7 @@ $row = $database->select($sql, $parameters, 'row'); if (is_array($row) && @sizeof($row) != 0) { $recording_filename = $row['recording_filename']; - if (!empty($_SESSION['recordings']['storage_type']['text']) && $_SESSION['recordings']['storage_type']['text'] == 'base64' && !empty($row['recording_base64'])) { + if ($recording_storage_type == 'base64') { $recording_decoded = base64_decode($row['recording_base64']); file_put_contents($path.'/'.$recording_filename, $recording_decoded); } @@ -130,12 +154,12 @@ $recording_filename = str_replace("'", "", $recording_filename); //make sure the destination directory exists - if (!is_dir($_SESSION['switch']['recordings']['dir'].'/'.$_SESSION['domain_name'])) { - mkdir($_SESSION['switch']['recordings']['dir'].'/'.$_SESSION['domain_name'], 0770, false); + if (!is_dir($switch_recordings.'/'.$domain_name)) { + mkdir($switch_recordings.'/'.$domain_name, 0770, false); } //move the uploaded files - $result = move_uploaded_file($_FILES['file']['tmp_name'], $_SESSION['switch']['recordings']['dir'].'/'.$_SESSION['domain_name'].'/'.$recording_filename); + $result = move_uploaded_file($_FILES['file']['tmp_name'], $switch_recordings.'/'.$domain_name.'/'.$recording_filename); //clear the destinations session array if (isset($_SESSION['destinations']['array'])) { @@ -171,10 +195,10 @@ $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 (!empty($_SESSION['recordings']['storage_type']['text']) && $_SESSION['recordings']['storage_type']['text'] != 'base64' && $row['recording_base64'] != '') { - if (!file_exists($_SESSION['switch']['recordings']['dir'].'/'.$_SESSION['domain_name'].'/'.$row['recording_filename'])) { + if ($recording_storage_type != 'base64' && $row['recording_base64'] != '') { + if (!file_exists($switch_recordings.'/'.$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); + file_put_contents($switch_recordings.'/'.$domain_name.'/'.$row['recording_filename'], $recording_decoded); //build array $array['recordings'][0]['recording_uuid'] = $row['recording_uuid']; $array['recordings'][0]['domain_uuid'] = $domain_uuid; @@ -196,10 +220,10 @@ unset($sql, $parameters, $result, $row); //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'].'/')) { + if (is_dir($switch_recordings.'/'.$domain_name.'/')) { + if ($dh = opendir($switch_recordings.'/'.$domain_name.'/')) { while (($recording_filename = readdir($dh)) !== false) { - if (filetype($_SESSION['switch']['recordings']['dir']."/".$_SESSION['domain_name']."/".$recording_filename) == "file") { + if (filetype($switch_recordings."/".$domain_name."/".$recording_filename) == "file") { if (!is_array($array_recordings) || !in_array($recording_filename, $array_recordings)) { //file not found in db, add it @@ -212,8 +236,8 @@ $array['recordings'][0]['recording_filename'] = $recording_filename; $array['recordings'][0]['recording_name'] = $recording_name; $array['recordings'][0]['recording_description'] = $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)); + if ($recording_storage_type == 'base64') { + $recording_base64 = base64_encode(file_get_contents($switch_recordings.'/'.$domain_name.'/'.$recording_filename)); $array['recordings'][0]['recording_base64'] = $recording_base64; } //set temporary permissions @@ -229,10 +253,10 @@ } else { //file found in db, check if base64 present - if (!empty($_SESSION['recordings']['storage_type']['text']) && $_SESSION['recordings']['storage_type']['text'] == 'base64') { + if ($recording_storage_type == '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)); + $recording_base64 = base64_encode(file_get_contents($switch_recordings.'/'.$domain_name.'/'.$recording_filename)); //build array $array['recordings'][0]['domain_uuid'] = $domain_uuid; $array['recordings'][0]['recording_uuid'] = $found_recording_uuid; @@ -296,7 +320,7 @@ $sql .= "where true "; if ($show != "all" || !permission_exists('conference_center_all')) { $sql .= "and (domain_uuid = :domain_uuid or domain_uuid is null) "; - $parameters['domain_uuid'] = $_SESSION['domain_uuid']; + $parameters['domain_uuid'] = $domain_uuid; } if (!empty($search)) { $sql .= "and ("; @@ -309,7 +333,7 @@ $num_rows = $database->select($sql, $parameters ?? null, 'column'); //prepare to page the results - $rows_per_page = ($_SESSION['domain']['paging']['numeric'] != '') ? $_SESSION['domain']['paging']['numeric'] : 50; + $rows_per_page = ($domain_paging != '') ? $domain_paging : 50; $param = "&search=".urlencode($search); if ($show == "all" && permission_exists('recording_all')) { $param .= "&show=all"; @@ -321,7 +345,7 @@ $offset = $rows_per_page * $page; //get the file size - if (!empty($_SESSION['recordings']['storage_type']['text']) && $_SESSION['recordings']['storage_type']['text'] == 'base64') { + if ($recording_storage_type == 'base64') { switch ($db_type) { case 'pgsql': $sql_file_size = "length(decode(recording_base64,'base64')) as recording_size, "; break; case 'mysql': $sql_file_size = "length(from_base64(recording_base64)) as recording_size, "; break; @@ -331,12 +355,14 @@ //get the recordings from the database $sql = "select recording_uuid, domain_uuid, "; if (!empty($sql_file_size)) { $sql .= $sql_file_size; } + $sql .= "to_char(timezone(:time_zone, update_date), 'DD Mon YYYY') as date_formatted, \n"; + $sql .= "to_char(timezone(:time_zone, update_date), '".$sql_time_format."') as time_formatted, \n"; $sql .= "recording_name, recording_filename, recording_description "; $sql .= "from v_recordings "; $sql .= "where true "; if ($show != "all" || !permission_exists('conference_center_all')) { $sql .= "and (domain_uuid = :domain_uuid or domain_uuid is null) "; - $parameters['domain_uuid'] = $_SESSION['domain_uuid']; + $parameters['domain_uuid'] = $domain_uuid; } if (!empty($search)) { $sql .= "and ("; @@ -348,13 +374,14 @@ } $sql .= order_by($order_by, $order, 'recording_name', 'asc'); $sql .= limit_offset($rows_per_page, $offset); + $parameters['time_zone'] = $time_zone; $recordings = $database->select($sql, $parameters ?? null, 'all'); unset($sql, $parameters); //get current recordings password if (permission_exists('recording_password')) { - if (isset($_SESSION['recordings']['recording_password']['numeric'])) { - $recording_password = $_SESSION['recordings']['recording_password']['numeric']; + if (!empty($recording_password)) { + $recording_password = $recording_password; } else { $sql = " @@ -373,7 +400,7 @@ dd.dialplan_detail_type = 'set' and dd.dialplan_detail_data like 'pin_number=%' and dd.dialplan_detail_enabled = 'true' "; - $parameters['domain_uuid'] = $_SESSION['domain_uuid']; + $parameters['domain_uuid'] = $domain_uuid; $recording_password = $database->select($sql, $parameters, 'column'); unset($sql, $parameters); } @@ -402,7 +429,7 @@ echo "
".$text['title-recordings']."
".number_format($num_rows)."
\n"; echo "
\n"; if (permission_exists('recording_add') && $speech_enabled == 'true') { - echo button::create(['type'=>'button','label'=>$text['button-add'],'icon'=>$_SESSION['theme']['button_icon_add'],'id'=>'btn_add','link'=>'recording_edit.php']); + echo button::create(['type'=>'button','label'=>$text['button-add'],'icon'=>$theme_button_icon_add,'id'=>'btn_add','link'=>'recording_edit.php']); } if (permission_exists('recording_upload')) { echo "
\n"; @@ -410,17 +437,17 @@ echo "\n"; echo "\n"; - echo button::create(['type'=>'button','label'=>$text['button-upload'],'icon'=>$_SESSION['theme']['button_icon_add'],'id'=>'btn_upload','onclick'=>"$(this).fadeOut(250, function(){ $('span#form_upload').fadeIn(250); document.getElementById('ulfile').click(); });"]); + echo button::create(['type'=>'button','label'=>$text['button-upload'],'icon'=>$theme_button_icon_add,'id'=>'btn_upload','onclick'=>"$(this).fadeOut(250, function(){ $('span#form_upload').fadeIn(250); document.getElementById('ulfile').click(); });"]); echo "\n"; echo "
"; } if (permission_exists('recording_delete') && $recordings) { - echo button::create(['type'=>'button','label'=>$text['button-delete'],'icon'=>$_SESSION['theme']['button_icon_delete'],'id'=>'btn_delete','name'=>'btn_delete','style'=>'display: none;','onclick'=>"modal_open('modal-delete','btn_delete');"]); + echo button::create(['type'=>'button','label'=>$text['button-delete'],'icon'=>$theme_button_icon_delete,'id'=>'btn_delete','name'=>'btn_delete','style'=>'display: none;','onclick'=>"modal_open('modal-delete','btn_delete');"]); } echo "
".$text['label-tools']."".(!empty($_SESSION['recordings']['storage_type']['text']) && $_SESSION['recordings']['storage_type']['text'] == 'base64' ? $text['label-size'] : $text['label-file_size'])."".($recording_storage_type == 'base64' ? $text['label-size'] : $text['label-file_size'])."".$text['label-date']." 
".str_replace('_', '_​', escape($row['recording_filename']))."".$file_size."".($file_size ?? '')."".($file_date ?? '')."".($row['date_formatted'] ?? '')." ".($row['time_formatted'] ?? '')."".escape($row['recording_description'])." "; - echo button::create(['type'=>'button','title'=>$text['button-edit'],'icon'=>$_SESSION['theme']['button_icon_edit'],'link'=>$list_row_url]); + echo button::create(['type'=>'button','title'=>$text['button-edit'],'icon'=>$theme_button_icon_edit,'link'=>$list_row_url]); echo "
\n"; From ff95ada636eca8dec4b05025dccd663f46d00df0 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Thu, 26 Dec 2024 10:57:45 -0700 Subject: [PATCH 11/32] Fix the duration by use the created_epoch Also used the settings class --- app/calls_active/calls_active_inc.php | 51 ++++++++++++++++----------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/app/calls_active/calls_active_inc.php b/app/calls_active/calls_active_inc.php index 567951aa52..e7680d1cd3 100644 --- a/app/calls_active/calls_active_inc.php +++ b/app/calls_active/calls_active_inc.php @@ -37,6 +37,21 @@ exit; } +//get the session settings + $domain_uuid = $_SESSION['domain_uuid']; + $domain_name = $_SESSION['domain_name']; + $user_uuid = $_SESSION['user_uuid']; + $gateways = $_SESSION['gateways']; + $user = $_SESSION['user']; + +//initialize the settings object + $settings = new settings(["domain_uuid" => $domain_uuid, "user_uuid" => $user_uuid]); + +//get the settings + $template_name = $settings->get('domain', 'template', 'default'); + $theme_button_icon_back = $settings->get('theme', 'button_icon_back', ''); + $theme_button_icon_all = $settings->get('theme', 'button_icon_all', ''); + //add multi-lingual support $language = new text; $text = $language->get(); @@ -46,7 +61,7 @@ if ($show != "all") { $show = ''; } //include theme config for button images - include_once("themes/".$_SESSION['domain']['template']['name']."/config.php"); + include_once("themes/".$template_name."/config.php"); //set the command $switch_cmd = 'show channels as json'; @@ -80,7 +95,7 @@ if (($show == 'all' && permission_exists('call_active_all'))) { $rows[] = $row; } - elseif ($row['domain_name'] == $_SESSION['domain_name']) { + elseif ($row['domain_name'] == $domain_name) { $rows[] = $row; } } @@ -131,20 +146,20 @@ echo "
".$text['title']."
".number_format($num_rows)."
\n"; echo "
\n"; echo " ".button::create(['type'=>'button','title'=>$text['label-refresh_pause'],'icon'=>'sync-alt fa-spin','onclick'=>'refresh_stop()']).""; - if (permission_exists('call_active_eavesdrop') && !empty($_SESSION['user']['extensions'])) { - if (sizeof($_SESSION['user']['extensions']) > 1) { - echo " \n"; + if (permission_exists('call_active_eavesdrop') && !empty($user['extensions'])) { + if (sizeof($user['extensions']) > 1) { + echo " \n"; echo " \n"; echo " \n"; } - else if (sizeof($_SESSION['user']['extensions']) == 1) { - echo " \n"; + else if (sizeof($user['extensions']) == 1) { + echo " \n"; } } if (permission_exists('call_active_hangup') && $rows) { @@ -152,10 +167,10 @@ } if (permission_exists('call_active_all')) { if ($show == "all") { - echo button::create(['type'=>'button','label'=>$text['button-back'],'icon'=>$_SESSION['theme']['button_icon_back'],'link'=>'calls_active.php','onmouseover'=>'refresh_stop()','onmouseout'=>'refresh_start()']); + echo button::create(['type'=>'button','label'=>$text['button-back'],'icon'=>$theme_button_icon_back,'link'=>'calls_active.php','onmouseover'=>'refresh_stop()','onmouseout'=>'refresh_start()']); } else { - echo button::create(['type'=>'button','label'=>$text['button-show_all'],'icon'=>$_SESSION['theme']['button_icon_all'],'link'=>'calls_active.php?show=all','onmouseover'=>'refresh_stop()','onmouseout'=>'refresh_start()']); + echo button::create(['type'=>'button','label'=>$text['button-show_all'],'icon'=>$theme_button_icon_all,'link'=>'calls_active.php?show=all','onmouseover'=>'refresh_stop()','onmouseout'=>'refresh_start()']); } } echo "
\n"; @@ -224,20 +239,14 @@ $cid_num = str_replace("+", "", $cid_num); //replace gateway uuid with name - if (is_array($_SESSION['gateways']) && sizeof($_SESSION['gateways']) > 0) { - foreach ($_SESSION['gateways'] as $gateway_uuid => $gateway_name) { + if (is_array($gateways) && sizeof($gateways) > 0) { + foreach ($gateways as $gateway_uuid => $gateway_name) { $application_data = str_replace($gateway_uuid, $gateway_name, $application_data); } } - //convert $created to a UNIX timestamp - $created_timestamp = strtotime($created); - - //get the current timestamp - $now = time(); - //calculate elapsed seconds - $elapsed_seconds = $now - $created_timestamp; + $elapsed_seconds = time() - $created_epoch; //convert seconds to hours, minutes, and seconds $hours = floor($elapsed_seconds / 3600); @@ -276,7 +285,7 @@ if (permission_exists('call_active_eavesdrop') || permission_exists('call_active_hangup')) { echo " \n"; //eavesdrop - if (permission_exists('call_active_eavesdrop') && $callstate == 'ACTIVE' && !empty($_SESSION['user']['extensions']) && !in_array($cid_num, $_SESSION['user']['extensions'])) { + if (permission_exists('call_active_eavesdrop') && $callstate == 'ACTIVE' && !empty($user['extensions']) && !in_array($cid_num, $user['extensions'])) { echo button::create(['type'=>'button','label'=>$text['label-eavesdrop'],'icon'=>'headphones','collapse'=>'hide-lg-dn','onclick'=>"if (confirm('".$text['confirm-eavesdrop']."')) { eavesdrop_call('".escape($cid_num)."','".escape($uuid)."'); } else { this.blur(); return false; }",'onmouseover'=>'refresh_stop()','onmouseout'=>'refresh_start()']); } //hangup From 9203fa0ed96310ba6be84bc84af054bad599690d Mon Sep 17 00:00:00 2001 From: chansizzle <14916599+chansizzle@users.noreply.github.com> Date: Fri, 27 Dec 2024 09:55:26 -0700 Subject: [PATCH 12/32] update cpm_ans to be cpm_answered (#7204) The sql aliases the calculation as cpm_answered. Without this change the CDR Statistics Call Per Minute will always be zero. --- app/xml_cdr/xml_cdr_statistics.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/xml_cdr/xml_cdr_statistics.php b/app/xml_cdr/xml_cdr_statistics.php index 9a688a85cd..37b7247804 100644 --- a/app/xml_cdr/xml_cdr_statistics.php +++ b/app/xml_cdr/xml_cdr_statistics.php @@ -329,7 +329,7 @@ } echo " ".escape($row['volume'])." \n"; echo " ".escape(round($row['minutes'] ?? 0, 2))." \n"; - echo " ".escape(round($row['avg_min'] ?? 0, 2))." / ".escape(round($row['cpm_ans'] ?? 0, 2))." \n"; + echo " ".escape(round($row['avg_min'] ?? 0, 2))." / ".escape(round($row['cpm_answered'] ?? 0, 2))." \n"; echo " ".escape($row['missed'] ?? '')." \n"; echo " ".escape(round($row['asr'] ?? 0, 2))." \n"; echo " ".escape(round($row['aloc'] ?? 0, 2))." \n"; From 5ace1902e3f208520049c084a4aa6be49d3453db Mon Sep 17 00:00:00 2001 From: fusionate Date: Mon, 30 Dec 2024 12:33:54 -0700 Subject: [PATCH 13/32] Recordings: Restore audio playback. --- app/recordings/recordings.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/recordings/recordings.php b/app/recordings/recordings.php index cc7b5d65ff..cf82f67db4 100644 --- a/app/recordings/recordings.php +++ b/app/recordings/recordings.php @@ -50,6 +50,7 @@ $settings = new settings(["domain_uuid" => $domain_uuid, "user_uuid" => $user_uuid]); //get the settings + $switch_recordings = $settings->get('switch', 'recordings'); $time_zone = $settings->get('domain', 'time_zone', date_default_timezone_get()); $speech_enabled = $settings->get('speech', 'enabled', false); $recording_storage_type = $settings->get('recordings','storage_type'); From 76af096f52c24584dad4d200b2ef8a7c393dd31e Mon Sep 17 00:00:00 2001 From: frytimo Date: Wed, 1 Jan 2025 13:32:12 -0400 Subject: [PATCH 14/32] xml_cdr catch edge case of failed import when no start stamp is present (#7207) * xml_cdr catch edge case of failed import when no start stamp is present * xml_cdr catch edge case of failed import when no start stamp is present --- app/xml_cdr/resources/classes/xml_cdr.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/app/xml_cdr/resources/classes/xml_cdr.php b/app/xml_cdr/resources/classes/xml_cdr.php index 6980a5d534..866095de43 100644 --- a/app/xml_cdr/resources/classes/xml_cdr.php +++ b/app/xml_cdr/resources/classes/xml_cdr.php @@ -638,6 +638,17 @@ if (!class_exists('xml_cdr')) { $this->array[$key][0]['status'] = $status; //time + //catch invalid call detail records + if (empty($xml->variables->start_epoch)) { + //empty the array so it can't save + $this->array = null; + + //move the file to the failed location + $this->move_to_failed($this->file); + + //stop processing + return; + } $start_epoch = urldecode($xml->variables->start_epoch); $this->array[$key][0]['start_epoch'] = $start_epoch; $this->array[$key][0]['start_stamp'] = is_numeric((int)$start_epoch) ? date('c', $start_epoch) : null; @@ -1486,6 +1497,15 @@ if (!class_exists('xml_cdr')) { } } + public function moved_to_failed($failed_file) { + $xml_cdr_dir = $this->setting->get('switch', 'log', '/var/log/freeswitch').'/xml_cdr'; + if (!file_exists($xml_cdr_dir.'/failed')) { + if (!mkdir($xml_cdr_dir.'/failed', 0660, true)) { + die('Failed to create '.$xml_cdr_dir.'/failed'); + } + } + rename($xml_cdr_dir.'/'.$failed_file, $xml_cdr_dir.'/failed/'.$failed_file); + } /** * get xml from the filesystem and save it to the database From 5c9c872c99178d5a02e7700462f3a44406f7ba6b Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Wed, 1 Jan 2025 11:26:44 -0700 Subject: [PATCH 15/32] Show newest emails first --- app/email_queue/resources/service/email_queue.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/email_queue/resources/service/email_queue.php b/app/email_queue/resources/service/email_queue.php index 06f2c3d6c0..f12a023502 100644 --- a/app/email_queue/resources/service/email_queue.php +++ b/app/email_queue/resources/service/email_queue.php @@ -141,7 +141,7 @@ $sql = "select * from v_email_queue "; $sql .= "where (email_status = 'waiting' or email_status = 'trying') "; $sql .= "and hostname = :hostname "; - $sql .= "order by domain_uuid asc "; + $sql .= "order by domain_uuid, email_date desc "; $sql .= "limit :limit "; $parameters['hostname'] = $hostname; $parameters['limit'] = $email_queue_limit; From eb7645772ae932e430d27031339f127ab8855cbc Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Fri, 3 Jan 2025 09:00:17 -0700 Subject: [PATCH 16/32] Update the context for the operator Use the domain_name as the context. --- .../resources/switch/conf/dialplan/480_operator.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/dialplans/resources/switch/conf/dialplan/480_operator.xml b/app/dialplans/resources/switch/conf/dialplan/480_operator.xml index 77cc9b8faa..cc8cac8650 100644 --- a/app/dialplans/resources/switch/conf/dialplan/480_operator.xml +++ b/app/dialplans/resources/switch/conf/dialplan/480_operator.xml @@ -1,9 +1,9 @@ - - - - - + + + + + From 5e8271ecc69d822318f2456ed851980e700db63b Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Fri, 3 Jan 2025 09:01:03 -0700 Subject: [PATCH 17/32] Use the domain_name as the context --- .../resources/switch/conf/dialplan/485_operator-forward.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/dialplans/resources/switch/conf/dialplan/485_operator-forward.xml b/app/dialplans/resources/switch/conf/dialplan/485_operator-forward.xml index 26aa9dbad8..7eeecdadf8 100644 --- a/app/dialplans/resources/switch/conf/dialplan/485_operator-forward.xml +++ b/app/dialplans/resources/switch/conf/dialplan/485_operator-forward.xml @@ -1,6 +1,6 @@ - + From 2aae8635db65eb35b8422256ddf04d4a3d27140a Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Fri, 3 Jan 2025 14:41:08 -0700 Subject: [PATCH 18/32] Fix the device line default values and use the settings class --- app/devices/device_edit.php | 170 +++++++++++++++++------------------- 1 file changed, 82 insertions(+), 88 deletions(-) diff --git a/app/devices/device_edit.php b/app/devices/device_edit.php index 9b54b6535f..4a02b8762f 100644 --- a/app/devices/device_edit.php +++ b/app/devices/device_edit.php @@ -44,8 +44,9 @@ $device_firmware_version = ''; $device_template =''; -//get the domain uuid +//get the domain values $domain_uuid = $_SESSION['domain_uuid'] ?? ''; + $domain_name = $_SESSION['domain_name'] ?? ''; //initialize the database object $database = database::new(); @@ -64,12 +65,12 @@ //get the total device count from the database, check the limit, if defined if ($action == 'add') { - if (!empty($_SESSION['limit']['devices']['numeric']) && $_SESSION['limit']['devices']['numeric']) { + if (!empty($settings->get('limit', 'devices', ''))) { $sql = "select count(*) from v_devices where domain_uuid = :domain_uuid "; - $parameters['domain_uuid'] = $_SESSION['domain_uuid']; + $parameters['domain_uuid'] = $domain_uuid; $total_devices = $database->select($sql, $parameters, 'column'); - if ($total_devices >= $_SESSION['limit']['devices']['numeric']) { - message::add($text['message-maximum_devices'].' '.$_SESSION['limit']['devices']['numeric'], 'negative'); + if ($total_devices >= $settings->get('limit', 'devices', '')) { + message::add($text['message-maximum_devices'].' '.$settings->get('limit', 'devices', ''), 'negative'); header('Location: devices.php'); exit; } @@ -228,14 +229,14 @@ $sql .= " and d1.device_uuid <> :device_uuid "; } $parameters['device_address'] = $device_address; - $domain_name = $database->select($sql, $parameters, 'column'); - if ($domain_name != '') { - $message = $text['message-duplicate'].(if_group("superadmin") && $_SESSION["domain_name"] != $domain_name ? ": ".$domain_name : null); + $device_domain_name = $database->select($sql, $parameters, 'column'); + if ($device_domain_name != '') { + $message = $text['message-duplicate'].($device_domain_name != $domain_name ? ": ".$device_domain_name : null); message::add($message,'negative'); header('Location: devices.php'); exit; } - unset($sql, $parameters, $domain_name); + unset($sql, $parameters, $device_domain_name); } //add or update the database @@ -304,6 +305,7 @@ $device_line_uuid = uuid(); $new_line = true; } + $array['devices'][0]['device_lines'][$y]['domain_uuid'] = $domain_uuid; $array['devices'][0]['device_lines'][$y]['device_uuid'] = $device_uuid; $array['devices'][0]['device_lines'][$y]['device_line_uuid'] = $device_line_uuid; @@ -311,23 +313,23 @@ $array['devices'][0]['device_lines'][$y]['server_address'] = $row["server_address"]; if (permission_exists('device_line_outbound_proxy_primary')) { $array['devices'][0]['device_lines'][$y]['outbound_proxy_primary'] = $row["outbound_proxy_primary"]; - } else if ($new_line && isset($_SESSION['provision']['outbound_proxy_primary'])) { - $array['devices'][0]['device_lines'][$y]['outbound_proxy_primary'] = $_SESSION['provision']['outbound_proxy_primary']['text']; + } else if ($new_line && !empty($settings->get('provision', 'outbound_proxy_primary'))) { + $array['devices'][0]['device_lines'][$y]['outbound_proxy_primary'] = $settings->get('provision', 'outbound_proxy_primary', ''); } if (permission_exists('device_line_outbound_proxy_secondary')) { $array['devices'][0]['device_lines'][$y]['outbound_proxy_secondary'] = $row["outbound_proxy_secondary"]; - } else if ($new_line && isset($_SESSION['provision']['outbound_proxy_secondary'])) { - $array['devices'][0]['device_lines'][$y]['outbound_proxy_secondary'] = $_SESSION['provision']['outbound_proxy_secondary']['text']; + } else if ($new_line && !empty($settings->get('provision', 'outbound_proxy_secondary'))) { + $array['devices'][0]['device_lines'][$y]['outbound_proxy_secondary'] = $settings->get('provision', 'outbound_proxy_secondary', ''); } if (permission_exists('device_line_server_address_primary')) { $array['devices'][0]['device_lines'][$y]['server_address_primary'] = $row["server_address_primary"]; - } else if ($new_line && isset($_SESSION['provision']['server_address_primary'])) { - $array['devices'][0]['device_lines'][$y]['server_address_primary'] = $_SESSION['provision']['server_address_primary']['text']; + } else if ($new_line && !empty($settings->get('provision', 'server_address_primary'))) { + $array['devices'][0]['device_lines'][$y]['server_address_primary'] = $settings->get('provision', 'server_address_primary', ''); } if (permission_exists('device_line_server_address_secondary')) { $array['devices'][0]['device_lines'][$y]['server_address_secondary'] = $row["server_address_secondary"]; - } else if ($new_line && isset($_SESSION['provision']['server_address_secondary'])) { - $array['devices'][0]['device_lines'][$y]['server_address_secondary'] = $_SESSION['provision']['server_address_secondary']['text']; + } else if ($new_line && !empty($settings->get('provision', 'server_address_secondary'))) { + $array['devices'][0]['device_lines'][$y]['server_address_secondary'] = $settings->get('provision', 'server_address_secondary', ''); } if (permission_exists('device_line_label')) { $array['devices'][0]['device_lines'][$y]['label'] = $row["label"]; @@ -351,7 +353,7 @@ } else { if ($action == "add") { - $array['devices'][0]['device_lines'][$y]['sip_port'] = $_SESSION['provision']['line_sip_port']['numeric']; + $array['devices'][0]['device_lines'][$y]['sip_port'] = $settings->get('provision', 'line_sip_port', '5060'); } } if (permission_exists('device_line_transport')) { @@ -359,7 +361,7 @@ } else { if ($action == "add") { - $array['devices'][0]['device_lines'][$y]['sip_transport'] = $_SESSION['provision']['line_sip_transport']['text']; + $array['devices'][0]['device_lines'][$y]['sip_transport'] = $settings->get('provision', 'line_sip_transport', 'tcp'); } } if (permission_exists('device_line_register_expires')) { @@ -367,7 +369,7 @@ } else { if ($action == "add") { - $array['devices'][0]['device_lines'][$y]['register_expires'] = $_SESSION['provision']['line_register_expires']['numeric']; + $array['devices'][0]['device_lines'][$y]['register_expires'] = $settings->get('provision', 'line_register_expires', '120'); } } $y++; @@ -480,7 +482,7 @@ } //write the provision files - if (!empty($_SESSION['provision']['path']['text'])) { + if (!empty($settings->get('provision', 'path'))) { $prov = new provision(['settings' => $settings]); $prov->domain_uuid = $domain_uuid; $response = $prov->write(); @@ -509,7 +511,6 @@ $sql = "select * from v_devices "; $sql .= "where device_uuid = :device_uuid "; $parameters['device_uuid'] = $device_uuid; - $row = $database->select($sql, $parameters, 'row'); if (is_array($row) && @sizeof($row) != 0) { $device_address = $row["device_address"]; @@ -533,6 +534,14 @@ unset($sql, $parameters, $row); } +//get device lines + $sql = "select * "; + $sql .= "from v_domains "; + $sql .= "where domain_enabled = true "; + $sql .= "order by domain_name asc "; + $domains = $database->select($sql, null, 'all'); + unset($sql, $parameters); + //set the defaults if (empty($device_enabled)) { $device_enabled = 'true'; } @@ -563,20 +572,22 @@ } //get device lines - $sql = "select * from v_device_lines "; + $sql = "select l.*, d.domain_name "; + $sql .= "from v_device_lines as l, v_domains as d "; $sql .= "where device_uuid = :device_uuid "; + $sql .= "and l.domain_uuid = d.domain_uuid "; $sql .= "order by cast(line_number as int) asc "; $parameters['device_uuid'] = $device_uuid ?? null; - $device_lines = $database->select($sql, $parameters, 'all'); unset($sql, $parameters); +//set the new line defaults $device_lines[$x]['line_number'] = ''; $device_lines[$x]['server_address'] = ''; - $device_lines[$x]['outbound_proxy_primary'] = $_SESSION['provision']['outbound_proxy_primary']['text'] ?? null; - $device_lines[$x]['outbound_proxy_secondary'] = $_SESSION['provision']['outbound_proxy_secondary']['text'] ?? null; - $device_lines[$x]['server_address_primary'] = $_SESSION['provision']['server_address_primary']['text'] ?? null; - $device_lines[$x]['server_address_secondary'] = $_SESSION['provision']['server_address_secondary']['text'] ?? null; + $device_lines[$x]['outbound_proxy_primary'] = $settings->get('provision', 'outbound_proxy_primary', null); + $device_lines[$x]['outbound_proxy_secondary'] = $settings->get('provision', 'outbound_proxy_secondary', null); + $device_lines[$x]['server_address_primary'] = $settings->get('provision', 'server_address_primary', null); + $device_lines[$x]['server_address_secondary'] = $settings->get('provision', 'server_address_secondary', null); $device_lines[$x]['label'] = ''; $device_lines[$x]['display_name'] = ''; $device_lines[$x]['user_id'] = ''; @@ -584,9 +595,9 @@ $device_lines[$x]['password'] = ''; $device_lines[$x]['shared_line'] = ''; $device_lines[$x]['enabled'] = ''; - $device_lines[$x]['sip_port'] = $_SESSION['provision']['line_sip_port']['numeric']; - $device_lines[$x]['sip_transport'] = $_SESSION['provision']['line_sip_transport']['text']; - $device_lines[$x]['register_expires'] = $_SESSION['provision']['line_register_expires']['numeric']; + $device_lines[$x]['sip_port'] = $settings->get('provision', 'line_sip_port', '5060'); + $device_lines[$x]['sip_transport'] = $settings->get('provision', 'line_sip_transport', 'tcp'); + $device_lines[$x]['register_expires'] = $settings->get('provision', 'line_register_expires', '120'); //get device keys $sql = "select * from v_device_keys "; @@ -612,11 +623,11 @@ //add empty device key row(s) if (!is_uuid($device_uuid)) { - $rows = $_SESSION['devices']['key_add_rows']['numeric'] ?? 1; + $rows = $settings->get('devices', 'key_add_rows', '10'); $id = 0; } else { - $rows = $_SESSION['devices']['key_edit_rows']['numeric'] ?? 1; + $rows = $settings->get('devices', 'key_edit_rows', '3'); $id = count($device_keys) + 1; } for ($x = 0; $x < $rows; $x++) { @@ -638,7 +649,6 @@ $sql .= "from v_device_vendors "; $sql .= "where enabled = 'true' "; $sql .= "order by name asc "; - $device_vendors = $database->select($sql, null, 'all'); unset($sql); @@ -662,11 +672,11 @@ //add empty device setting row(s) if (!is_uuid($device_uuid)) { - $rows = $_SESSION['devices']['setting_add_rows']['numeric'] ?? 1; + $rows = $settings->get('devices', 'key_add_rows', '10'); $id = 0; } else { - $rows = $_SESSION['devices']['setting_edit_rows']['numeric'] ?? 1; + $rows = $settings->get('devices', 'key_edit_rows', '3'); $id = count($device_settings) + 1; } for ($x = 0; $x < $rows; $x++) { @@ -694,12 +704,7 @@ //get the first device line info (found on the local server) for the provision button foreach ($device_lines as $row) { - if ( - array_key_exists($row['domain_uuid'], $_SESSION['domains']) && - $row['server_address'] == $_SESSION['domains'][$row['domain_uuid']]['domain_name'] && - !empty($row['user_id']) && - !empty($row['server_address']) - ) { + if ($row['server_address'] == $row['domain_name'] && !empty($row['user_id']) && !empty($row['server_address'])) { $user_id = $row['user_id']; $server_address = $row['server_address']; break; @@ -731,14 +736,13 @@ echo " $('#target_file').fadeOut(fade_speed);\n"; echo " document.getElementById('target_file').selectedIndex = 0;\n"; echo " }\n"; - echo " function download(d) {\n"; echo " if (d == '".$text['label-download']."') return;\n"; - if ($_SESSION['provision']['http_domain_filter']['boolean'] == "false") { - $domain_name = $_SERVER["HTTP_HOST"]; + if ($settings->get('provision', 'http_domain_filter', true)) { + $provision_domain_name = $domain_name; } else { - $domain_name = $_SESSION['domain_name']; + $provision_domain_name = $_SERVER["HTTP_HOST"]; } if (!isset($_SERVER['HTTP_PROTOCOL'])) { @@ -747,7 +751,7 @@ if ($_SERVER['HTTPS'] == 'on') { $_SERVER['HTTP_PROTOCOL'] = 'https'; } if ($_SERVER['SERVER_PORT'] == '443') { $_SERVER['HTTP_PROTOCOL'] = 'https'; } } - echo " window.location = '".$_SERVER['HTTP_PROTOCOL']."://".$domain_name.PROJECT_PATH."/app/provision/index.php?address=".escape($device_address ?? '')."&file=' + d + '&content_type=application/octet-stream';\n"; + echo " window.location = '".$_SERVER['HTTP_PROTOCOL']."://".$provision_domain_name.PROJECT_PATH."/app/provision/index.php?address=".escape($device_address ?? '')."&file=' + d + '&content_type=application/octet-stream';\n"; echo " }\n"; echo "\n"; @@ -793,16 +797,11 @@ //add the QR code if (permission_exists("device_line_password") && !empty($device_template) && $qr_code_enabled) { //set the mode - if (isset($_SESSION['theme']['qr_image'])) { - if (!empty($_SESSION['theme']['qr_image'])) { - $mode = '4'; - } - else { - $mode = '0'; - } + if (!empty($settings->get('theme', 'qr_image', ''))) { + $mode = '4'; } else { - $mode = '4'; + $mode = '0'; } //get the device line settings @@ -922,15 +921,10 @@ //build content for linphone if ($device_template == "linphone/default") { $auth_string = ''; - if ( - !empty($_SESSION['provision']['http_auth_enabled']['boolean']) && - $_SESSION['provision']['http_auth_enabled']['boolean'] == 'true' && - !empty($_SESSION['provision']['http_auth_username']['text']) && - !empty($_SESSION['provision']['http_auth_password'][0]) - ) { - $auth_string = $_SESSION['provision']['http_auth_username']['text'].':'.$_SESSION['provision']['http_auth_password'][0].'@'; + if ($settings->get('provision', 'http_auth_enabled', true) && !empty($settings->get('provision', 'http_auth_username', '')) && !empty($settings->get('provision', 'http_auth_password', ''))) { + $auth_string = $settings->get('provision', 'http_auth_username', '').':'.$settings->get('provision', 'http_auth_password', '').'@'; } - $content = "https://".$auth_string.$_SESSION['domain_name'].'/app/provision/index.php?address='.$device_address; + $content = "https://".$auth_string.$provision_domain_name.'/app/provision/index.php?address='.$device_address; } //stream the file @@ -1001,16 +995,16 @@ echo " \n"; echo "\n"; } + /* - if (isset($_SESSION['theme']['qr_image'])) { - echo ""; + if (!empty($settings->get('theme', 'qr_image', ''))) { + echo ""; } else { - echo ""; + echo ""; } */ - } //show the content @@ -1020,7 +1014,7 @@ echo "
\n"; echo "
".$text['header-device']."
\n"; echo "
\n"; - echo button::create(['type'=>'button','label'=>$text['button-back'],'icon'=>$_SESSION['theme']['button_icon_back'],'id'=>'btn_back','link'=>'devices.php']); + echo button::create(['type'=>'button','label'=>$text['button-back'],'icon'=>$settings->get('theme', 'button_icon_back', ''),'id'=>'btn_back','link'=>'devices.php']); if ($action == 'update') { $button_margin = 'margin-left: 15px;'; if (permission_exists("device_line_password") && $qr_code_enabled) { @@ -1038,7 +1032,7 @@ $template_dir = $prov->template_dir; $files = glob($template_dir.'/'.$device_template.'/*'); //add file buttons and the file list - echo button::create(['type'=>'button','id'=>'button_files','label'=>$text['button-files'],'icon'=>$_SESSION['theme']['button_icon_download'],'style'=>($button_margin ?? ''),'onclick'=>'show_files()']); + echo button::create(['type'=>'button','id'=>'button_files','label'=>$text['button-files'],'icon'=>$settings->get('theme', 'button_icon_download', ''),'style'=>($button_margin ?? ''),'onclick'=>'show_files()']); echo "\n"; echo " \n"; - foreach($_SESSION['provision']['server_address_primary'] as $field) { + foreach($settings->get('provision', 'server_address_primary', '') as $field) { echo " \n"; } echo " \n"; @@ -1339,10 +1333,10 @@ if (permission_exists('device_line_server_address_secondary')) { echo " \n"; - if (isset($_SESSION['provision']['server_address_secondary']) && !isset($_SESSION['provision']['server_address_secondary']['text'])) { + if (!empty($settings->get('provision', 'server_address_secondary', ''))) { echo " \n"; @@ -1355,10 +1349,10 @@ if (permission_exists('device_line_outbound_proxy_primary')) { echo " \n"; - if (isset($_SESSION['provision']['outbound_proxy_primary']) && !isset($_SESSION['provision']['outbound_proxy_primary']['text'])) { + if (!empty($settings->get('provision', 'outbound_proxy_primary', ''))) { echo " \n"; @@ -1371,10 +1365,10 @@ if (permission_exists('device_line_outbound_proxy_secondary')) { echo " \n"; - if (isset($_SESSION['provision']['outbound_proxy_secondary']) && !isset($_SESSION['provision']['outbound_proxy_secondary']['text'])) { + if (!empty($settings->get('provision', 'outbound_proxy_secondary', ''))) { echo " \n"; @@ -1495,7 +1489,7 @@ foreach($device_profiles as $row) { echo " \n"; } - echo " \n"; + echo " \n"; } else { foreach($device_profiles as $row) { @@ -1963,7 +1957,7 @@ else { echo " \n"; } - foreach ($_SESSION['domains'] as $row) { + foreach ($domains as $row) { if ($row['domain_uuid'] == $domain_uuid) { echo " \n"; } @@ -1978,7 +1972,7 @@ echo "\n"; } else { - echo " \n"; + echo " \n"; } if (permission_exists('device_enable')) { @@ -1987,7 +1981,7 @@ echo " ".$text['label-device_enabled']."\n"; echo "\n"; echo "\n"; - if (substr($_SESSION['theme']['input_toggle_style']['text'], 0, 6) == 'switch') { + if (substr($settings->get('theme', 'input_toggle_style', ''), 0, 6) == 'switch') { echo "
\n"; - if ($menu_side_state != 'hidden') { + if ($menu_side_state != 'expanded') { $content_container_onclick = "onclick=\"clearTimeout(menu_side_contract_timer); if ($(window).width() >= 576) { menu_side_contract(); }\""; } $html .= "
\n"; @@ -1286,7 +1286,7 @@ if (!class_exists('menu')) { //header: left $html .= "
\n"; // $html .= button::create(['type'=>'button','id'=>'menu_side_state_hidden_button','title'=>$this->text['theme-label-expand_menu'],'icon'=>'bars','class'=>'default '.($this->settings->get('theme', 'menu_side_state') != 'hidden' ? 'hide-sm-up ' : null).'float-left','onclick'=>'menu_side_expand();']); - $html .= "text['theme-label-expand_menu']."\">"; + $html .= "text['theme-label-expand_menu']."\">"; $body_header_brand_text = escape($this->settings->get('theme', 'body_header_brand_text', 'FusionPBX')); if ($this->settings->get('theme', 'body_header_brand_type') == 'image' || $this->settings->get('theme', 'body_header_brand_type') == 'image_text') { $body_header_brand_image = $this->settings->get('theme', 'body_header_brand_image', PROJECT_PATH.'/themes/default/images/logo_side_expanded.png'); From d49e8e4d2c636d3573c022f6002bfb673af09018 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Wed, 15 Jan 2025 15:42:11 -0700 Subject: [PATCH 30/32] Add a default for paging --- app/recordings/recordings.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/recordings/recordings.php b/app/recordings/recordings.php index cf82f67db4..b429120270 100644 --- a/app/recordings/recordings.php +++ b/app/recordings/recordings.php @@ -55,8 +55,7 @@ $speech_enabled = $settings->get('speech', 'enabled', false); $recording_storage_type = $settings->get('recordings','storage_type'); $recording_password = $settings->get('recordings','recording_password'); - $domain_paging = $settings->get('domain','paging'); - $domain_paging = $settings->get('domain','paging', ); + $domain_paging = $settings->get('domain','paging', 100); $theme_button_icon_edit = $settings->get('theme','button_icon_edit'); $theme_button_icon_add = $settings->get('theme','button_icon_add'); $theme_button_icon_upload = $settings->get('theme','button_icon_upload'); From df90b758bb21847ee08a2161af459bd9ff5e5ee9 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Wed, 15 Jan 2025 19:44:56 -0700 Subject: [PATCH 31/32] Fix issue with sending local faxes When sip_to_user or sip_req_user are used then we need to add these variables so that it can find the correct inbound route. --- app/fax_queue/resources/job/fax_send.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/fax_queue/resources/job/fax_send.php b/app/fax_queue/resources/job/fax_send.php index b48a9e0674..61c7dff3d7 100644 --- a/app/fax_queue/resources/job/fax_send.php +++ b/app/fax_queue/resources/job/fax_send.php @@ -291,7 +291,9 @@ $sql .= ")"; $parameters['destination_number'] = $fax_number; $destination_count = $database->select($sql, $parameters, 'column'); + $local_destination = false; if ($destination_count > 0) { + $local_destination = true; $route_array[] = 'loopback/'.$fax_number.'/public'; } @@ -307,6 +309,12 @@ $common_variables .= "fax_header='" . escape_quote($fax_caller_id_name) . "',"; $common_variables .= "fax_file='" . escape_quote($fax_file) . "',"; + //add the fax destination number variables + if ($local_destination) { + $common_variables .= "sip_to_user=".$fax_number.","; + $common_variables .= "sip_req_user=".$fax_number.","; + } + //prepare the fax command if (empty($route_array)) { $route_array = outbound_route_to_bridge($domain_uuid, $fax_prefix . $fax_number, $channel_variables); From edf2efb517055894c8147833a3b700ef6e4294f3 Mon Sep 17 00:00:00 2001 From: fusionate Date: Thu, 16 Jan 2025 10:51:41 -0700 Subject: [PATCH 32/32] Voicemails - List: Restore search functionality. --- app/voicemails/voicemails.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/voicemails/voicemails.php b/app/voicemails/voicemails.php index 435a3be647..28dab54440 100644 --- a/app/voicemails/voicemails.php +++ b/app/voicemails/voicemails.php @@ -119,7 +119,6 @@ $sql_search .= " or lower(voicemail_enabled) like :search "; $sql_search .= " or lower(voicemail_description) like :search "; $sql_search .= ") "; - $parameters['search'] = '%'.$search.'%'; } //prepare to page the results @@ -146,7 +145,10 @@ $sql .= "and voicemail_uuid is null "; } } - $sql .= $sql_search ?? ''; + if (!empty($sql_search)) { + $sql .= $sql_search; + $parameters['search'] = '%'.$search.'%'; + } $num_rows = $database->select($sql, $parameters, 'column'); //prepare to page the results