From 24ecfa16a073f9c35d703defc2e7c6d1e144c339 Mon Sep 17 00:00:00 2001 From: frytimo Date: Thu, 16 Jan 2025 15:49:00 -0400 Subject: [PATCH 001/196] update voicemails to use settings object where possible (#7212) --- app/voicemails/voicemails.php | 40 +++++++++++++++++------------------ 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/app/voicemails/voicemails.php b/app/voicemails/voicemails.php index 28dab54440..250e0b7160 100644 --- a/app/voicemails/voicemails.php +++ b/app/voicemails/voicemails.php @@ -52,11 +52,9 @@ $settings = new settings(['database' => $database, 'domain_uuid' => $_SESSION['domain_uuid'] ?? '', 'user_uuid' => $_SESSION['user_uuid'] ?? '']); //get the http post data - if (!empty($_POST['voicemails'])) { - $action = $_POST['action']; - $search = $_POST['search']; - $voicemails = $_POST['voicemails']; - } + $action = $_POST['action'] ?? ''; + $search = $_POST['search'] ?? ''; + $voicemails = $_POST['voicemails'] ?? []; //process the http post data by action if (!empty($action) && !empty($voicemails)) { @@ -101,13 +99,13 @@ //get order and order by $order_by = $_GET["order_by"] ?? 'voicemail_id'; $order = $_GET["order"] ?? 'asc'; - $sort = $order_by == 'voicemail_id' ? 'natural' : null; + $sort = $order_by == 'voicemail_id' ? 'natural' : ''; //set additional variables $show = $_GET["show"] ?? ''; //set from session variables - $list_row_edit_button = !empty($_SESSION['theme']['list_row_edit_button']['boolean']) ? $_SESSION['theme']['list_row_edit_button']['boolean'] : 'false'; + $list_row_edit_button = $settings->get('theme', 'list_row_edit_button', false); //add the search string $search = strtolower($_GET["search"] ?? ''); @@ -152,7 +150,7 @@ $num_rows = $database->select($sql, $parameters, 'column'); //prepare to page the results - $rows_per_page = ($_SESSION['domain']['paging']['numeric'] != '') ? $_SESSION['domain']['paging']['numeric'] : 50; + $rows_per_page = $settings->get('domain', 'paging', 50); $param = $search ? "&search=".urlencode($search) : null; if ($show == "all" && permission_exists('voicemail_all')) { $param .= "&show=all"; @@ -220,19 +218,19 @@ echo "
".$text['title-voicemails']."
".number_format($num_rows)."
\n"; echo "
\n"; if (permission_exists('voicemail_import')) { - echo button::create(['type'=>'button','label'=>$text['button-import'],'icon'=>$_SESSION['theme']['button_icon_import'],'style'=>'','link'=>'voicemail_imports.php']); + echo button::create(['type'=>'button','label'=>$text['button-import'],'icon'=>$settings->get('theme', 'button_icon_import'),'style'=>'','link'=>'voicemail_imports.php']); } if (permission_exists('voicemail_export')) { - echo button::create(['type'=>'button','label'=>$text['button-export'],'icon'=>$_SESSION['theme']['button_icon_export'],'style'=>'margin-right: 15px;','link'=>'voicemail_export.php']); + echo button::create(['type'=>'button','label'=>$text['button-export'],'icon'=>$settings->get('theme', 'button_icon_export'),'style'=>'margin-right: 15px;','link'=>'voicemail_export.php']); } if (permission_exists('voicemail_add')) { - echo button::create(['type'=>'button','label'=>$text['button-add'],'icon'=>$_SESSION['theme']['button_icon_add'],'id'=>'btn_add','link'=>'voicemail_edit.php']); + echo button::create(['type'=>'button','label'=>$text['button-add'],'icon'=>$settings->get('theme', 'button_icon_add'),'id'=>'btn_add','link'=>'voicemail_edit.php']); } if (permission_exists('voicemail_edit') && $voicemails) { - echo button::create(['type'=>'button','label'=>$text['button-toggle'],'icon'=>$_SESSION['theme']['button_icon_toggle'],'id'=>'btn_toggle','name'=>'btn_toggle','style'=>'display: none;','onclick'=>"modal_open('modal-toggle','btn_toggle');"]); + echo button::create(['type'=>'button','label'=>$text['button-toggle'],'icon'=>$settings->get('theme', 'button_icon_toggle'),'id'=>'btn_toggle','name'=>'btn_toggle','style'=>'display: none;','onclick'=>"modal_open('modal-toggle','btn_toggle');"]); } if (permission_exists('voicemail_delete') && $voicemails) { - 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'=>$settings->get('theme', 'button_icon_delete'),'id'=>'btn_delete','name'=>'btn_delete','style'=>'display: none;','onclick'=>"modal_open('modal-delete','btn_delete');"]); } echo "
+ +
+ {if !empty($login_password_reset_enabled) && $login_password_reset_enabled} + + {/if}
@@ -104,4 +110,3 @@ - diff --git a/login.php b/login.php index e6c9bbc620..0bfef4fe2f 100644 --- a/login.php +++ b/login.php @@ -23,10 +23,11 @@ Contributor(s): Mark J. Crane */ + //includes files require_once __DIR__ . "/resources/require.php"; //additional includes require_once "resources/check_auth.php"; -?> \ No newline at end of file +?> diff --git a/resources/functions.php b/resources/functions.php index 116883b284..cc791db9df 100644 --- a/resources/functions.php +++ b/resources/functions.php @@ -1045,19 +1045,23 @@ //check password strength against requirements (if any) function check_password_strength($password, $text, $type = 'default') { + + //initialize the settigns object + $settings = new settings(['database' => $database, 'domain_uuid' => $_SESSION['domain_uuid']]); + if (!empty($password)) { if ($type == 'default') { - $req['length'] = $_SESSION['extension']['password_length']['numeric']; - $req['number'] = ($_SESSION['extension']['password_number']['boolean'] == 'true') ? true : false; - $req['lowercase'] = ($_SESSION['extension']['password_lowercase']['boolean'] == 'true') ? true : false; - $req['uppercase'] = ($_SESSION['extension']['password_uppercase']['boolean'] == 'true') ? true : false; - $req['special'] = ($_SESSION['extension']['password_special']['boolean'] == 'true') ? true : false; + $req['length'] = $settings->get('extension', 'password_length', '10'); + $req['number'] = $settings->get('extension', 'password_number', true); + $req['lowercase'] = $settings->get('extension', 'password_lowercase', true); + $req['uppercase'] = $settings->get('extension', 'password_uppercase', false); + $req['special'] = $settings->get('extension', 'password_special', false); } elseif ($type == 'user') { - $req['length'] = $_SESSION['user']['password_length']['numeric']; - $req['number'] = ($_SESSION['user']['password_number']['boolean'] == 'true') ? true : false; - $req['lowercase'] = ($_SESSION['user']['password_lowercase']['boolean'] == 'true') ? true : false; - $req['uppercase'] = ($_SESSION['user']['password_uppercase']['boolean'] == 'true') ? true : false; - $req['special'] = ($_SESSION['user']['password_special']['boolean'] == 'true') ? true : false; + $req['length'] = $settings->get('users', 'password_length', '10'); + $req['number'] = $settings->get('users', 'password_number', true); + $req['lowercase'] = $settings->get('users', 'password_lowercase', true); + $req['uppercase'] = $settings->get('users', 'password_uppercase', false); + $req['special'] = $settings->get('users', 'password_special', false); } if (is_numeric($req['length']) && $req['length'] != 0 && !preg_match_all('$\S*(?=\S{' . $req['length'] . ',})\S*$', $password)) { // length $msg_errors[] = $req['length'] . '+ ' . $text['label-characters']; diff --git a/resources/login.php b/resources/login.php index e079da6414..4e0c033ac8 100644 --- a/resources/login.php +++ b/resources/login.php @@ -17,7 +17,7 @@ The Initial Developer of the Original Code is Mark J Crane - Portions created by the Initial Developer are Copyright (C) 2008-2023 + Portions created by the Initial Developer are Copyright (C) 2008-2025 the Initial Developer. All Rights Reserved. Contributor(s): @@ -31,57 +31,46 @@ $language = new text; $text = $language->get(null,'core/user_settings'); -//get action, if any +//connect to the database + $database = database::new(); + +//set the current domain_uuid + $domain_uuid = $_SESSION['domain_uuid'] ?? ''; + +//initialize the settigns object + $settings = new settings(['database' => $database, 'domain_uuid' => $domain_uuid]); + +//get action, if any - define, request, reset if (isset($_REQUEST['action'])) { $action = $_REQUEST['action']; } -//retrieve parse reset key - if ($action == 'define') { - $key = $_GET['key']; - $key_part = explode('|', decrypt($_SESSION['login']['password_reset_key']['text'], $key)); - $username = $key_part[0]; - $domain_uuid = $key_part[1]; - $password_submitted = $key_part[2]; - - //get current salt, see if same as submitted salt - $sql = "select password from v_users "; - $sql .= "where domain_uuid = :domain_uuid "; - $sql .= "and username = :username "; - $parameters['domain_uuid'] = $domain_uuid; - $parameters['username'] = $username; - $database = new database; - $password_current = $database->select($sql, $parameters, 'column'); - unset($sql, $parameters); - - //set flag - if ($username != '' && $password_submitted == $password_current) { - $password_reset = true; - $_SESSION['valid_username'] = $username; - $_SESSION['valid_domain'] = $domain_uuid; - } - else { - header("Location: /login.php"); - exit; +//get the domains if user has permission for show all + $domains = []; + if ($has_device_domain_all) { + $rows = $database->select("select domain_uuid, domain_name from v_domains"); + if (!empty($rows)) { + foreach ($rows as $row) { + $domains[$row['domain_uuid']] = $row['domain_name']; } + } } -//send password reset link - if ($action == 'request') { +//send an email with the password reset link + if (isset($action) && $action == 'request' && isset($_REQUEST['email'])) { if (valid_email($_REQUEST['email'])) { - $email = $_REQUEST['email']; + //set the email address + $email = $_REQUEST['email']; - //see if email exists + //see if email existsesources/login.php?action=request $sql = "select "; $sql .= "user_uuid, "; $sql .= "username, "; $sql .= "password, "; $sql .= "domain_uuid "; - $sql .= "from "; - $sql .= "v_users "; + $sql .= "from v_users "; $sql .= "where user_email = :email "; $parameters['email'] = $email; - $database = new database; $results = $database->select($sql, $parameters, 'all'); unset($sql, $parameters); @@ -92,23 +81,27 @@ $result = $results[0]; if ($result['username'] != '') { + //set valid email + $_SESSION['valid_email'] = $email; + + //set the password reset domain + $password_reset_domain = $_SESSION['domain_name']; //generate reset link email and body variables $domain_uuid = $result['domain_uuid']; - if ($_SESSION['login']['password_reset_domain']['text'] != '') { - $domain_name = $_SESSION['login']['password_reset_domain']['text']; + if ($settings->get('login', 'password_reset_domain', '') != '') { + $password_reset_domain = $settings->get('login', 'password_reset_domain', ''); } else { - foreach ($_SESSION['domains'] as $uuid => $domain) { - if (strtolower($domain['domain_name']) == strtolower($_SERVER['HTTP_HOST'])) { - $domain_name = $_SERVER['HTTP_HOST']; + foreach ($domains as $domain) { + if (strtolower($domain) == strtolower($_SERVER['HTTP_HOST'])) { + $password_reset_domain = $_SERVER['HTTP_HOST']; break; } } - $domain_name = $domain_name ? $domain_name : $_SESSION['domains'][$domain_uuid]['domain_name']; } - $key = encrypt($_SESSION['login']['password_reset_key']['text'], $result['username'].'|'.$result['domain_uuid'].'|'.$result['password']); - $reset_link = "https://".$domain_name.PROJECT_PATH."/login.php?action=define&key=".urlencode($key); + $key = encrypt($settings->get('login', 'password_reset_key', ''), $result['username'].'|'.$result['domain_uuid'].'|'.$result['password']); + $reset_link = "https://".$password_reset_domain.PROJECT_PATH."/resources/login.php?action=define&key=".urlencode($key); $reset_button = email_button(strtoupper($text['label-reset_password']), $reset_link, ($_SESSION['theme']['button_background_color_email']['text'] ? $_SESSION['theme']['button_background_color_email']['text'] : '#2e82d0'), ($_SESSION['theme']['button_text_color_email']['text'] ? $_SESSION['theme']['button_text_color_email']['text'] : '#ffffff')); $logo_full = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPoAAABGCAYAAADl5IkzAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NjAzQjkyMEYxMzA5MTFFNEJCMEVBNTk1RkYzM0FEMjciIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NjAzQjkyMTAxMzA5MTFFNEJCMEVBNTk1RkYzM0FEMjciPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo2MDNCOTIwRDEzMDkxMUU0QkIwRUE1OTVGRjMzQUQyNyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo2MDNCOTIwRTEzMDkxMUU0QkIwRUE1OTVGRjMzQUQyNyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PufA528AAFJVSURBVHja7H0HnBRV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'; $logo_shield = 'data:image/png;base64,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'; @@ -122,14 +115,13 @@ $sql .= "and user_setting_name = 'code' "; $parameters['user_uuid'] = $result['user_uuid']; $parameters['domain_uuid'] = $domain_uuid; - $database = new database; $row = $database->select($sql, $parameters, 'row'); if (is_array($row) && @sizeof($row) != 0) { $user_language_code = $row['user_setting_value']; } unset($sql, $parameters, $row); - //get email template from db + //get the email template from database $sql = "select template_subject, template_body from v_email_templates "; $sql .= "where template_language = :template_language "; $sql .= "and (domain_uuid = :domain_uuid or domain_uuid is null) "; @@ -137,9 +129,8 @@ $sql .= "and template_subcategory = 'default' "; $sql .= "and template_type = 'html' "; $sql .= "and template_enabled = 'true' "; - $parameters['template_language'] = $user_language_code ? $user_language_code : $_SESSION['domain']['language']['code']; + $parameters['template_language'] = $user_language_code ? $user_language_code : $settings->get('domain', 'language', 'en-us'); $parameters['domain_uuid'] = $domain_uuid; - $database = new database; $row = $database->select($sql, $parameters, 'row'); if (is_array($row)) { $email_subject = $row['template_subject']; @@ -157,85 +148,111 @@ //send reset link if (send_email($email, $email_subject, $email_body, $eml_error)) { //email sent - message::add($text['message-reset_link_sent'], 'positive', 2500); + message::add($text['message-reset_link_sent'], 'positive', 2500); } else { //email failed - message::add($eml_error, 'negative', 5000); + message::add($eml_error, 'negative', 5000); } } else { //not found - message::add($text['message-invalid_email'], 'negative', 5000); + message::add($text['message-invalid_email'], 'negative', 5000); } } else { //matched multiple users - message::add($text['message-email_assigned_mutliple_users'], 'negative', 5000); + message::add($text['message-email_assigned_mutliple_users'], 'negative', 5000); } } else { //not found - message::add($text['message-invalid_email'], 'negative', 5000); + message::add($text['message-invalid_email'], 'negative', 5000); } } - else { - //invalid email - message::add($text['message-invalid_email'], 'negative', 5000); - } + //else { + // //invalid email + // message::add($text['message-invalid_email'], 'negative', 5000); + //} } -//reset password - if ($action == 'reset') { - $username = trim($_REQUEST['username']); +//validate the password reset key + if (isset($action) && $action == 'define') { + //get the key and decrypt and parse it + $key = $_GET['key']; + $key_part = explode('|', decrypt($settings->get('login', 'password_reset_key', ''), $key)); + $username = $key_part[0]; + $domain_uuid = $key_part[1]; + $password_submitted = $key_part[2]; + + //get the user_email + $user_email = $_SESSION['valid_email']; + + //get current, see if same as submitted salt + $sql = "select username, password from v_users "; //user_token_hash, user_token_expires + $sql .= "where domain_uuid = :domain_uuid "; + $sql .= "and username = :username "; + //$sql .= "and user_email = :user_email "; + $parameters['domain_uuid'] = $domain_uuid; + $parameters['username'] = $username; + //$parameters['user_email'] = $user_email; + $row = $database->select($sql, $parameters, 'row'); + $password_current = $row['password']; + unset($sql, $parameters); + + //the key has been validated set the reset flag + if ($username != '' && $password_submitted == $password_current) { + $_SESSION['valid_username'] = $row['username']; + $_SESSION['valid_domain'] = $domain_uuid; + $_SESSION['valid_reset'] = true; + } + else { + header("Location: /login.php"); + exit; + } + } + +//reset the password + if ($_SESSION['valid_reset'] && !empty($_SESSION['valid_username']) && !empty($_REQUEST['password_new']) && !empty($_REQUEST['password_repeat'])) { + //$username = trim($_REQUEST['username']); $password_new = trim($_REQUEST['password_new']); $password_repeat = trim($_REQUEST['password_repeat']); //if not requiring usernames to be of email format, strip off @domain as the valid domain for the reset is already being provided in the where clause below - if ($_SESSION['users']['username_format']['text'] != 'email') { - $username = substr_count($username, '@') != 0 ? explode('@', $username)[0] : $username; - } + //if ($settings->get('users', 'username_format', '') != 'email') { + // $username = substr_count($username, '@') != 0 ? explode('@', $username)[0] : $username; + //} - if ($username !== '' && - $username === $_SESSION['valid_username'] && - $password_new !== '' && - $password_repeat !== '' && - $password_new === $password_repeat - ) { + if ($password_new === $password_repeat && check_password_strength($password_new, $text, 'user')) { - if (!check_password_strength($password_new, $text, 'user')) { - $password_reset = true; - } - else { - $salt = uuid(); - $sql = "update v_users set "; - $sql .= "password = :password, "; - $sql .= "salt = :salt "; - $sql .= "where domain_uuid = :domain_uuid "; - $sql .= "and username = :username "; - $parameters['domain_uuid'] = $_SESSION['valid_domain']; - $parameters['password'] = md5($salt.$password_new); - $parameters['salt'] = $salt; - $parameters['username'] = $username; - $database = new database; - $database->execute($sql, $parameters); - unset($sql, $parameters); + //set the password hash cost + $options = array('cost' => 10); - message::add($text['message-password_reset'], 'positive', 2500); - unset($_SESSION['valid_username'], $_SESSION['valid_domain']); + //update the pasword + $sql = "update v_users set "; + $sql .= "password = :password, "; + $sql .= "salt = null "; + $sql .= "where domain_uuid = :domain_uuid "; + $sql .= "and username = :username "; + $parameters['domain_uuid'] = $_SESSION['valid_domain']; + $parameters['password'] = password_hash($password_new, PASSWORD_DEFAULT, $options); + $parameters['username'] = $_SESSION['valid_username']; + $database->execute($sql, $parameters); + unset($sql, $parameters); - header('Location: //'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']); - exit; + //set the message to password reset completed + message::add($text['message-password_reset'], 'positive', 2500); + + //unset the php session + unset($_SESSION); + + //redirect the browser + header('Location: //'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']); + exit; - } - } - else { - //not found - message::add($text['message-invalid_username_mismatch_passwords'], 'negative', 5000); - $password_reset = true; } } @@ -243,24 +260,32 @@ $msg = isset($_GET["msg"]) ? $_GET["msg"] : null; //set variable if not set - if (!isset($_SESSION['login']['domain_name_visible']['boolean'])) { $_SESSION['login']['domain_name_visible']['boolean'] = null; } + $login_domain_name_visible = $settings->get('login', 'domain_name_visible', false); //santize the login destination url and set a default value - if (isset($_SESSION['login']['destination']['text'])) { - $destination_path = parse_url($_SESSION['login']['destination']['text'])['path'] ?? ''; - $destination_query = parse_url($_SESSION['login']['destination']['text'])['query'] ?? ''; + if (!empty($settings->get('login', 'destination', ''))) { + $destination_path = parse_url($settings->get('login', 'destination', ''))['path'] ?? ''; + $destination_query = parse_url($settings->get('login', 'destination', ''))['query'] ?? ''; $destination_path = preg_replace('#[^a-zA-Z0-9_\-\./]#', '', $destination_path); $destination_query = preg_replace('#[^a-zA-Z0-9_\-\./&=]#', '', $destination_query); - $_SESSION['login']['destination']['text'] = (!empty($destination_query)) ? $destination_path.'?'.$destination_query : $destination_path; + $login_destination = (!empty($destination_query)) ? $destination_path.'?'.$destination_query : $destination_path; } else { - $_SESSION['login']['destination']['text'] = PROJECT_PATH."/core/dashboard/"; + $login_destination = PROJECT_PATH."/core/dashboard/"; } +//set the redirect path if (!empty($_REQUEST['path'])) { $_SESSION['redirect_path'] = $_REQUEST['path']; } +//get the user settings + $user_setting['length'] = $settings->get('users', 'password_length', '10'); + $user_setting['number'] = $settings->get('users', 'password_number', true); + $user_setting['lowercase'] = $settings->get('users', 'password_lowercase', true); + $user_setting['uppercase'] = $settings->get('users', 'password_uppercase', false); + $user_setting['special'] = $settings->get('users', 'password_special', false); + //add the header $document['title'] = $text['title-login']; include "resources/header.php"; @@ -280,58 +305,38 @@ echo " }"; echo ""; - echo "
\n"; +//send an email with the password reset link + if (isset($action) && $action == 'request' && !empty($_SESSION['valid_email'])) { + echo "
\n"; + echo "
".$text['label-email_sent']."
\n"; + echo " ".$text['description-email_sent']."
\n"; + echo "
\n"; + } - if (!$password_reset) { +//request the email address + if (empty($_SESSION['valid_email']) && !isset($_SESSION['valid_reset'])) { //create token - $object = new token; - $token = $object->create('login'); + $object = new token; + $token = $object->create('login'); - echo "
\n"; - echo "
\n"; - echo "
\n"; - echo "
\n"; - if ($_SESSION['login']['domain_name_visible']['boolean'] == "true") { - if (count($_SESSION['login']['domain_name']) > 0) { - $click_change_color = ($_SESSION['theme']['login_input_text_color']['text'] != '') ? $_SESSION['theme']['login_input_text_color']['text'] : (($_SESSION['theme']['input_text_color']['text'] != '') ? $_SESSION['theme']['input_text_color']['text'] : '#000000'); - $placeholder_color = ($_SESSION['theme']['login_input_text_placeholder_color']['text'] != '') ? 'color: '.$_SESSION['theme']['login_input_text_placeholder_color']['text'].';' : 'color: #999999;'; - echo "
\n"; - } - else { - echo "
\n"; - } - } - echo "\n"; - if ( - function_exists('openssl_encrypt') && - $_SESSION['login']['password_reset_key']['text'] != '' && - $_SESSION['email']['smtp_host']['text'] != '' - ) { - echo "

"; - } - echo "\n"; - echo "
"; - echo ""; - echo "
"; - - echo "\n"; echo " \n"; + +if ($dashboard_details_state != 'disabled') { +echo "
\n"; +echo " \n"; +echo " \n"; +echo " \n"; +echo " \n"; +echo " \n"; + $row_style[false] = "row_style0"; + $row_style[true] = "row_style1"; + $c = true; + foreach ($services as $name => $enabled) { + echo " \n"; + echo " \n"; + echo " \n"; + echo " \n"; + $c = !$c; + } +echo "
".($text['label-service'] ?? 'Service')."".($text['label-running'] ?? 'Running')."
$name" . ($enabled ? $text['label-yes'] ?? 'Yes' : $text['label-no'] ?? 'No') . "
\n"; +echo "
\n"; +} +echo "\n"; From aa75be76e77af88cc222f890006e505bb10f7325 Mon Sep 17 00:00:00 2001 From: fusionate Date: Tue, 28 Jan 2025 11:58:32 -0700 Subject: [PATCH 028/196] Yealink App: Fix UUID in a previous commit. This was preventing the App Defaults to run properly, because the database was rejecting the UUID value. --- app/yealink/app_config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/yealink/app_config.php b/app/yealink/app_config.php index ed32e50259..31ad1f0320 100644 --- a/app/yealink/app_config.php +++ b/app/yealink/app_config.php @@ -272,7 +272,7 @@ $apps[$x]['default_settings'][$y]['default_setting_enabled'] = "false"; $apps[$x]['default_settings'][$y]['default_setting_description'] = "URL for Yealink Super Search XML configuration file"; $y++; - $apps[$x]['default_settings'][$y]['default_setting_uuid'] = "9c704e81-cbb4-4cb3-ab1c-427755008714c"; + $apps[$x]['default_settings'][$y]['default_setting_uuid'] = "9c704e81-cbb4-4cb3-ab1c-427755008714"; $apps[$x]['default_settings'][$y]['default_setting_category'] = "provision"; $apps[$x]['default_settings'][$y]['default_setting_subcategory'] = "yealink_t33g_wallpaper"; $apps[$x]['default_settings'][$y]['default_setting_name'] = "text"; From 7c887184ffecb4da6bdb1f2ece0425049c29addc Mon Sep 17 00:00:00 2001 From: frytimo Date: Tue, 28 Jan 2025 15:17:04 -0400 Subject: [PATCH 029/196] adjust system service dashboard widget to not show by default (#7233) --- app/system/resources/dashboard/config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/system/resources/dashboard/config.php b/app/system/resources/dashboard/config.php index bdaa3f7d0a..933ea2363a 100644 --- a/app/system/resources/dashboard/config.php +++ b/app/system/resources/dashboard/config.php @@ -70,7 +70,7 @@ $array['dashboard'][$x]['dashboard_column_span'] = '1'; $array['dashboard'][$x]['dashboard_row_span'] = '2'; $array['dashboard'][$x]['dashboard_details_state'] = 'hidden'; $array['dashboard'][$x]['dashboard_order'] = '110'; -$array['dashboard'][$x]['dashboard_enabled'] = 'true'; +$array['dashboard'][$x]['dashboard_enabled'] = 'false'; $array['dashboard'][$x]['dashboard_description'] = 'A list of showing the count of active and inactive services'; $y = 0; $array['dashboard'][$x]['dashboard_groups'][$y]['dashboard_group_uuid'] = '719d8a56-00b2-437e-83c0-a9e5005a53c5'; From 14288772d57d87188f32538798615ae01a33d969 Mon Sep 17 00:00:00 2001 From: fusionate Date: Tue, 28 Jan 2025 12:53:32 -0700 Subject: [PATCH 030/196] Yealink App: Replace an invalid UUID. --- app/yealink/app_config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/yealink/app_config.php b/app/yealink/app_config.php index 31ad1f0320..cff1b28fe1 100644 --- a/app/yealink/app_config.php +++ b/app/yealink/app_config.php @@ -288,7 +288,7 @@ $apps[$x]['default_settings'][$y]['default_setting_enabled'] = "false"; $apps[$x]['default_settings'][$y]['default_setting_description'] = "Wallpaper to load on to T33G screen"; $y++; - $apps[$x]['default_settings'][$y]['default_setting_uuid'] = "9ddc080dd-0157-4eea-90b7-ca288a938d43"; + $apps[$x]['default_settings'][$y]['default_setting_uuid'] = "ab97779a-8d32-4ab4-a88f-4ea1433d00ba"; $apps[$x]['default_settings'][$y]['default_setting_category'] = "provision"; $apps[$x]['default_settings'][$y]['default_setting_subcategory'] = "yealink_t46s_wallpaper"; $apps[$x]['default_settings'][$y]['default_setting_name'] = "text"; From a4f83539baa5434d37fc77fe9fe9b9dddca83cb9 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Tue, 28 Jan 2025 12:54:09 -0700 Subject: [PATCH 031/196] Update login.php --- resources/login.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/login.php b/resources/login.php index 19e64870f8..b4227bf727 100644 --- a/resources/login.php +++ b/resources/login.php @@ -62,7 +62,7 @@ //set the email address $email = $_REQUEST['email']; - //see if email existsesources/login.php?action=request + //see if email exists $sql = "select "; $sql .= "user_uuid, "; $sql .= "username, "; From b8b796316e74a754db2566bd5a48beeaaac19c9f Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Tue, 28 Jan 2025 15:35:02 -0700 Subject: [PATCH 032/196] Add method column_exists to the database class --- resources/classes/database.php | 84 +++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/resources/classes/database.php b/resources/classes/database.php index 37d6bd0f0d..f745b8a489 100644 --- a/resources/classes/database.php +++ b/resources/classes/database.php @@ -297,7 +297,6 @@ //driver and type point to the same value $this->driver = $config->get('database.0.type', 'pgsql'); - $this->driver = $config->get('database.0.type', 'pgsql'); $this->type = $config->get('database.0.type', 'pgsql'); $this->host = $config->get('database.0.host', '127.0.0.1'); $this->port = $config->get('database.0.port', '5432'); @@ -787,6 +786,89 @@ } } + /** + * Checks if the column exists in the database. + *

Note:
+ * Tables and Column names must be sanitized. Otherwise, a warning will be + * emitted and false will be returned.

+ * @param type $table_name Sanitized name of the table to search for. + * @param type $column_name Sanitized name of the column to search for. + * @return boolean Returns true if the column exists and false if it does not. + * @depends connect() + */ + public function column_exists ($table_name, $column_name) { + //sanitize the table name + if (self::sanitize($table_name) != $table_name) { + trigger_error('Table Name must be sanitized', E_USER_WARNING); + return false; + } + + //sanitize the column name + if (self::sanitize($column_name) != $column_name) { + trigger_error('Column Name must be sanitized', E_USER_WARNING); + return false; + } + + //connect to the database if needed + if (!$this->db) { + $this->connect(); + } + + //if unable to connect to the database + if (!$this->db) { + $backtrace = debug_backtrace(); + echo "Connection Failed
\n"; + echo "line number ".__line__."
\n"; + echo "
";
+					print_r($backtrace);
+					echo "
"; + return false; + } + + //check the sqlite database to see if the column exists + //if ($this->db_type == "sqlite") { + // $table_info = $this->table_info($table_name); + // if ($this->sqlite_column_exists($table_info, $column_name)) { + // return true; + // } + // else { + // return false; + // } + //} + + //check the postgresql database to see if the column exists + if ($this->type == "pgsql") { + $sql = "SELECT attname FROM pg_attribute WHERE attrelid = (SELECT oid FROM pg_class WHERE relname = '$table_name' limit 1) AND attname = '$column_name'; "; + } + + //check the mysql database to see if the column exists + if ($this->type == "mysql") { + //$sql .= "SELECT * FROM information_schema.COLUMNS where TABLE_SCHEMA = '$db_name' and TABLE_NAME = '$table_name' and COLUMN_NAME = '$column_name' "; + $sql = "show columns from $table_name where field = '$column_name' "; + } + + //return the results from the sql query + if (empty($sql)) { + return false; + } + else { + $prep_statement = $this->db->prepare($sql); + $prep_statement->execute(); + $result = $prep_statement->fetchAll(PDO::FETCH_NAMED); + if (!$result) { + return false; + } + if (count($result) > 0) { + return true; + } + else { + return false; + } + unset ($prep_statement); + } + + } + /** * Queries {@link database::table_info()} to return the fields. * @access public From 42a1625daa83ce87671d7a7f504ab77efbe55c4a Mon Sep 17 00:00:00 2001 From: fusionate Date: Tue, 28 Jan 2025 15:54:35 -0700 Subject: [PATCH 033/196] Contact - Phone: Prevent duplicate speed dial numbers. --- core/contacts/app_languages.php | 25 +++++++++++++++++++++++++ core/contacts/contact_edit.php | 28 +++++++++++++++++++++++++++- core/contacts/contact_phone_edit.php | 26 ++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/core/contacts/app_languages.php b/core/contacts/app_languages.php index e8825a4c77..0a86f3826a 100644 --- a/core/contacts/app_languages.php +++ b/core/contacts/app_languages.php @@ -1793,6 +1793,31 @@ $text['message-uploaded']['zh-cn'] = "文件已上传"; $text['message-uploaded']['ja-jp'] = "ファイルがアップロードされました"; $text['message-uploaded']['ko-kr'] = "업로드된 파일"; +$text['message-speed_dial_exists']['en-us'] = "Speed Dial Number Already Exists"; +$text['message-speed_dial_exists']['en-gb'] = "Speed Dial Number Already Exists"; +$text['message-speed_dial_exists']['ar-eg'] = "رقم الاتصال السريع موجود بالفعل"; +$text['message-speed_dial_exists']['de-at'] = "Kurzwahlnummer existiert bereits"; +$text['message-speed_dial_exists']['de-ch'] = "Kurzwahlnummer existiert bereits"; +$text['message-speed_dial_exists']['de-de'] = "Kurzwahlnummer existiert bereits"; +$text['message-speed_dial_exists']['es-cl'] = "El número de marcación rápida ya existe"; +$text['message-speed_dial_exists']['es-mx'] = "El número de marcación rápida ya existe"; +$text['message-speed_dial_exists']['fr-ca'] = "Le numéro abrégé existe déjà"; +$text['message-speed_dial_exists']['fr-fr'] = "Le numéro de numérotation rapide existe déjà"; +$text['message-speed_dial_exists']['he-il'] = "מספר חיוג מהיר כבר קיים"; +$text['message-speed_dial_exists']['it-it'] = "Il numero di selezione rapida esiste già"; +$text['message-speed_dial_exists']['ka-ge'] = "სწრაფი აკრეფის ნომერი უკვე არსებობს"; +$text['message-speed_dial_exists']['nl-nl'] = "Snelkiesnummer bestaat al"; +$text['message-speed_dial_exists']['pl-pl'] = "Numer szybkiego wybierania już istnieje"; +$text['message-speed_dial_exists']['pt-br'] = "Número de discagem rápida já existe"; +$text['message-speed_dial_exists']['pt-pt'] = "O número de marcação rápida já existe"; +$text['message-speed_dial_exists']['ro-ro'] = "Numărul de apelare rapidă există deja"; +$text['message-speed_dial_exists']['ru-ru'] = "Номер быстрого набора уже существует"; +$text['message-speed_dial_exists']['sv-se'] = "Snabbuppringningsnummer finns redan"; +$text['message-speed_dial_exists']['uk-ua'] = "Номер швидкого набору вже існує"; +$text['message-speed_dial_exists']['zh-cn'] = "快速拨号号码已存在"; +$text['message-speed_dial_exists']['ja-jp'] = "短縮ダイヤル番号は既に存在します"; +$text['message-speed_dial_exists']['ko-kr'] = "단축번호가 이미 존재합니다"; + $text['label-voice']['en-us'] = "Voice"; $text['label-voice']['en-gb'] = "Voice"; $text['label-voice']['ar-eg'] = "صوت"; diff --git a/core/contacts/contact_edit.php b/core/contacts/contact_edit.php index d8d1767eab..75e7caf809 100644 --- a/core/contacts/contact_edit.php +++ b/core/contacts/contact_edit.php @@ -367,7 +367,33 @@ if (!empty($contact_phones)) { foreach ($contact_phones as $row) { if (!empty($row['phone_number'])) { - //add the speed dial + + //if speed dial number already exists, empty before save + if (!empty($row["phone_speed_dial"])) { + $phone_speed_dial_exists = false; + if (is_numeric($row["phone_speed_dial"])) { + $sql = "select count(contact_phone_uuid) "; + $sql .= "from v_contact_phones "; + $sql .= "where phone_speed_dial = :phone_speed_dial "; + $sql .= "and domain_uuid = :domain_uuid "; + if ($action == "update" && is_uuid($row["contact_phone_uuid"])) { + $sql .= "and contact_phone_uuid <> :contact_phone_uuid "; + $parameters['contact_phone_uuid'] = $row["contact_phone_uuid"]; + } + $parameters['phone_speed_dial'] = $row["phone_speed_dial"]; + $parameters['domain_uuid'] = $_SESSION['domain_uuid']; + $database = new database; + if (!empty($database->execute($sql, $parameters, 'column'))) { + $phone_speed_dial_exists = true; + } + unset($sql, $parameters); + } + if (!is_numeric($row["phone_speed_dial"]) || $phone_speed_dial_exists) { + message::add($text['message-speed_dial_exists'],'negative'); + unset($row["phone_speed_dial"]); + } + } + $array['contacts'][0]['contact_phones'][$y]['domain_uuid'] = $_SESSION['domain_uuid']; $array['contacts'][0]['contact_phones'][$y]['contact_uuid'] = $contact_uuid; $array['contacts'][0]['contact_phones'][$y]['contact_phone_uuid'] = $row["contact_phone_uuid"]; diff --git a/core/contacts/contact_phone_edit.php b/core/contacts/contact_phone_edit.php index c999eb7aec..acb196b05f 100644 --- a/core/contacts/contact_phone_edit.php +++ b/core/contacts/contact_phone_edit.php @@ -155,6 +155,32 @@ unset($sql, $parameters); } + //if speed dial number already exists, empty before save + if (!empty($phone_speed_dial)) { + $phone_speed_dial_exists = false; + if (is_numeric($phone_speed_dial)) { + $sql = "select count(contact_phone_uuid) "; + $sql .= "from v_contact_phones "; + $sql .= "where phone_speed_dial = :phone_speed_dial "; + $sql .= "and domain_uuid = :domain_uuid "; + if ($action == "update") { + $sql .= "and contact_uuid <> :contact_uuid "; + $parameters['contact_uuid'] = $contact_uuid; + } + $parameters['phone_speed_dial'] = $phone_speed_dial; + $parameters['domain_uuid'] = $domain_uuid; + $database = new database; + if (!empty($database->execute($sql, $parameters, 'column'))) { + $phone_speed_dial_exists = true; + } + unset($sql, $parameters); + } + if (!is_numeric($phone_speed_dial) || $phone_speed_dial_exists) { + message::add($text['message-speed_dial_exists'],'negative'); + unset($phone_speed_dial); + } + } + //add the phone if ($action == "add" && permission_exists('contact_phone_add')) { $contact_phone_uuid = uuid(); From fe0680f9b17a8903b97d80c93b42897c03dbc154 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Tue, 28 Jan 2025 15:59:04 -0700 Subject: [PATCH 034/196] Handle columns in the table that may not exist The old v_device_keys column device_profile_uuid is deprecated. It will exist on systems that were upgraded from an older version before the change was made. The app default code here moves data from the old format to the newer one. This is useful for upgrades. Newer installs will not have this deprecated field in the device_keys and device_settings table. --- app/devices/app_defaults.php | 145 ++++++++++++++++++----------------- 1 file changed, 75 insertions(+), 70 deletions(-) diff --git a/app/devices/app_defaults.php b/app/devices/app_defaults.php index 9dde91d806..1df2f32a0b 100644 --- a/app/devices/app_defaults.php +++ b/app/devices/app_defaults.php @@ -77,86 +77,90 @@ if ($domains_processed == 1) { unset($sql, $device_keys); //set the device profile keys - $sql = "select count(*) from v_device_profile_keys "; - $num_rows = $database->select($sql, null, 'column'); - if ($num_rows == 0) { - //get the device profile keys from device_keys table - $sql = "select * from v_device_keys "; - $sql .= "where device_profile_uuid is not null "; - $device_profile_keys = $database->select($sql, null, 'all'); + if ($database->column_exists('v_device_keys', 'device_profile_uuid')) { + $sql = "select count(*) from v_device_profile_keys "; + $num_rows = $database->select($sql, null, 'column'); + if ($num_rows == 0) { + //get the device profile keys from device_keys table + $sql = "select * from v_device_keys "; + $sql .= "where device_profile_uuid is not null "; + $device_profile_keys = $database->select($sql, null, 'all'); - //loop through the device_keys to build the data array - if (!empty($device_profile_keys)) { - foreach ($device_profile_keys as $index => $row) { - $array['device_profile_keys'][$index]['device_profile_key_uuid'] = $row["device_key_uuid"]; - $array['device_profile_keys'][$index]['domain_uuid'] = $row["domain_uuid"]; - $array['device_profile_keys'][$index]['device_profile_uuid'] = $row["device_profile_uuid"]; - $array['device_profile_keys'][$index]['profile_key_id'] = $row["device_key_id"]; - $array['device_profile_keys'][$index]['profile_key_category'] = $row["device_key_category"]; - $array['device_profile_keys'][$index]['profile_key_vendor'] = $row["device_key_vendor"]; - $array['device_profile_keys'][$index]['profile_key_type'] = $row["device_key_type"]; - $array['device_profile_keys'][$index]['profile_key_line'] = $row["device_key_line"]; - $array['device_profile_keys'][$index]['profile_key_value'] = $row["device_key_value"]; - $array['device_profile_keys'][$index]['profile_key_extension'] = $row["device_key_extension"]; - $array['device_profile_keys'][$index]['profile_key_protected'] = $row["device_key_protected"]; - $array['device_profile_keys'][$index]['profile_key_label'] = $row["device_key_label"]; - $array['device_profile_keys'][$index]['profile_key_icon'] = $row["device_key_icon"]; + //loop through the device_keys to build the data array + if (!empty($device_profile_keys)) { + foreach ($device_profile_keys as $index => $row) { + $array['device_profile_keys'][$index]['device_profile_key_uuid'] = $row["device_key_uuid"]; + $array['device_profile_keys'][$index]['domain_uuid'] = $row["domain_uuid"]; + $array['device_profile_keys'][$index]['device_profile_uuid'] = $row["device_profile_uuid"]; + $array['device_profile_keys'][$index]['profile_key_id'] = $row["device_key_id"]; + $array['device_profile_keys'][$index]['profile_key_category'] = $row["device_key_category"]; + $array['device_profile_keys'][$index]['profile_key_vendor'] = $row["device_key_vendor"]; + $array['device_profile_keys'][$index]['profile_key_type'] = $row["device_key_type"]; + $array['device_profile_keys'][$index]['profile_key_line'] = $row["device_key_line"]; + $array['device_profile_keys'][$index]['profile_key_value'] = $row["device_key_value"]; + $array['device_profile_keys'][$index]['profile_key_extension'] = $row["device_key_extension"]; + $array['device_profile_keys'][$index]['profile_key_protected'] = $row["device_key_protected"]; + $array['device_profile_keys'][$index]['profile_key_label'] = $row["device_key_label"]; + $array['device_profile_keys'][$index]['profile_key_icon'] = $row["device_key_icon"]; + } + } + + //save the array + if (!empty($array)) { + $p = permissions::new(); + $p->add('device_profile_key_add', 'temp'); + + $database->app_name = 'devices'; + $database->app_uuid = '4efa1a1a-32e7-bf83-534b-6c8299958a8e'; + $database->save($array); + $response = $database->message; + unset($array); + + $p->delete('device_profile_key_add', 'temp'); } } - - //save the array - if (!empty($array)) { - $p = permissions::new(); - $p->add('device_profile_key_add', 'temp'); - - $database->app_name = 'devices'; - $database->app_uuid = '4efa1a1a-32e7-bf83-534b-6c8299958a8e'; - $database->save($array); - $response = $database->message; - unset($array); - - $p->delete('device_profile_key_add', 'temp'); - } + unset($sql, $device_profile_keys); } - unset($sql, $device_profile_keys); //set the device profile settings - $sql = "select count(*) from v_device_profile_settings "; - $num_rows = $database->select($sql, null, 'column'); - if ($num_rows == 0) { - //get the device profile keys from device_keys table - $sql = "select * from v_device_settings "; - $sql .= "where device_profile_uuid is not null "; - $device_profile_keys = $database->select($sql, null, 'all'); + if ($database->column_exists('v_device_settings', 'device_profile_uuid')) { + $sql = "select count(*) from v_device_profile_settings "; + $num_rows = $database->select($sql, null, 'column'); + if ($num_rows == 0) { + //get the device profile keys from device_keys table + $sql = "select * from v_device_settings "; + $sql .= "where device_profile_uuid is not null "; + $device_profile_keys = $database->select($sql, null, 'all'); - //loop through the device_keys to build the data array - if (!empty($device_profile_keys)) { - foreach ($device_profile_keys as $index => $row) { - $array['device_profile_settings'][$index]['device_profile_setting_uuid'] = $row["device_setting_uuid"]; - $array['device_profile_settings'][$index]['domain_uuid'] = $row["domain_uuid"]; - $array['device_profile_settings'][$index]['device_profile_uuid'] = $row["device_profile_uuid"]; - $array['device_profile_settings'][$index]['profile_setting_name'] = $row["device_setting_subcategory"]; - $array['device_profile_settings'][$index]['profile_setting_value'] = $row["device_setting_value"]; - $array['device_profile_settings'][$index]['profile_setting_enabled'] = $row["device_setting_enabled"]; - $array['device_profile_settings'][$index]['profile_setting_description'] = $row["device_setting_description"]; + //loop through the device_keys to build the data array + if (!empty($device_profile_keys)) { + foreach ($device_profile_keys as $index => $row) { + $array['device_profile_settings'][$index]['device_profile_setting_uuid'] = $row["device_setting_uuid"]; + $array['device_profile_settings'][$index]['domain_uuid'] = $row["domain_uuid"]; + $array['device_profile_settings'][$index]['device_profile_uuid'] = $row["device_profile_uuid"]; + $array['device_profile_settings'][$index]['profile_setting_name'] = $row["device_setting_subcategory"]; + $array['device_profile_settings'][$index]['profile_setting_value'] = $row["device_setting_value"]; + $array['device_profile_settings'][$index]['profile_setting_enabled'] = $row["device_setting_enabled"]; + $array['device_profile_settings'][$index]['profile_setting_description'] = $row["device_setting_description"]; + } + } + + //save the array + if (!empty($array)) { + $p = permissions::new(); + $p->add('device_profile_setting_add', 'temp'); + + $database->app_name = 'devices'; + $database->app_uuid = '4efa1a1a-32e7-bf83-534b-6c8299958a8e'; + $database->save($array); + $response = $database->message; + unset($array); + + $p->delete('device_profile_setting_add', 'temp'); } } - - //save the array - if (!empty($array)) { - $p = permissions::new(); - $p->add('device_profile_setting_add', 'temp'); - - $database->app_name = 'devices'; - $database->app_uuid = '4efa1a1a-32e7-bf83-534b-6c8299958a8e'; - $database->save($array); - $response = $database->message; - unset($array); - - $p->delete('device_profile_setting_add', 'temp'); - } + unset($sql, $device_profile_keys); } - unset($sql, $device_profile_keys); //add device vendor functions to the database $sql = "select count(*) from v_device_vendors; "; @@ -247,6 +251,7 @@ if ($domains_processed == 1) { $sql = "update v_device_lines set label = display_name where label is null;\n"; $database->execute($sql); unset($sql); + } ?> From 9106c7fbfef0b91c5d52d09d6dd002ccaeb7ed48 Mon Sep 17 00:00:00 2001 From: fusionate Date: Tue, 28 Jan 2025 16:11:21 -0700 Subject: [PATCH 035/196] Contact - Phone: Adjust to even check same contact for duplicate speed dial numbers. --- core/contacts/contact_phone_edit.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/contacts/contact_phone_edit.php b/core/contacts/contact_phone_edit.php index acb196b05f..f204491500 100644 --- a/core/contacts/contact_phone_edit.php +++ b/core/contacts/contact_phone_edit.php @@ -163,9 +163,9 @@ $sql .= "from v_contact_phones "; $sql .= "where phone_speed_dial = :phone_speed_dial "; $sql .= "and domain_uuid = :domain_uuid "; - if ($action == "update") { - $sql .= "and contact_uuid <> :contact_uuid "; - $parameters['contact_uuid'] = $contact_uuid; + if ($action == "update" && is_uuid($contact_phone_uuid)) { + $sql .= "and contact_phone_uuid <> :contact_phone_uuid "; + $parameters['contact_phone_uuid'] = $contact_phone_uuid; } $parameters['phone_speed_dial'] = $phone_speed_dial; $parameters['domain_uuid'] = $domain_uuid; From 3144036ae04044ec31e370dd90c0449fe158fbd2 Mon Sep 17 00:00:00 2001 From: frytimo Date: Tue, 28 Jan 2025 19:20:43 -0400 Subject: [PATCH 036/196] add new menu upgrade option to reset file permissions (#7232) * add new menu upgrade option to reset file permissions --- core/upgrade/app_languages.php | 187 ++++++++++++++++++++++++++++----- core/upgrade/upgrade_menu.php | 68 +++++++++++- 2 files changed, 224 insertions(+), 31 deletions(-) diff --git a/core/upgrade/app_languages.php b/core/upgrade/app_languages.php index 351841051e..74b3d9c625 100644 --- a/core/upgrade/app_languages.php +++ b/core/upgrade/app_languages.php @@ -594,6 +594,33 @@ $text['label-upgrade_permissions']['zh-cn'] = "权限默认值"; $text['label-upgrade_permissions']['ja-jp'] = "許可のデフォルト"; $text['label-upgrade_permissions']['ko-kr'] = "권한 기본값"; +$text['label-update_filesystem_permissions']['en-us'] = "Filesystem Permissions"; +$text['label-update_filesystem_permissions']['en-gb'] = "Filesystem Permissions"; +$text['label-update_filesystem_permissions']['ar-eg'] = ""; +$text['label-update_filesystem_permissions']['de-at'] = ""; +$text['label-update_filesystem_permissions']['de-ch'] = ""; +$text['label-update_filesystem_permissions']['de-de'] = ""; +$text['label-update_filesystem_permissions']['el-gr'] = ""; +$text['label-update_filesystem_permissions']['es-cl'] = ""; +$text['label-update_filesystem_permissions']['es-mx'] = ""; +$text['label-update_filesystem_permissions']['fr-ca'] = ""; +$text['label-update_filesystem_permissions']['fr-fr'] = ""; +$text['label-update_filesystem_permissions']['he-il'] = ""; +$text['label-update_filesystem_permissions']['it-it'] = ""; +$text['label-update_filesystem_permissions']['ka-ge'] = ""; +$text['label-update_filesystem_permissions']['nl-nl'] = ""; +$text['label-update_filesystem_permissions']['pl-pl'] = ""; +$text['label-update_filesystem_permissions']['pt-br'] = ""; +$text['label-update_filesystem_permissions']['pt-pt'] = ""; +$text['label-update_filesystem_permissions']['ro-ro'] = ""; +$text['label-update_filesystem_permissions']['ru-ru'] = ""; +$text['label-update_filesystem_permissions']['sv-se'] = ""; +$text['label-update_filesystem_permissions']['uk-ua'] = ""; +$text['label-update_filesystem_permissions']['tr-tr'] = ""; +$text['label-update_filesystem_permissions']['zh-cn'] = ""; +$text['label-update_filesystem_permissions']['ja-jp'] = ""; +$text['label-update_filesystem_permissions']['ko-kr'] = ""; + $text['label-upgrade_menu']['en-us'] = "Menu Defaults"; $text['label-upgrade_menu']['en-gb'] = "Menu Defaults"; $text['label-upgrade_menu']['ar-eg'] = "افتراضيات القائمة"; @@ -1242,6 +1269,87 @@ $text['description-upgrade_permissions']['zh-cn'] = "还原默认组权限。"; $text['description-upgrade_permissions']['ja-jp'] = "デフォルトのグループ許可を復元します。"; $text['description-upgrade_permissions']['ko-kr'] = "기본 그룹 권한을 복원합니다."; +$text['description-update_filesystem_permissions']['en-us'] = 'Update the filesystem permissions to use user www-data'; +$text['description-update_filesystem_permissions']['en-gb'] = 'Update the filesystem permissions to use user www-data'; +$text['description-update_filesystem_permissions']['ar-eg'] = 'تحديث أذونات نظام الملفات لاستخدام بيانات المستخدم www-data'; +$text['description-update_filesystem_permissions']['de-at'] = 'Aktualisieren Sie die Dateisystemberechtigungen, um den Benutzer www-data zu verwenden'; +$text['description-update_filesystem_permissions']['de-ch'] = 'Aktualisieren Sie die Dateisystemberechtigungen, um den Benutzer www-data zu verwenden'; +$text['description-update_filesystem_permissions']['de-de'] = 'Aktualisieren Sie die Dateisystemberechtigungen, um den Benutzer www-data zu verwenden'; +$text['description-update_filesystem_permissions']['el-gr'] = 'Ενημερώστε τα δικαιώματα του συστήματος αρχείων για να χρησιμοποιήσετε τα www-data χρήστη'; +$text['description-update_filesystem_permissions']['es-cl'] = 'Actualice los permisos del sistema de archivos para utilizar el usuario www-data'; +$text['description-update_filesystem_permissions']['es-mx'] = 'Actualice los permisos del sistema de archivos para utilizar el usuario www-data'; +$text['description-update_filesystem_permissions']['fr-ca'] = 'Mettre à jour les autorisations du système de fichiers pour utiliser l'utilisateur www-data'; +$text['description-update_filesystem_permissions']['fr-fr'] = 'Mettre à jour les autorisations du système de fichiers pour utiliser l'utilisateur www-data'; +$text['description-update_filesystem_permissions']['he-il'] = 'עדכן את הרשאות מערכת הקבצים כדי להשתמש ב-www-data של המשתמש'; +$text['description-update_filesystem_permissions']['it-it'] = 'Aggiornare i permessi del file system per utilizzare l'utente www-data'; +$text['description-update_filesystem_permissions']['ka-ge'] = 'განაახლეთ ფაილური სისტემის ნებართვები მომხმარებლის www-data-ის გამოსაყენებლად'; +$text['description-update_filesystem_permissions']['nl-nl'] = 'Werk de bestandssysteemmachtigingen bij om de gebruiker www-data te gebruiken'; +$text['description-update_filesystem_permissions']['pl-pl'] = 'Zaktualizuj uprawnienia systemu plików, aby użyć użytkownika www-data'; +$text['description-update_filesystem_permissions']['pt-br'] = 'Atualize as permissões do sistema de arquivos para usar o usuário www-data'; +$text['description-update_filesystem_permissions']['pt-pt'] = 'Atualize as permissões do sistema de arquivos para usar o usuário www-data'; +$text['description-update_filesystem_permissions']['ro-ro'] = 'Actualizați permisiunile sistemului de fișiere pentru a utiliza www-data utilizatorului'; +$text['description-update_filesystem_permissions']['ru-ru'] = 'Обновите разрешения файловой системы для использования пользователя www-data'; +$text['description-update_filesystem_permissions']['sv-se'] = 'Uppdatera filsystemets behörigheter för att använda användarens www-data'; +$text['description-update_filesystem_permissions']['uk-ua'] = 'Оновіть дозволи файлової системи, щоб використовувати дані користувача www'; +$text['description-update_filesystem_permissions']['tr-tr'] = 'Dosya sistemi izinlerini www-data kullanıcısını kullanacak şekilde güncelleyin'; +$text['description-update_filesystem_permissions']['zh-cn'] = '更新文件系统权限以使用用户 www-data'; +$text['description-update_filesystem_permissions']['ja-jp'] = 'ユーザーwww-dataを使用するためにファイルシステムの権限を更新します'; +$text['description-update_filesystem_permissions']['ko-kr'] = '사용자 www-data를 사용하기 위해 파일 시스템 권한을 업데이트합니다.'; + +$text['label-header1']['en-us'] = 'Root account or sudo account must be used for this option'; +$text['label-header1']['en-gb'] = 'Root account or sudo account must be used for this option'; +$text['label-header1']['ar-eg'] = 'يجب استخدام حساب الجذر أو حساب sudo لهذا الخيار'; +$text['label-header1']['de-at'] = 'Für diese Option muss ein Root-Konto oder ein Sudo-Konto verwendet werden.'; +$text['label-header1']['de-ch'] = 'Für diese Option muss ein Root-Konto oder ein Sudo-Konto verwendet werden.'; +$text['label-header1']['de-de'] = 'Für diese Option muss ein Root-Konto oder ein Sudo-Konto verwendet werden.'; +$text['label-header1']['el-gr'] = 'Για αυτήν την επιλογή πρέπει να χρησιμοποιηθεί λογαριασμός ρίζας ή λογαριασμός sudo'; +$text['label-header1']['es-cl'] = 'Se debe utilizar una cuenta raíz o una cuenta sudo para esta opción'; +$text['label-header1']['es-mx'] = 'Se debe utilizar una cuenta raíz o una cuenta sudo para esta opción'; +$text['label-header1']['fr-ca'] = 'Un compte root ou un compte sudo doit être utilisé pour cette option'; +$text['label-header1']['fr-fr'] = 'Un compte root ou un compte sudo doit être utilisé pour cette option'; +$text['label-header1']['he-il'] = 'יש להשתמש בחשבון שורש או חשבון sudo עבור אפשרות זו'; +$text['label-header1']['it-it'] = 'Per questa opzione è necessario utilizzare un account root o un account sudo'; +$text['label-header1']['ka-ge'] = 'Root ან sudo ანგარიში უნდა იყოს გამოყენებული ამ ვარიანტისთვის'; +$text['label-header1']['nl-nl'] = 'Voor deze optie moet een root-account of sudo-account worden gebruikt'; +$text['label-header1']['pl-pl'] = 'Do tej opcji należy użyć konta root lub sudo'; +$text['label-header1']['pt-br'] = 'A conta root ou sudo deve ser usada para esta opção'; +$text['label-header1']['pt-pt'] = 'A conta root ou sudo deve ser usada para esta opção'; +$text['label-header1']['ro-ro'] = 'Contul root sau contul sudo trebuie utilizat pentru această opțiune'; +$text['label-header1']['ru-ru'] = 'Для этой опции необходимо использовать учетную запись root или sudo.'; +$text['label-header1']['sv-se'] = 'Root-konto eller sudo-konto måste användas för detta alternativ'; +$text['label-header1']['uk-ua'] = 'Для цієї опції необхідно використовувати обліковий запис root або sudo'; +$text['label-header1']['tr-tr'] = 'Bu seçenek için kök hesap veya sudo hesabı kullanılmalıdır'; +$text['label-header1']['zh-cn'] = '此选项必须使用 root 帐户或 sudo 帐户'; +$text['label-header1']['ja-jp'] = 'このオプションにはルートアカウントまたはsudoアカウントを使用する必要があります'; +$text['label-header1']['ko-kr'] = '이 옵션에는 루트 계정 또는 sudo 계정을 사용해야 합니다.'; + +$text['label-header2']['en-us'] = 'This option is used for resetting the permissions on the file system after executing commands using the root user account'; +$text['label-header2']['en-gb'] = 'This option is used for resetting the permissions on the file system after executing commands using the root user account'; +$text['label-header2']['ar-eg'] = 'يستخدم هذا الخيار لإعادة تعيين الأذونات على نظام الملفات بعد تنفيذ الأوامر باستخدام حساب المستخدم الجذر'; +$text['label-header2']['de-at'] = 'Diese Option wird zum Zurücksetzen der Berechtigungen für das Dateisystem verwendet, nachdem Befehle mit dem Root-Benutzerkonto ausgeführt wurden.'; +$text['label-header2']['de-ch'] = 'Diese Option wird zum Zurücksetzen der Berechtigungen für das Dateisystem verwendet, nachdem Befehle mit dem Root-Benutzerkonto ausgeführt wurden.'; +$text['label-header2']['de-de'] = 'Diese Option wird zum Zurücksetzen der Berechtigungen für das Dateisystem verwendet, nachdem Befehle mit dem Root-Benutzerkonto ausgeführt wurden.'; +$text['label-header2']['el-gr'] = 'Αυτή η επιλογή χρησιμοποιείται για την επαναφορά των δικαιωμάτων στο σύστημα αρχείων μετά την εκτέλεση εντολών χρησιμοποιώντας τον λογαριασμό χρήστη root'; +$text['label-header2']['es-cl'] = 'Esta opción se utiliza para restablecer los permisos en el sistema de archivos después de ejecutar comandos utilizando la cuenta de usuario root'; +$text['label-header2']['es-mx'] = 'Esta opción se utiliza para restablecer los permisos en el sistema de archivos después de ejecutar comandos utilizando la cuenta de usuario root'; +$text['label-header2']['fr-ca'] = 'Cette option est utilisée pour réinitialiser les autorisations sur le système de fichiers après l'exécution de commandes à l'aide du compte utilisateur root'; +$text['label-header2']['fr-fr'] = 'Cette option est utilisée pour réinitialiser les autorisations sur le système de fichiers après l'exécution de commandes à l'aide du compte utilisateur root'; +$text['label-header2']['he-il'] = 'אפשרות זו משמשת לאיפוס ההרשאות במערכת הקבצים לאחר ביצוע פקודות באמצעות חשבון המשתמש השורש'; +$text['label-header2']['it-it'] = 'Questa opzione viene utilizzata per reimpostare i permessi sul file system dopo l'esecuzione di comandi utilizzando l'account utente root'; +$text['label-header2']['ka-ge'] = 'ეს პარამეტრი გამოიყენება ფაილურ სისტემაზე ნებართვების გადატვირთვისთვის ბრძანებების შესრულების შემდეგ root მომხმარებლის ანგარიშის გამოყენებით'; +$text['label-header2']['nl-nl'] = 'Deze optie wordt gebruikt om de machtigingen op het bestandssysteem opnieuw in te stellen na het uitvoeren van opdrachten met behulp van het root-gebruikersaccount'; +$text['label-header2']['pl-pl'] = 'Ta opcja służy do resetowania uprawnień w systemie plików po wykonaniu poleceń przy użyciu konta użytkownika root'; +$text['label-header2']['pt-br'] = 'Esta opção é usada para redefinir as permissões no sistema de arquivos após executar comandos usando a conta de usuário root'; +$text['label-header2']['pt-pt'] = 'Esta opção é usada para redefinir as permissões no sistema de arquivos após executar comandos usando a conta de usuário root'; +$text['label-header2']['ro-ro'] = 'Această opțiune este utilizată pentru resetarea permisiunilor pe sistemul de fișiere după executarea comenzilor folosind contul de utilizator root'; +$text['label-header2']['ru-ru'] = 'Эта опция используется для сброса прав доступа к файловой системе после выполнения команд с использованием учетной записи пользователя root.'; +$text['label-header2']['sv-se'] = 'Det här alternativet används för att återställa behörigheterna på filsystemet efter att ha kört kommandon med root-användarkontot'; +$text['label-header2']['uk-ua'] = 'Цей параметр використовується для скидання дозволів на файлову систему після виконання команд за допомогою облікового запису користувача root'; +$text['label-header2']['tr-tr'] = 'Bu seçenek, kök kullanıcı hesabını kullanarak komutları yürüttükten sonra dosya sistemindeki izinleri sıfırlamak için kullanılır'; +$text['label-header2']['zh-cn'] = '此选项用于在使用 root 用户帐户执行命令后重置文件系统的权限'; +$text['label-header2']['ja-jp'] = 'このオプションは、ルートユーザーアカウントを使用してコマンドを実行した後にファイルシステムの権限をリセットするために使用されます。'; +$text['label-header2']['ko-kr'] = '이 옵션은 root 사용자 계정을 사용하여 명령을 실행한 후 파일 시스템의 권한을 재설정하는 데 사용됩니다.'; + $text['description-upgrade_menu']['en-us'] = "Restores the default items in the menu."; $text['description-upgrade_menu']['en-gb'] = "Restores the default items in the menu."; $text['description-upgrade_menu']['ar-eg'] = ""; @@ -1431,32 +1539,59 @@ $text['label-all_of_the_above']['zh-cn'] = "上述所有的"; $text['label-all_of_the_above']['ja-jp'] = "上記のすべて"; $text['label-all_of_the_above']['ko-kr'] = "무엇보다도"; -$text['description-all_of_the_above']['en-us'] = "Performs an upgrade using options 1a, 2, 2b, 3, 4, and 5 in succession."; -$text['description-all_of_the_above']['en-gb'] = "Performs an upgrade using options 1a, 2, 2b, 3, 4, and 5 in succession."; -$text['description-all_of_the_above']['ar-eg'] = "إجراء ترقية باستخدام الخيارات 1أ، و2، و2ب، و3، و4، و5 على التوالي."; -$text['description-all_of_the_above']['de-at'] = "Führt ein Upgrade mit den Optionen 1a, 2, 2b, 3, 4 und 5 nacheinander durch."; -$text['description-all_of_the_above']['de-ch'] = "Führt ein Upgrade mit den Optionen 1a, 2, 2b, 3, 4 und 5 nacheinander durch."; -$text['description-all_of_the_above']['de-de'] = "Führt ein Upgrade mit den Optionen 1a, 2, 2b, 3, 4 und 5 nacheinander durch."; -$text['description-all_of_the_above']['el-gr'] = "Εκτελεί μια αναβάθμιση χρησιμοποιώντας τις επιλογές 1a, 2, 2b, 3, 4 και 5 διαδοχικά."; -$text['description-all_of_the_above']['es-cl'] = "Realiza una actualización utilizando las opciones 1a, 2, 2b, 3, 4 y 5 en sucesión."; -$text['description-all_of_the_above']['es-mx'] = "Realiza una actualización utilizando las opciones 1a, 2, 2b, 3, 4 y 5 en sucesión."; -$text['description-all_of_the_above']['fr-ca'] = "Effectue une mise à niveau en utilisant successivement les options 1a, 2, 2b, 3, 4 et 5."; -$text['description-all_of_the_above']['fr-fr'] = "Effectue une mise à niveau en utilisant successivement les options 1a, 2, 2b, 3, 4 et 5."; -$text['description-all_of_the_above']['he-il'] = "מבצע שדרוג באמצעות אפשרויות 1a, 2, 2b, 3, 4 ו-5 ברצף."; -$text['description-all_of_the_above']['it-it'] = "Esegue un aggiornamento utilizzando le opzioni 1a, 2, 2b, 3, 4 e 5 in successione."; -$text['description-all_of_the_above']['ka-ge'] = "შეასრულებს განახლებას არჩევნებით 1ა, 2, 2ბ, 3, 4 და 5 ამ მიმდევრობით."; -$text['description-all_of_the_above']['nl-nl'] = "Voert een upgrade uit met achtereenvolgens de opties 1a, 2, 2b, 3, 4 en 5."; -$text['description-all_of_the_above']['pl-pl'] = "Wykonuje aktualizację, korzystając kolejno z opcji 1a, 2, 2b, 3, 4 i 5."; -$text['description-all_of_the_above']['pt-br'] = "Executa uma atualização usando as opções 1a, 2, 2b, 3, 4 e 5 em sucessão."; -$text['description-all_of_the_above']['pt-pt'] = "Executa uma atualização usando as opções 1a, 2, 2b, 3, 4 e 5 em sucessão."; -$text['description-all_of_the_above']['ro-ro'] = "Efectuează o actualizare folosind opțiunile 1a, 2, 2b, 3, 4 și 5 succesiv."; -$text['description-all_of_the_above']['ru-ru'] = "Выполняет обновление, последовательно используя параметры 1a, 2, 2b, 3, 4 и 5."; -$text['description-all_of_the_above']['sv-se'] = "Utför en uppgradering med alternativ 1a, 2, 2b, 3, 4 och 5 i följd."; -$text['description-all_of_the_above']['uk-ua'] = "Виконує оновлення, використовуючи послідовно параметри 1a, 2, 2b, 3, 4 і 5."; -$text['description-all_of_the_above']['tr-tr'] = "Art arda 1a, 2, 2b, 3, 4 ve 5 seçeneklerini kullanarak yükseltme gerçekleştirir."; -$text['description-all_of_the_above']['zh-cn'] = "连续使用选项 1a、2、2b、3、4 和 5 执行升级。"; -$text['description-all_of_the_above']['ja-jp'] = "オプション 1a、2、2b、3、4、および 5 を連続して使用してアップグレードを実行します。"; -$text['description-all_of_the_above']['ko-kr'] = "옵션 1a, 2, 2b, 3, 4, 5를 차례로 사용하여 업그레이드를 수행합니다."; +$text['label-not_running_as_root']['en-us'] = 'Not root user - operation skipped'; +$text['label-not_running_as_root']['en-gb'] = 'Not root user - operation skipped'; +$text['label-not_running_as_root']['ar-eg'] = 'ليس مستخدمًا جذريًا - تم تخطي العملية'; +$text['label-not_running_as_root']['de-at'] = 'Kein Root-Benutzer – Vorgang übersprungen'; +$text['label-not_running_as_root']['de-ch'] = 'Kein Root-Benutzer – Vorgang übersprungen'; +$text['label-not_running_as_root']['de-de'] = 'Kein Root-Benutzer – Vorgang übersprungen'; +$text['label-not_running_as_root']['el-gr'] = 'Δεν είναι χρήστης root - η λειτουργία παραβλέφθηκε'; +$text['label-not_running_as_root']['es-cl'] = 'No es usuario root: se omitió la operación'; +$text['label-not_running_as_root']['es-mx'] = 'No es usuario root: se omitió la operación'; +$text['label-not_running_as_root']['fr-ca'] = 'Pas d'utilisateur root - opération ignorée'; +$text['label-not_running_as_root']['fr-fr'] = 'Pas d'utilisateur root - opération ignorée'; +$text['label-not_running_as_root']['he-il'] = 'לא משתמש שורש - הפעולה דילגה'; +$text['label-not_running_as_root']['it-it'] = 'Utente non root: operazione saltata'; +$text['label-not_running_as_root']['ka-ge'] = 'არ არის root მომხმარებელი - ოპერაცია გამოტოვებულია'; +$text['label-not_running_as_root']['nl-nl'] = 'Geen rootgebruiker - bewerking overgeslagen'; +$text['label-not_running_as_root']['pl-pl'] = 'Nie użytkownik root - operacja pominięta'; +$text['label-not_running_as_root']['pt-br'] = 'Usuário não root - operação ignorada'; +$text['label-not_running_as_root']['pt-pt'] = 'Usuário não root - operação ignorada'; +$text['label-not_running_as_root']['ro-ro'] = 'Nu utilizatorul root - operația a fost omisă'; +$text['label-not_running_as_root']['ru-ru'] = 'Не пользователь root — операция пропущена'; +$text['label-not_running_as_root']['sv-se'] = 'Inte root-användare - åtgärden hoppades över'; +$text['label-not_running_as_root']['uk-ua'] = 'Не root користувач - операцію пропущено'; +$text['label-not_running_as_root']['tr-tr'] = 'Kök kullanıcı değil - işlem atlandı'; +$text['label-not_running_as_root']['zh-cn'] = '非 root 用户 – 操作已跳过'; +$text['label-not_running_as_root']['ja-jp'] = 'ルートユーザーではありません - 操作はスキップされました'; +$text['label-not_running_as_root']['ko-kr'] = '루트 사용자가 아닙니다. 작업이 건너뛰어졌습니다.'; + +$text['description-all_of_the_above']['en-us'] = 'Performs an upgrade using options 1a, 2, 2b, 3, 4, 5, and 6 in succession.'; +$text['description-all_of_the_above']['en-gb'] = 'Performs an upgrade using options 1a, 2, 2b, 3, 4, 5, and 6 in succession.'; +$text['description-all_of_the_above']['ar-eg'] = 'يقوم بإجراء ترقية باستخدام الخيارات 1أ، 2، 2ب، 3، 4، 5، و6 على التوالي.'; +$text['description-all_of_the_above']['de-at'] = 'Führt ein Upgrade nacheinander mit den Optionen 1a, 2, 2b, 3, 4, 5 und 6 durch.'; +$text['description-all_of_the_above']['de-ch'] = 'Führt ein Upgrade nacheinander mit den Optionen 1a, 2, 2b, 3, 4, 5 und 6 durch.'; +$text['description-all_of_the_above']['de-de'] = 'Führt ein Upgrade nacheinander mit den Optionen 1a, 2, 2b, 3, 4, 5 und 6 durch.'; +$text['description-all_of_the_above']['el-gr'] = 'Εκτελεί μια αναβάθμιση χρησιμοποιώντας τις επιλογές 1a, 2, 2b, 3, 4, 5 και 6 διαδοχικά.'; +$text['description-all_of_the_above']['es-cl'] = 'Realiza una actualización utilizando las opciones 1a, 2, 2b, 3, 4, 5 y 6 en sucesión.'; +$text['description-all_of_the_above']['es-mx'] = 'Realiza una actualización utilizando las opciones 1a, 2, 2b, 3, 4, 5 y 6 en sucesión.'; +$text['description-all_of_the_above']['fr-ca'] = 'Effectue une mise à niveau en utilisant successivement les options 1a, 2, 2b, 3, 4, 5 et 6.'; +$text['description-all_of_the_above']['fr-fr'] = 'Effectue une mise à niveau en utilisant successivement les options 1a, 2, 2b, 3, 4, 5 et 6.'; +$text['description-all_of_the_above']['he-il'] = 'מבצע שדרוג באמצעות אפשרויות 1a, 2, 2b, 3, 4, 5 ו-6 ברצף.'; +$text['description-all_of_the_above']['it-it'] = 'Esegue un aggiornamento utilizzando le opzioni 1a, 2, 2b, 3, 4, 5 e 6 in successione.'; +$text['description-all_of_the_above']['ka-ge'] = 'განაახლებს ზედიზედ 1a, 2, 2b, 3, 4, 5 და 6 ვარიანტების გამოყენებით.'; +$text['description-all_of_the_above']['nl-nl'] = 'Voert een upgrade uit met behulp van opties 1a, 2, 2b, 3, 4, 5 en 6 achtereenvolgens.'; +$text['description-all_of_the_above']['pl-pl'] = 'Wykonuje aktualizację, korzystając kolejno z opcji 1a, 2, 2b, 3, 4, 5 i 6.'; +$text['description-all_of_the_above']['pt-br'] = 'Executa uma atualização usando as opções 1a, 2, 2b, 3, 4, 5 e 6 em sucessão.'; +$text['description-all_of_the_above']['pt-pt'] = 'Executa uma atualização usando as opções 1a, 2, 2b, 3, 4, 5 e 6 em sucessão.'; +$text['description-all_of_the_above']['ro-ro'] = 'Efectuează o actualizare folosind opțiunile 1a, 2, 2b, 3, 4, 5 și 6 succesiv.'; +$text['description-all_of_the_above']['ru-ru'] = 'Выполняет обновление, последовательно используя опции 1a, 2, 2b, 3, 4, 5 и 6.'; +$text['description-all_of_the_above']['sv-se'] = 'Utför en uppgradering med alternativ 1a, 2, 2b, 3, 4, 5 och 6 i följd.'; +$text['description-all_of_the_above']['uk-ua'] = 'Виконує оновлення, використовуючи послідовно параметри 1a, 2, 2b, 3, 4, 5 і 6.'; +$text['description-all_of_the_above']['tr-tr'] = '1a, 2, 2b, 3, 4, 5 ve 6 seçeneklerini sırayla kullanarak yükseltme gerçekleştirir.'; +$text['description-all_of_the_above']['zh-cn'] = '连续使用选项 1a、2、2b、3、4、5 和 6 执行升级。'; +$text['description-all_of_the_above']['ja-jp'] = 'オプション 1a、2、2b、3、4、5、6 を順番に使用してアップグレードを実行します。'; +$text['description-all_of_the_above']['ko-kr'] = '옵션 1a, 2, 2b, 3, 4, 5, 6을 연속으로 사용하여 업그레이드를 수행합니다.'; $text['label-update_external_repositories']['en-us'] = "Update External Repositories"; $text['label-update_external_repositories']['en-gb'] = "Update External Repositories"; diff --git a/core/upgrade/upgrade_menu.php b/core/upgrade/upgrade_menu.php index d31cf558ab..84c2115aca 100644 --- a/core/upgrade/upgrade_menu.php +++ b/core/upgrade/upgrade_menu.php @@ -33,7 +33,8 @@ defined('STDIN') or die('Unauthorized'); require_once dirname(__DIR__, 2) . "/resources/require.php"; //create a database connection using default config -$database = new database(); +$config = config::load(); +$database = database::new(['config' => $config]); //load global defaults $settings = new settings(['database' => $database]); @@ -58,7 +59,7 @@ $display_type = 'text'; show_upgrade_menu(); function show_upgrade_menu() { - global $text, $software_name; + global $text, $software_name, $settings; //error_reporting(E_ALL); $line = str_repeat('-', strlen($text['title-cli_upgrade']) + 2); while (true) { @@ -76,7 +77,8 @@ function show_upgrade_menu() { echo "3) {$text['label-upgrade_apps']} - {$text['description-upgrade_apps']}\n"; echo "4) {$text['label-upgrade_menu']} - {$text['description-upgrade_menu']}\n"; echo "5) {$text['label-upgrade_permissions']} - {$text['description-upgrade_permissions']}\n"; - echo "6) {$text['label-all_of_the_above']} - {$text['description-all_of_the_above']}\n"; + echo "6) {$text['label-update_filesystem_permissions']} - {$text['description-update_filesystem_permissions']}\n"; + echo "7) {$text['label-all_of_the_above']} - {$text['description-all_of_the_above']}\n"; echo "0) Exit\n"; echo "\n"; echo "Choice: "; @@ -108,11 +110,15 @@ function show_upgrade_menu() { do_upgrade_permissions(); break; case 6: + do_filesystem_permissions($text, $settings); + break; + case 7: do_upgrade_code(); do_upgrade_schema(); do_upgrade_domains(); do_upgrade_menu(); do_upgrade_permissions(); + do_filesystem_permissions($text, $settings); break; case 8: break; @@ -122,6 +128,58 @@ function show_upgrade_menu() { } } +function do_filesystem_permissions($text, settings $settings) { + + echo ($text['label-header1'] ?? "Root account or sudo account must be used for this option") . "\n"; + echo ($text['label-header2'] ?? "This option is used for resetting the permissions on the filesystem after executing commands using the root user account") . "\n"; + if (is_root_user()) { + $directories = []; + //get the fusionpbx folder + $project_root = dirname(__DIR__, 2); + //adjust the project root + $directories[] = $project_root; + //adjust the /etc/freeswitch + $directories[] = $settings->get('switch', 'conf', null); + $directories[] = $settings->get('switch', 'call_center', null); //normally in conf but can be different + $directories[] = $settings->get('switch', 'dialplan', null); //normally in conf but can be different + $directories[] = $settings->get('switch', 'directory', null); //normally in conf but can be different + $directories[] = $settings->get('switch', 'languages', null); //normally in conf but can be different + $directories[] = $settings->get('switch', 'sip_profiles', null); //normally in conf but can be different + //adjust the /usr/share/freeswitch/{scripts,sounds} + $directories[] = $settings->get('switch', 'scripts', null); + $directories[] = $settings->get('switch', 'sounds', null); + //adjust the /var/lib/freeswitch/{db,recordings,storage,voicemail} + $directories[] = $settings->get('switch', 'db', null); + $directories[] = $settings->get('switch', 'recordings', null); + $directories[] = $settings->get('switch', 'storage', null); + $directories[] = $settings->get('switch', 'voicemail', null); //normally included in storage but can be different + //only set the xml_cdr directory permissions + $log_directory = $settings->get('switch', 'log', null); + if ($log_directory !== null) { + $directories[] = $log_directory . '/xml_cdr'; + } + //execute chown command for each directory + foreach ($directories as $dir) { + if ($dir !== null) { + //notify user + echo "chown -R www-data:www-data $dir\n"; + //execute + exec("chown -R www-data:www-data $dir"); + } + } + } else { + echo ($text['label-not_running_as_root'] ?? "Not root user - operation skipped")."\n"; + } +} + +function is_root_user(): bool { + return posix_getuid() === 0; +} + +function current_user(): ?string { + return posix_getpwuid(posix_getuid())['name'] ?? null; +} + //show the upgrade type function show_software_version() { echo software::version() . "\n"; @@ -334,8 +392,8 @@ function load_config_php() { $conf .= "xml_handler.reg_as_number_alias = false\n"; $conf .= "xml_handler.number_as_presence_id = true\n"; $conf .= "\n"; - $conf .= "#error reporting hide show all errors except notices and warnings\n"; - $conf .= "error.reporting = 'E_ALL ^ E_NOTICE ^ E_WARNING'\n"; + $conf .= "#error reporting hide all errors\n"; + $conf .= "error.reporting = user\n"; //write the config file $file_handle = fopen($config_file, "w"); From 964865ae632ffb76d604b79a584d769a318f7b1f Mon Sep 17 00:00:00 2001 From: chansizzle <14916599+chansizzle@users.noreply.github.com> Date: Tue, 28 Jan 2025 16:22:02 -0700 Subject: [PATCH 037/196] add xml statistics mouse over text and use languages variables (#7211) * add xml statistics mouse over text and use languages variables * add xml statistics mouse over text and use languages variables * xml statistics - remove English words from non-English languages --- app/xml_cdr/app_languages.php | 130 +++++++++++++++++++++++++++++ app/xml_cdr/xml_cdr_statistics.php | 6 +- 2 files changed, 133 insertions(+), 3 deletions(-) diff --git a/app/xml_cdr/app_languages.php b/app/xml_cdr/app_languages.php index a293590e66..19dde926d7 100644 --- a/app/xml_cdr/app_languages.php +++ b/app/xml_cdr/app_languages.php @@ -243,6 +243,32 @@ $text['label-name']['zh-cn'] = "姓名"; $text['label-name']['ja-jp'] = "名前"; $text['label-name']['ko-kr'] = "이름"; +$text['label-volume']['en-us'] = "Volume"; +$text['label-volume']['en-gb'] = "Volume"; +$text['label-volume']['ar-eg'] = ""; +$text['label-volume']['de-at'] = ""; +$text['label-volume']['de-ch'] = ""; +$text['label-volume']['de-de'] = ""; +$text['label-volume']['el-gr'] = ""; +$text['label-volume']['es-cl'] = ""; +$text['label-volume']['es-mx'] = ""; +$text['label-volume']['fr-ca'] = ""; +$text['label-volume']['fr-fr'] = ""; +$text['label-volume']['he-il'] = ""; +$text['label-volume']['it-it'] = ""; +$text['label-volume']['nl-nl'] = ""; +$text['label-volume']['pl-pl'] = ""; +$text['label-volume']['pt-br'] = ""; +$text['label-volume']['pt-pt'] = ""; +$text['label-volume']['ro-ro'] = ""; +$text['label-volume']['ru-ru'] = ""; +$text['label-volume']['sv-se'] = ""; +$text['label-volume']['uk-ua'] = ""; +$text['label-volume']['tr-tr'] = ""; +$text['label-volume']['zh-cn'] = ""; +$text['label-volume']['ja-jp'] = ""; +$text['label-volume']['ko-kr'] = ""; + $text['label-minutes']['en-us'] = "Minutes"; $text['label-minutes']['en-gb'] = "Minutes"; $text['label-minutes']['ar-eg'] = "دقائق"; @@ -3240,6 +3266,32 @@ $text['label-answer']['zh-cn'] = "回答"; $text['label-answer']['ja-jp'] = "答え"; $text['label-answer']['ko-kr'] = "答え"; +$text['label-asr']['en-us'] = "ASR"; +$text['label-asr']['en-gb'] = "ASR"; +$text['label-asr']['ar-eg'] = ""; +$text['label-asr']['de-at'] = ""; +$text['label-asr']['de-ch'] = ""; +$text['label-asr']['de-de'] = ""; +$text['label-asr']['el-gr'] = ""; +$text['label-asr']['es-cl'] = ""; +$text['label-asr']['es-mx'] = ""; +$text['label-asr']['fr-ca'] = ""; +$text['label-asr']['fr-fr'] = ""; +$text['label-asr']['he-il'] = ""; +$text['label-asr']['it-it'] = ""; +$text['label-asr']['nl-nl'] = ""; +$text['label-asr']['pl-pl'] = ""; +$text['label-asr']['pt-br'] = ""; +$text['label-asr']['pt-pt'] = ""; +$text['label-asr']['ro-ro'] = ""; +$text['label-asr']['ru-ru'] = ""; +$text['label-asr']['sv-se'] = ""; +$text['label-asr']['uk-ua'] = ""; +$text['label-asr']['tr-tr'] = ""; +$text['label-asr']['zh-cn'] = ""; +$text['label-asr']['ja-jp'] = ""; +$text['label-asr']['ko-kr'] = ""; + $text['label-aloc']['en-us'] = "ALOC"; $text['label-aloc']['en-gb'] = "ALOC"; $text['label-aloc']['ar-eg'] = "ALOC"; @@ -3672,6 +3724,84 @@ $text['description-mos']['zh-cn'] = "平均意见得分"; $text['description-mos']['ja-jp'] = "平均意見スコア"; $text['description-mos']['ko-kr'] = "평균 의견 점수"; +$text['description-volume']['en-us'] = "Inbound, Outbound, and Local"; +$text['description-volume']['en-gb'] = "Inbound, Outbound, and Local"; +$text['description-volume']['ar-eg'] = ""; +$text['description-volume']['de-at'] = ""; +$text['description-volume']['de-ch'] = ""; +$text['description-volume']['de-de'] = ""; +$text['description-volume']['el-gr'] = ""; +$text['description-volume']['es-cl'] = ""; +$text['description-volume']['es-mx'] = ""; +$text['description-volume']['fr-ca'] = ""; +$text['description-volume']['fr-fr'] = ""; +$text['description-volume']['he-il'] = ""; +$text['description-volume']['it-it'] = ""; +$text['description-volume']['nl-nl'] = ""; +$text['description-volume']['pl-pl'] = ""; +$text['description-volume']['pt-br'] = ""; +$text['description-volume']['pt-pt'] = ""; +$text['description-volume']['ro-ro'] = ""; +$text['description-volume']['ru-ru'] = ""; +$text['description-volume']['sv-se'] = ""; +$text['description-volume']['uk-ua'] = ""; +$text['description-volume']['tr-tr'] = ""; +$text['description-volume']['zh-cn'] = ""; +$text['description-volume']['ja-jp'] = ""; +$text['description-volume']['ko-kr'] = ""; + +$text['description-calls-per-minute']['en-us'] = "average minutes / calls per minute answered"; +$text['description-calls-per-minute']['en-gb'] = "average minutes / calls per minute answered"; +$text['description-calls-per-minute']['ar-eg'] = ""; +$text['description-calls-per-minute']['de-at'] = ""; +$text['description-calls-per-minute']['de-ch'] = ""; +$text['description-calls-per-minute']['de-de'] = ""; +$text['description-calls-per-minute']['el-gr'] = ""; +$text['description-calls-per-minute']['es-cl'] = ""; +$text['description-calls-per-minute']['es-mx'] = ""; +$text['description-calls-per-minute']['fr-ca'] = ""; +$text['description-calls-per-minute']['fr-fr'] = ""; +$text['description-calls-per-minute']['he-il'] = ""; +$text['description-calls-per-minute']['it-it'] = ""; +$text['description-calls-per-minute']['nl-nl'] = ""; +$text['description-calls-per-minute']['pl-pl'] = ""; +$text['description-calls-per-minute']['pt-br'] = ""; +$text['description-calls-per-minute']['pt-pt'] = ""; +$text['description-calls-per-minute']['ro-ro'] = ""; +$text['description-calls-per-minute']['ru-ru'] = ""; +$text['description-calls-per-minute']['sv-se'] = ""; +$text['description-calls-per-minute']['uk-ua'] = ""; +$text['description-calls-per-minute']['tr-tr'] = ""; +$text['description-calls-per-minute']['zh-cn'] = ""; +$text['description-calls-per-minute']['ja-jp'] = ""; +$text['description-calls-per-minute']['ko-kr'] = ""; + +$text['description-asr']['en-us'] = "Answer-Seizure Ratio (% of calls answered)"; +$text['description-asr']['en-gb'] = "Answer-Seizure Ratio (% of calls answered)"; +$text['description-asr']['ar-eg'] = ""; +$text['description-asr']['de-at'] = ""; +$text['description-asr']['de-ch'] = ""; +$text['description-asr']['de-de'] = ""; +$text['description-asr']['el-gr'] = ""; +$text['description-asr']['es-cl'] = ""; +$text['description-asr']['es-mx'] = ""; +$text['description-asr']['fr-ca'] = ""; +$text['description-asr']['fr-fr'] = ""; +$text['description-asr']['he-il'] = ""; +$text['description-asr']['it-it'] = ""; +$text['description-asr']['nl-nl'] = ""; +$text['description-asr']['pl-pl'] = ""; +$text['description-asr']['pt-br'] = ""; +$text['description-asr']['pt-pt'] = ""; +$text['description-asr']['ro-ro'] = ""; +$text['description-asr']['ru-ru'] = ""; +$text['description-asr']['sv-se'] = ""; +$text['description-asr']['uk-ua'] = ""; +$text['description-asr']['tr-tr'] = ""; +$text['description-asr']['zh-cn'] = ""; +$text['description-asr']['ja-jp'] = ""; +$text['description-asr']['ko-kr'] = ""; + $text['description-aloc']['en-us'] = "Average Length of Call"; $text['description-aloc']['en-gb'] = "Average Length of Call"; $text['description-aloc']['ar-eg'] = "متوسط طول المحادثة"; diff --git a/app/xml_cdr/xml_cdr_statistics.php b/app/xml_cdr/xml_cdr_statistics.php index 37b7247804..c90285e111 100644 --- a/app/xml_cdr/xml_cdr_statistics.php +++ b/app/xml_cdr/xml_cdr_statistics.php @@ -281,11 +281,11 @@ echo " ".$text['label-hours']."\n"; echo " ".$text['label-date']."\n"; echo " ".$text['label-time']."\n"; - echo " Volume\n"; + echo " ".$text['label-volume']."\n"; echo " ".$text['label-minutes']."\n"; - echo " ".$text['label-calls-per-minute']."\n"; + echo " ".$text['label-calls-per-minute']."\n"; echo " ".$text['label-missed']."\n"; - echo " ASR\n"; + echo " ".$text['label-asr']."\n"; echo " ".$text['label-aloc']."\n"; echo "\n"; From bb1006aca86b7cf8ddd50f6ea94b2229332dd38e Mon Sep 17 00:00:00 2001 From: denisent <120752864+denisent@users.noreply.github.com> Date: Tue, 28 Jan 2025 15:26:32 -0800 Subject: [PATCH 038/196] Add serial number to the device edit page (#7234) * add device serial number * add device serial number field * add device serial number field --- app/devices/app_config.php | 8 ++++++ app/devices/app_languages.php | 52 +++++++++++++++++++++++++++++++++++ app/devices/device_edit.php | 18 ++++++++++++ 3 files changed, 78 insertions(+) diff --git a/app/devices/app_config.php b/app/devices/app_config.php index da31452c5a..a346b9fd38 100644 --- a/app/devices/app_config.php +++ b/app/devices/app_config.php @@ -224,6 +224,9 @@ $apps[$x]['permissions'][$y]['groups'][] = "superadmin"; $apps[$x]['permissions'][$y]['groups'][] = "admin"; $y++; + $apps[$x]['permissions'][$y]['name'] = "device_serial_number"; + $apps[$x]['permissions'][$y]['groups'][] = "superadmin"; + $y++; $apps[$x]['permissions'][$y]['name'] = "device_model"; //$apps[$x]['permissions'][$y]['groups'][] = "superadmin"; $y++; @@ -462,6 +465,11 @@ $apps[$x]['db'][$y]['fields'][$z]['search'] = 'true'; $apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = ""; $z++; + $apps[$x]['db'][$y]['fields'][$z]['name'] = "device_serial_number"; + $apps[$x]['db'][$y]['fields'][$z]['type'] = "text"; + $apps[$x]['db'][$y]['fields'][$z]['search'] = 'true'; + $apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = ""; + $z++; $apps[$x]['db'][$y]['fields'][$z]['name']['text'] = "device_model"; $apps[$x]['db'][$y]['fields'][$z]['name']['deprecated'] = "phone_model"; $apps[$x]['db'][$y]['fields'][$z]['type'] = "text"; diff --git a/app/devices/app_languages.php b/app/devices/app_languages.php index a1893028e9..1fe1aa92be 100644 --- a/app/devices/app_languages.php +++ b/app/devices/app_languages.php @@ -3198,6 +3198,32 @@ $text['label-device_location']['zh-cn'] = "地点"; $text['label-device_location']['ja-jp'] = "位置"; $text['label-device_location']['ko-kr'] = "위치"; +$text['label-device_serial_number']['en-us'] = "Serial Number"; +$text['label-device_serial_number']['en-gb'] = "Serial Number"; +$text['label-device_serial_number']['ar-eg'] = ""; +$text['label-device_serial_number']['de-at'] = ""; +$text['label-device_serial_number']['de-ch'] = ""; +$text['label-device_serial_number']['de-de'] = ""; +$text['label-device_serial_number']['el-gr'] = ""; +$text['label-device_serial_number']['es-cl'] = ""; +$text['label-device_serial_number']['es-mx'] = ""; +$text['label-device_serial_number']['fr-ca'] = ""; +$text['label-device_serial_number']['fr-fr'] = ""; +$text['label-device_serial_number']['he-il'] = ""; +$text['label-device_serial_number']['it-it'] = ""; +$text['label-device_serial_number']['ka-ge'] = ""; +$text['label-device_serial_number']['nl-nl'] = ""; +$text['label-device_serial_number']['pl-pl'] = ""; +$text['label-device_serial_number']['pt-br'] = ""; +$text['label-device_serial_number']['pt-pt'] = ""; +$text['label-device_serial_number']['ro-ro'] = ""; +$text['label-device_serial_number']['ru-ru'] = ""; +$text['label-device_serial_number']['sv-se'] = ""; +$text['label-device_serial_number']['uk-ua'] = ""; +$text['label-device_serial_number']['zh-cn'] = ""; +$text['label-device_serial_number']['ja-jp'] = ""; +$text['label-device_serial_number']['ko-kr'] = ""; + $text['label-device_key_vendor']['en-us'] = "Vendor"; $text['label-device_key_vendor']['en-gb'] = "Vendor"; $text['label-device_key_vendor']['ar-eg'] = "البائع"; @@ -6634,6 +6660,32 @@ $text['description-device_location']['zh-cn'] = "输入设备位置。"; $text['description-device_location']['ja-jp'] = "デバイスの場所を入力します。"; $text['description-device_location']['ko-kr'] = "장치 위치를 입력합니다."; +$text['description-device_serial_number']['en-us'] = "Enter the device serial number."; +$text['description-device_serial_number']['en-gb'] = "Enter the device serial number."; +$text['description-device_serial_number']['ar-eg'] = ""; +$text['description-device_serial_number']['de-at'] = ""; +$text['description-device_serial_number']['de-ch'] = ""; +$text['description-device_serial_number']['de-de'] = ""; +$text['description-device_serial_number']['el-gr'] = ""; +$text['description-device_serial_number']['es-cl'] = ""; +$text['description-device_serial_number']['es-mx'] = ""; +$text['description-device_serial_number']['fr-ca'] = ""; +$text['description-device_serial_number']['fr-fr'] = ""; +$text['description-device_serial_number']['he-il'] = ""; +$text['description-device_serial_number']['it-it'] = ""; +$text['description-device_serial_number']['ka-ge'] = ""; +$text['description-device_serial_number']['nl-nl'] = ""; +$text['description-device_serial_number']['pl-pl'] = ""; +$text['description-device_serial_number']['pt-br'] = ""; +$text['description-device_serial_number']['pt-pt'] = ""; +$text['description-device_serial_number']['ro-ro'] = ""; +$text['description-device_serial_number']['ru-ru'] = ""; +$text['description-device_serial_number']['sv-se'] = ""; +$text['description-device_serial_number']['uk-ua'] = ""; +$text['description-device_serial_number']['zh-cn'] = ""; +$text['description-device_serial_number']['ja-jp'] = ""; +$text['description-device_serial_number']['ko-kr'] = ""; + $text['description-device_time_zone']['en-us'] = "Enter the time zone."; $text['description-device_time_zone']['en-gb'] = "Enter the time zone."; $text['description-device_time_zone']['ar-eg'] = "أدخل المنطقة الزمنية"; diff --git a/app/devices/device_edit.php b/app/devices/device_edit.php index f058c0becb..b8cedfff56 100644 --- a/app/devices/device_edit.php +++ b/app/devices/device_edit.php @@ -124,6 +124,7 @@ $device_password = $_POST["device_password"]; $device_vendor = $_POST["device_vendor"]; $device_location = $_POST["device_location"]; + $device_serial_number = $_POST["device_serial_number"]; $device_uuid_alternate = $_POST["device_uuid_alternate"] ?? null; $device_model = $_POST["device_model"] ?? null; $device_firmware_version = $_POST["device_firmware_version"] ?? null; @@ -269,6 +270,9 @@ if (permission_exists('device_location')) { $array['devices'][0]['device_location'] = $device_location; } + if (permission_exists('device_serial_number')) { + $array['devices'][0]['device_serial_number'] = $device_serial_number; + } if (permission_exists('device_alternate')) { $array['devices'][0]['device_uuid_alternate'] = is_uuid($device_uuid_alternate) ? $device_uuid_alternate : null; } @@ -521,6 +525,7 @@ $device_password = $row["device_password"]; $device_vendor = $row["device_vendor"]; $device_location = $row["device_location"]; + $device_serial_number = $row["device_serial_number"]; $device_uuid_alternate = $row["device_uuid_alternate"]; $device_model = $row["device_model"]; $device_firmware_version = $row["device_firmware_version"]; @@ -1915,6 +1920,19 @@ echo "\n"; } + if (permission_exists('device_serial_number')) { + echo "\n"; + echo "\n"; + echo " ".$text['label-device_serial_number']."\n"; + echo "\n"; + echo "\n"; + echo " \n"; + echo "
\n"; + echo $text['description-device_serial_number']."\n"; + echo "\n"; + echo "\n"; + } + if (permission_exists('device_model')) { echo "\n"; echo "\n"; From b2349060b591d8c59589112c4cb26d85f2691c86 Mon Sep 17 00:00:00 2001 From: Alex <40072887+alexdcrane@users.noreply.github.com> Date: Tue, 28 Jan 2025 16:39:35 -0700 Subject: [PATCH 039/196] Fix number text and background color not applying (#7235) * Fix number text and background color not applying * Update registrations.php * Update voicemails.php * Update missed_calls.php * Update recent_calls.php * Update domains.php --- app/registrations/resources/dashboard/registrations.php | 2 +- app/voicemails/resources/dashboard/voicemails.php | 2 +- app/xml_cdr/resources/dashboard/missed_calls.php | 2 +- app/xml_cdr/resources/dashboard/recent_calls.php | 2 +- core/dashboard/index.php | 2 ++ core/domains/resources/dashboard/domains.php | 2 +- 6 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/registrations/resources/dashboard/registrations.php b/app/registrations/resources/dashboard/registrations.php index 44ea55ed3f..417174b3a0 100644 --- a/app/registrations/resources/dashboard/registrations.php +++ b/app/registrations/resources/dashboard/registrations.php @@ -55,7 +55,7 @@ echo " ".escape($dashboard_label).""; echo "
\n"; echo " \n"; - echo " ".$active_registrations." / ".($active_registrations + $inactive_registrations)."\n"; + echo " ".$active_registrations." / ".($active_registrations + $inactive_registrations)."\n"; echo "
\n"; echo " \n"; if (empty($dashboard_details_state) || $dashboard_details_state != "disabled") { diff --git a/app/voicemails/resources/dashboard/voicemails.php b/app/voicemails/resources/dashboard/voicemails.php index 9c5b571c08..d3665ae467 100644 --- a/app/voicemails/resources/dashboard/voicemails.php +++ b/app/voicemails/resources/dashboard/voicemails.php @@ -111,7 +111,7 @@ echo "\n"; echo "
\n"; echo " \n"; - echo " ".$messages['new']."\n"; + echo " ".$messages['new']."\n"; echo "
\n"; echo "
"; } diff --git a/app/xml_cdr/resources/dashboard/missed_calls.php b/app/xml_cdr/resources/dashboard/missed_calls.php index 80b3378c2d..d52fd832c1 100644 --- a/app/xml_cdr/resources/dashboard/missed_calls.php +++ b/app/xml_cdr/resources/dashboard/missed_calls.php @@ -149,7 +149,7 @@ echo "\n"; echo "
\n"; echo " \n"; - echo " ".$num_rows."\n"; + echo " ".$num_rows."\n"; echo "
\n"; echo "
"; } diff --git a/app/xml_cdr/resources/dashboard/recent_calls.php b/app/xml_cdr/resources/dashboard/recent_calls.php index 8de16e74cb..135b4fd8a7 100644 --- a/app/xml_cdr/resources/dashboard/recent_calls.php +++ b/app/xml_cdr/resources/dashboard/recent_calls.php @@ -147,7 +147,7 @@ echo "
\n"; echo "
\n"; echo " \n"; - echo " ".$num_rows."\n"; + echo " ".$num_rows."\n"; echo "
\n"; echo "
"; } diff --git a/core/dashboard/index.php b/core/dashboard/index.php index 9e28e1f689..606832bbff 100644 --- a/core/dashboard/index.php +++ b/core/dashboard/index.php @@ -533,6 +533,7 @@ function toggle_grid_row_end_all() { $dashboard_chart_type = $row['dashboard_chart_type'] ?? "doughnut"; $dashboard_label_text_color = $row['dashboard_label_text_color'] ?? $settings->get('theme', 'dashboard_label_text_color', ''); $dashboard_number_text_color = $row['dashboard_number_text_color'] ?? $settings->get('theme', 'dashboard_number_text_color', ''); + $dashboard_number_background_color = $row['dashboard_number_background_color'] ?? $settings->get('theme', 'dashboard_number_background_color', ''); $dashboard_details_state = $row['dashboard_details_state'] ?? "expanded"; $dashboard_row_span = $row['dashboard_row_span'] ?? 2; @@ -558,6 +559,7 @@ function toggle_grid_row_end_all() { $dashboard_chart_type = preg_replace($text_pattern, '', $dashboard_chart_type); $dashboard_label_text_color = preg_replace($text_pattern, '', $dashboard_label_text_color); $dashboard_number_text_color = preg_replace($text_pattern, '', $dashboard_number_text_color); + $dashboard_number_background_color = preg_replace($text_pattern, '', $dashboard_number_background_color); $dashboard_details_state = preg_replace($text_pattern, '', $dashboard_details_state); $dashboard_row_span = preg_replace($number_pattern, '', $dashboard_row_span); $dashboard_path = preg_replace($text_pattern, '', strtolower($row['dashboard_path'])); diff --git a/core/domains/resources/dashboard/domains.php b/core/domains/resources/dashboard/domains.php index 190ebb6cd0..7a789b33c0 100644 --- a/core/domains/resources/dashboard/domains.php +++ b/core/domains/resources/dashboard/domains.php @@ -37,7 +37,7 @@ echo " ".escape($dashboard_label).""; echo "
\n"; echo " \n"; - echo " ".$domain_count."\n"; + echo " ".$domain_count."\n"; echo "
\n"; echo " \n"; if (empty($dashboard_details_state) || $dashboard_details_state != "disabled") { From 77f9161408b9958bca67313e7d27bb6f82994b9c Mon Sep 17 00:00:00 2001 From: simplecoder732 <128755293+eliweaver732@users.noreply.github.com> Date: Tue, 28 Jan 2025 18:57:50 -0500 Subject: [PATCH 040/196] Add a voicemail deletion queue (#7221) * Add a deleted messages option to voicemail. Messages are only deleted after a certain amount of time instead of immediately. The queue can be turned off or on with the default setting "use_deletion_queue" in the "voicemail" category. Changed deleted phrase and added a deleted messages count phrase Added a program to delete messages that are due for deletion. Also small changes to phrases. * Added a remove_deleted_messages function that runs on voicemail main menu log in. With this method, the deletion queue is handled per mailbox vs system-wide as in the cron-triggered script. It also allows us to adjust the retention hours on a per-domain basis. --- .../resources/conf/languages/en/vm/sounds.xml | 19 +++ .../conf/languages/en/vm/voicemail.xml | 36 ++++++ .../resources/scripts/app/voicemail/index.lua | 17 +++ .../functions/listen_to_recording.lua | 13 +- .../resources/functions/main_menu.lua | 31 +++++ .../resources/functions/menu_messages.lua | 6 +- .../resources/functions/message_saved.lua | 14 +- .../functions/remove_deleted_messages.lua | 92 ++++++++++++++ .../resources/scripts/delete_messages.lua | 120 ++++++++++++++++++ app/voicemails/app_config.php | 18 ++- 10 files changed, 356 insertions(+), 10 deletions(-) create mode 100644 app/switch/resources/scripts/app/voicemail/resources/functions/remove_deleted_messages.lua create mode 100644 app/switch/resources/scripts/app/voicemail/resources/scripts/delete_messages.lua diff --git a/app/switch/resources/conf/languages/en/vm/sounds.xml b/app/switch/resources/conf/languages/en/vm/sounds.xml index 250cb96e1d..14866b7383 100644 --- a/app/switch/resources/conf/languages/en/vm/sounds.xml +++ b/app/switch/resources/conf/languages/en/vm/sounds.xml @@ -104,6 +104,25 @@ + + + + + + + + + + + + + + + + + + + diff --git a/app/switch/resources/conf/languages/en/vm/voicemail.xml b/app/switch/resources/conf/languages/en/vm/voicemail.xml index 0daec58637..3218186ccc 100644 --- a/app/switch/resources/conf/languages/en/vm/voicemail.xml +++ b/app/switch/resources/conf/languages/en/vm/voicemail.xml @@ -65,6 +65,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + @@ -96,6 +121,17 @@ + + + + + + + + + + + diff --git a/app/switch/resources/scripts/app/voicemail/index.lua b/app/switch/resources/scripts/app/voicemail/index.lua index ebbe781fef..253bfcb43b 100644 --- a/app/switch/resources/scripts/app/voicemail/index.lua +++ b/app/switch/resources/scripts/app/voicemail/index.lua @@ -246,6 +246,22 @@ end end + use_deletion_queue = 'false'; + if (settings['voicemail']['use_deletion_queue'] ~= nil) then + if (settings['voicemail']['use_deletion_queue']['boolean'] ~= nil) then + use_deletion_queue = settings['voicemail']['use_deletion_queue']['boolean']; + end + end + + deletion_queue_retention_hours = "24"; + if (settings['voicemail'] ~= nil) then + if (settings['voicemail']['deletion_queue_retention_hours'] ~= nil) then + if (settings['voicemail']['deletion_queue_retention_hours']['numeric'] ~= nil) then + deletion_queue_retention_hours = settings['voicemail']['deletion_queue_retention_hours']['numeric']; + end + end + end + end if (settings['voicemail']) then @@ -363,6 +379,7 @@ require "app.voicemail.resources.functions.mwi_notify"; require "app.voicemail.resources.functions.blf_notify"; require "app.voicemail.resources.functions.tutorial"; + require "app.voicemail.resources.functions.remove_deleted_messages"; --send a message waiting event if (voicemail_action == "mwi") then diff --git a/app/switch/resources/scripts/app/voicemail/resources/functions/listen_to_recording.lua b/app/switch/resources/scripts/app/voicemail/resources/functions/listen_to_recording.lua index 635e160b10..3fc0cfd5f5 100644 --- a/app/switch/resources/scripts/app/voicemail/resources/functions/listen_to_recording.lua +++ b/app/switch/resources/scripts/app/voicemail/resources/functions/listen_to_recording.lua @@ -233,7 +233,11 @@ --post listen options if (session:ready()) then if (string.len(dtmf_digits) == 0) then - dtmf_digits = session:playAndGetDigits(1, 1, max_tries, digit_timeout, "#", "phrase:voicemail_listen_file_options:1:2:3:5:7:8:9:0", "", "^[\\d\\*#]$"); + if (use_deletion_queue == "true" and message_status == "deleted") then + dtmf_digits = session:playAndGetDigits(1, 1, max_tries, digit_timeout, "#", "phrase:voicemail_listen_file_options:deleted:1:2:3:5:7:8:9:0", "", "^[\\d\\*#]$"); + else + dtmf_digits = session:playAndGetDigits(1, 1, max_tries, digit_timeout, "#", "phrase:voicemail_listen_file_options:1:2:3:5:7:8:9:0", "", "^[\\d\\*#]$"); + end end end @@ -264,7 +268,12 @@ message_saved(voicemail_id, uuid); return_call(caller_id_number); elseif (dtmf_digits == "7") then - delete_recording(voicemail_id, uuid); + if (use_deletion_queue == "true" and message_status ~= "deleted") then + message_saved(voicemail_id, uuid, "deleted"); + session:execute("playback", "phrase:voicemail_ack:deleted"); + else + delete_recording(voicemail_id, uuid); + end message_waiting(voicemail_id, domain_uuid); --fix for extensions that start with 0 (Ex: 0712) if (voicemail_id_copy ~= voicemail_id and voicemail_id_copy ~= nil) then diff --git a/app/switch/resources/scripts/app/voicemail/resources/functions/main_menu.lua b/app/switch/resources/scripts/app/voicemail/resources/functions/main_menu.lua index c69593b248..ea289054f1 100644 --- a/app/switch/resources/scripts/app/voicemail/resources/functions/main_menu.lua +++ b/app/switch/resources/scripts/app/voicemail/resources/functions/main_menu.lua @@ -38,6 +38,11 @@ session:execute("sleep", "1000"); end + --remove deleted messages in queue + if (use_deletion_queue == "true") then + remove_deleted_messages(voicemail_id); + end + --new voicemail count if (session:ready()) then local sql = [[SELECT count(*) as new_messages FROM v_voicemail_messages @@ -70,6 +75,24 @@ dtmf_digits = session:playAndGetDigits(0, 1, 1, 300, "#", "phrase:voicemail_saved_message_count:" .. saved_messages .. ":saved", "", "\\d+"); end end + --deleted messages + if (session:ready()) then + deleted_messages = 0; + if (string.len(dtmf_digits) == 0 and use_deletion_queue == "true") then + sql = [[SELECT count(*) as deleted_messages FROM v_voicemail_messages + WHERE domain_uuid = :domain_uuid + AND voicemail_uuid = :voicemail_uuid + AND message_status = 'deleted' ]]; + local params = {domain_uuid = domain_uuid, voicemail_uuid = voicemail_uuid}; + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); + end + dbh:query(sql, params, function(row) + deleted_messages = row["deleted_messages"]; + end); + dtmf_digits = session:playAndGetDigits(0, 1, 1, 300, "#", "phrase:voicemail_deleted_message_count:" .. deleted_messages .. ":deleted", "", "\\d+"); + end + end --to listen to new message if (session:ready() and new_messages ~= '0') then @@ -83,6 +106,12 @@ dtmf_digits = session:playAndGetDigits(0, 1, 1, 100, "#", "phrase:voicemail_main_menu:saved:2", "", "\\d+"); end end + --deleted messages + if (session:ready() and deleted_messages ~= '0') then + if (string.len(dtmf_digits) == 0) then + dtmf_digits = session:playAndGetDigits(0, 1, 1, 100, "#", "phrase:voicemail_main_menu:deleted:3", "", "\\d+"); + end + end --for advanced options if (session:ready()) then if (string.len(dtmf_digits) == 0) then @@ -101,6 +130,8 @@ menu_messages("new"); elseif (dtmf_digits == "2") then menu_messages("saved"); + elseif (dtmf_digits == "3" and use_deletion_queue == "true") then + menu_messages("deleted"); elseif (dtmf_digits == "5") then timeouts = 0; advanced(); diff --git a/app/switch/resources/scripts/app/voicemail/resources/functions/menu_messages.lua b/app/switch/resources/scripts/app/voicemail/resources/functions/menu_messages.lua index c106823065..e17990a8aa 100644 --- a/app/switch/resources/scripts/app/voicemail/resources/functions/menu_messages.lua +++ b/app/switch/resources/scripts/app/voicemail/resources/functions/menu_messages.lua @@ -38,7 +38,7 @@ --session:flushDigits(); --set the message number message_number = 0; - --message_status new,saved + --message_status new,any if (session:ready()) then if (voicemail_id ~= nil) then --get the voicemail_id @@ -58,8 +58,8 @@ AND voicemail_uuid = :voicemail_uuid ]] if (message_status == "new") then sql = sql .. [[AND (message_status is null or message_status = '') ]]; - elseif (message_status == "saved") then - sql = sql .. [[AND message_status = 'saved' ]]; + else + sql = sql .. "AND message_status = '" .. message_status .. "' "; end sql = sql .. [[ORDER BY created_epoch ]]..message_order; local params = {domain_uuid = domain_uuid, voicemail_uuid = voicemail_uuid}; diff --git a/app/switch/resources/scripts/app/voicemail/resources/functions/message_saved.lua b/app/switch/resources/scripts/app/voicemail/resources/functions/message_saved.lua index 15bec62635..d48ad0f472 100644 --- a/app/switch/resources/scripts/app/voicemail/resources/functions/message_saved.lua +++ b/app/switch/resources/scripts/app/voicemail/resources/functions/message_saved.lua @@ -24,11 +24,15 @@ -- POSSIBILITY OF SUCH DAMAGE. --save the message - function message_saved(voicemail_id, uuid) + function message_saved(voicemail_id, uuid, status) --clear the dtmf dtmf_digits = ''; --flush dtmf digits from the input buffer session:flushDigits(); + --set default status + if (status == nil) then + status = 'saved'; + end --get the voicemail_uuid local sql = [[SELECT * FROM v_voicemails WHERE domain_uuid = :domain_uuid @@ -38,18 +42,20 @@ db_voicemail_uuid = row["voicemail_uuid"]; end); --delete from the database - sql = [[UPDATE v_voicemail_messages SET message_status = 'saved' + sql = [[UPDATE v_voicemail_messages + SET message_status = :status, + update_date = now() WHERE domain_uuid = :domain_uuid AND voicemail_uuid = :voicemail_uuid AND voicemail_message_uuid = :uuid]]; - params = {domain_uuid = domain_uuid, voicemail_uuid = db_voicemail_uuid, uuid = uuid}; + params = {status = status, domain_uuid = domain_uuid, voicemail_uuid = db_voicemail_uuid, uuid = uuid}; if (debug["sql"]) then freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end dbh:query(sql, params); --log to console if (debug["info"]) then - freeswitch.consoleLog("notice", "[voicemail][saved] id: " .. voicemail_id .. " message: "..uuid.."\n"); + freeswitch.consoleLog("notice", "[voicemail]["..status.."] id: " .. voicemail_id .. " message: "..uuid.."\n"); end --check the message waiting status message_waiting(voicemail_id, domain_uuid); diff --git a/app/switch/resources/scripts/app/voicemail/resources/functions/remove_deleted_messages.lua b/app/switch/resources/scripts/app/voicemail/resources/functions/remove_deleted_messages.lua new file mode 100644 index 0000000000..1e8a94bc27 --- /dev/null +++ b/app/switch/resources/scripts/app/voicemail/resources/functions/remove_deleted_messages.lua @@ -0,0 +1,92 @@ +-- Part of FusionPBX +-- Copyright (C) 2013-2025 +-- All rights reserved. +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- 1. Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- 2. Redistributions in binary form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. + +--delete all deleted messages for a single mailbox + function remove_deleted_messages(voicemail_id) + --get the voicemail_uuid + local sql = [[SELECT * FROM v_voicemails + WHERE domain_uuid = :domain_uuid + AND voicemail_id = :voicemail_id]]; + local params = {domain_uuid = domain_uuid, voicemail_id = voicemail_id}; + dbh:query(sql, params, function(row) + db_voicemail_uuid = row["voicemail_uuid"]; + end); + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); + end + + --get messages + local sql = [[SELECT * FROM v_voicemail_messages + WHERE message_status = 'deleted' ]] + sql = sql .. "AND (update_date + interval '" .. deletion_queue_retention_hours .. " hours') < now() " + sql = sql .. [[AND voicemail_uuid = :voicemail_uuid + AND domain_uuid = :domain_uuid]]; + local params = {voicemail_uuid = db_voicemail_uuid, domain_uuid = domain_uuid} + messages_to_delete = {}; + dbh:query(sql, params, function(row) + table.insert(messages_to_delete, row); + end); + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); + end + + --flush dtmf digits from the input buffer + session:flushDigits(); + + total_messages = #messages_to_delete; + message_number = 1; + while message_number <= total_messages do + local message_row = messages_to_delete[message_number]; + local uuid = message_row["voicemail_message_uuid"]; + + --delete the file + os.remove(voicemail_dir.."/"..voicemail_id.."/intro_msg_"..uuid.."."..vm_message_ext); + os.remove(voicemail_dir.."/"..voicemail_id.."/intro_"..uuid.."."..vm_message_ext); + os.remove(voicemail_dir.."/"..voicemail_id.."/msg_"..uuid.."."..vm_message_ext); + --delete from the database + sql = [[DELETE FROM v_voicemail_messages + WHERE domain_uuid = :domain_uuid + AND voicemail_uuid = :voicemail_uuid + AND voicemail_message_uuid = :uuid]]; + params = {domain_uuid = domain_uuid, voicemail_uuid = db_voicemail_uuid, uuid = uuid}; + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); + end + dbh:query(sql, params); + --log to console + if (debug["info"]) then + freeswitch.consoleLog("notice", "[voicemail][deleted] message: " .. uuid .. "\n"); + end + end + + + --clear the variable + db_voicemail_uuid = ''; + messages_to_delete = {}; + + --flush dtmf digits from the input buffer + session:flushDigits(); + +end diff --git a/app/switch/resources/scripts/app/voicemail/resources/scripts/delete_messages.lua b/app/switch/resources/scripts/app/voicemail/resources/scripts/delete_messages.lua new file mode 100644 index 0000000000..4deef47da6 --- /dev/null +++ b/app/switch/resources/scripts/app/voicemail/resources/scripts/delete_messages.lua @@ -0,0 +1,120 @@ +-- Part of FusionPBX +-- Copyright (C) 2013-2025 Mark J Crane +-- All rights reserved. +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- 1. Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- 2. Redistributions in binary form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +-- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +-- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +-- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. + +--connect to the database + Database = require "resources.functions.database"; + dbh = Database.new('system'); + +--get settings + require "resources.functions.settings"; + settings = settings(); + +--set deletion_queue_retention_hours + if (settings['voicemail'] ~= nil) then + if (settings['voicemail']['deletion_queue_retention_hours'] ~= nil) then + if (settings['voicemail']['deletion_queue_retention_hours']['numeric'] ~= nil) then + retention_hours = settings['voicemail']['deletion_queue_retention_hours']['numeric']; + else + retention_hours = "24"; + end + end + end + +--set the voicemail_dir + if (settings['switch'] ~= nil) then + if (settings['switch']['voicemail'] ~= nil) then + if (settings['switch']['voicemail']['dir'] ~= nil) then + voicemail_dir = settings['switch']['voicemail']['dir'].."/default"; + end + end + end + +--get the voicemail extension + sql = "SELECT * FROM v_vars WHERE var_category = 'Defaults' AND var_name = 'vm_message_ext' AND var_enabled = 'true'"; + dbh:query(sql, function(row) + vm_message_ext = row["var_value"]; + end); + if (vm_message_ext == nil) then + vm_message_ext = "wav"; + end + +--get messages + sql = "SELECT * FROM v_voicemail_messages WHERE message_status = 'deleted' AND (update_date + interval '" .. retention_hours .. " hours') < now()"; + messages_to_delete = {}; + dbh:query(sql, function(row) + table.insert(messages_to_delete, row); + end); + +--delete the messages + total_messages = #messages_to_delete; + message_number = 1; + while message_number <= total_messages do + local message_row = messages_to_delete[message_number]; + local uuid = message_row["voicemail_message_uuid"]; + + --get domain_name + sql = [[SELECT * from v_domains + WHERE domain_uuid = :domain_uuid + ]]; + local params = {domain_uuid = message_row["domain_uuid"]}; + dbh:query(sql, params, function(row) + domain_name = row["domain_name"]; + end); + + --get voicemail_id + sql = [[SELECT * from v_voicemails + WHERE domain_uuid = :domain_uuid + AND voicemail_uuid = :voicemail_uuid + ]]; + local params = {domain_uuid = message_row["domain_uuid"], voicemail_uuid = message_row["voicemail_uuid"]}; + dbh:query(sql, params, function(row) + voicemail_id = row["voicemail_id"]; + end); + + --delete the file + os.remove(voicemail_dir.."/"..domain_name.."/"..voicemail_id.."/intro_msg_"..uuid.."."..vm_message_ext); + os.remove(voicemail_dir.."/"..domain_name.."/"..voicemail_id.."/intro_"..uuid.."."..vm_message_ext); + os.remove(voicemail_dir.."/"..domain_name.."/"..voicemail_id.."/msg_"..uuid.."."..vm_message_ext); + + --delete from the database + sql = [[DELETE FROM v_voicemail_messages + WHERE domain_uuid = :domain_uuid + AND voicemail_uuid = :voicemail_uuid + AND voicemail_message_uuid = :uuid]]; + local params = { + domain_uuid = message_row["domain_uuid"], + voicemail_uuid = message_row["voicemail_uuid"], + uuid = uuid + }; + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); + end + dbh:query(sql, params); + --log to console + if (debug["info"]) then + freeswitch.consoleLog("notice", "[voicemail][deleted] message: " .. uuid .. "\n"); + end + + end \ No newline at end of file diff --git a/app/voicemails/app_config.php b/app/voicemails/app_config.php index a34a4091f2..11d6f974b0 100644 --- a/app/voicemails/app_config.php +++ b/app/voicemails/app_config.php @@ -401,6 +401,22 @@ $apps[$x]['default_settings'][$y]['default_setting_value'] = "90"; $apps[$x]['default_settings'][$y]['default_setting_enabled'] = "true"; $apps[$x]['default_settings'][$y]['default_setting_description'] = "Number of days maintenance application will retain files."; + $y++; + $apps[$x]['default_settings'][$y]['default_setting_uuid'] = "79d05433-a7ab-4641-ae5d-6eb7810eb560"; + $apps[$x]['default_settings'][$y]['default_setting_category'] = "voicemail"; + $apps[$x]['default_settings'][$y]['default_setting_subcategory'] = "use_deletion_queue"; + $apps[$x]['default_settings'][$y]['default_setting_name'] = "boolean"; + $apps[$x]['default_settings'][$y]['default_setting_value'] = "false"; + $apps[$x]['default_settings'][$y]['default_setting_enabled'] = "false"; + $apps[$x]['default_settings'][$y]['default_setting_description'] = "Instead of deleting voicemails right away when pressing 7; queue them for deletion"; + $y++; + $apps[$x]['default_settings'][$y]['default_setting_uuid'] = "b06cc9df-379e-4b45-8bda-d2d431506317"; + $apps[$x]['default_settings'][$y]['default_setting_category'] = "voicemail"; + $apps[$x]['default_settings'][$y]['default_setting_subcategory'] = "deletion_queue_retention_hours"; + $apps[$x]['default_settings'][$y]['default_setting_name'] = "numeric"; + $apps[$x]['default_settings'][$y]['default_setting_value'] = "24"; + $apps[$x]['default_settings'][$y]['default_setting_enabled'] = "true"; + $apps[$x]['default_settings'][$y]['default_setting_description'] = "Number of hours the voicemail deletion queue will retain deleted voicemails"; //schema details $y=0; $apps[$x]['db'][$y]['table']['name'] = "v_voicemails"; @@ -735,4 +751,4 @@ $apps[$x]['db'][$y]['fields'][$z]['type']['mysql'] = "char(36)"; $apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = ""; -?> \ No newline at end of file +?> From d6f9b252838c882bce71e5f150cc4ac2356338e7 Mon Sep 17 00:00:00 2001 From: frytimo Date: Tue, 28 Jan 2025 20:05:00 -0400 Subject: [PATCH 041/196] format schema class (#7145) - format schema class using autoformat --- resources/classes/schema.php | 1609 +++++++++++++++++----------------- 1 file changed, 799 insertions(+), 810 deletions(-) diff --git a/resources/classes/schema.php b/resources/classes/schema.php index d4f57e8518..3ec6c2c57f 100644 --- a/resources/classes/schema.php +++ b/resources/classes/schema.php @@ -1,931 +1,920 @@ - Copyright (C) 2013 - 2023 - All Rights Reserved. + The Initial Developer of the Original Code is + Mark J Crane + Copyright (C) 2013 - 2023 + All Rights Reserved. - Contributor(s): - Mark J Crane -*/ + Contributor(s): + Mark J Crane + */ //define the schema class if (!class_exists('schema')) { + class schema { //define variables - private $database; - public $apps; - public $db_type; - public $result; - public $data_types; + private $database; + public $apps; + public $db_type; + public $result; + public $data_types; //class constructor - public function __construct() { + public function __construct() { - //includes files - require dirname(__DIR__, 2) . "/resources/require.php"; + //includes files + require dirname(__DIR__, 2) . "/resources/require.php"; - //connect to the database - $this->database = database::new(); + //connect to the database + $this->database = database::new(); - //get the list of installed apps from the core and mod directories - $config_list = glob($_SERVER["DOCUMENT_ROOT"] . PROJECT_PATH . "/*/*/app_config.php"); - $x=0; - foreach ($config_list as $config_path) { - try { - include($config_path); - } - catch (Exception $e) { - //echo 'Caught exception: ', $e->getMessage(), "\n"; - } - $x++; + //get the list of installed apps from the core and mod directories + $config_list = glob($_SERVER["DOCUMENT_ROOT"] . PROJECT_PATH . "/*/*/app_config.php"); + $x = 0; + foreach ($config_list as $config_path) { + try { + include($config_path); + } catch (Exception $e) { + //echo 'Caught exception: ', $e->getMessage(), "\n"; } - $this->apps = $apps; + $x++; } + $this->apps = $apps; + } //create the database schema - public function sql() { - $sql = ''; - $sql_schema = ''; - foreach ($this->apps as $app) { - if (isset($app['db']) && count($app['db'])) { - foreach ($app['db'] as $row) { - //create the sql string - $table_name = $row['table']['name']; - $sql = "CREATE TABLE " . $row['table']['name'] . " (\n"; - $field_count = 0; - foreach ($row['fields'] as $field) { - if (!empty($field['deprecated']) and ($field['deprecated'] == "true")) { - //skip this field + public function sql() { + $sql = ''; + $sql_schema = ''; + foreach ($this->apps as $app) { + if (isset($app['db']) && count($app['db'])) { + foreach ($app['db'] as $row) { + //create the sql string + $table_name = $row['table']['name']; + $sql = "CREATE TABLE " . $row['table']['name'] . " (\n"; + $field_count = 0; + foreach ($row['fields'] as $field) { + if (!empty($field['deprecated']) and ($field['deprecated'] == "true")) { + //skip this field + } else { + if ($field_count > 0) { + $sql .= ",\n"; + } + if (is_array($field['name'])) { + $sql .= $field['name']['text'] . " "; + } else { + $sql .= $field['name'] . " "; + } + if (is_array($field['type'])) { + $sql .= $field['type'][$this->db_type]; + } else { + $sql .= $field['type']; + } + if (isset($field['key']) && isset($field['key']['type']) && ($field['key']['type'] == "primary")) { + $sql .= " PRIMARY KEY"; + } + if (isset($field['key']) && isset($field['key']['type']) && ($field['key']['type'] == "foreign")) { + if ($this->db_type == "pgsql") { + //$sql .= " references ".$field['key']['reference']['table']."(".$field['key']['reference']['field'].")"; } - else { - if ($field_count > 0 ) { $sql .= ",\n"; } - if (is_array($field['name'])) { - $sql .= $field['name']['text']." "; - } - else { - $sql .= $field['name']." "; - } - if (is_array($field['type'])) { - $sql .= $field['type'][$this->db_type]; - } - else { - $sql .= $field['type']; - } - if (isset($field['key']) && isset($field['key']['type']) && ($field['key']['type'] == "primary")) { - $sql .= " PRIMARY KEY"; - } - if (isset($field['key']) && isset($field['key']['type']) && ($field['key']['type'] == "foreign")) { - if ($this->db_type == "pgsql") { - //$sql .= " references ".$field['key']['reference']['table']."(".$field['key']['reference']['field'].")"; - } - if ($this->db_type == "sqlite") { - //$sql .= " references ".$field['key']['reference']['table']."(".$field['key']['reference']['field'].")"; - } - if ($this->db_type == "mysql") { - //$sql .= " references ".$field['key']['reference']['table']."(".$field['key']['reference']['field'].")"; - } - } - $field_count++; + if ($this->db_type == "sqlite") { + //$sql .= " references ".$field['key']['reference']['table']."(".$field['key']['reference']['field'].")"; + } + if ($this->db_type == "mysql") { + //$sql .= " references ".$field['key']['reference']['table']."(".$field['key']['reference']['field'].")"; } } - if ($this->db_type == "mysql") { - $sql .= ") ENGINE=INNODB;"; - } - else { - $sql .= ");"; - } - $this->result['sql'][] = $sql; - unset($sql); + $field_count++; + } } + if ($this->db_type == "mysql") { + $sql .= ") ENGINE=INNODB;"; + } else { + $sql .= ");"; + } + $this->result['sql'][] = $sql; + unset($sql); } } } + } //create the database schema - public function exec() { - foreach ($this->result['sql'] as $sql) { - //start the sql transaction - $this->database->beginTransaction(); - //execute the sql query - try { - $this->database->query($sql); - } - catch (PDOException $error) { - echo "error: " . $error->getMessage() . " sql: $sql
"; - } - //complete the transaction - $this->database->commit(); + public function exec() { + foreach ($this->result['sql'] as $sql) { + //start the sql transaction + $this->database->beginTransaction(); + //execute the sql query + try { + $this->database->query($sql); + } catch (PDOException $error) { + echo "error: " . $error->getMessage() . " sql: $sql
"; } + //complete the transaction + $this->database->commit(); } + } //check if a column exists in sqlite - private function sqlite_column_exists($table_info, $column_name) { - foreach ($table_info as $key => $row) { - if ($row['name'] == $column_name) { - return true; - } + private function sqlite_column_exists($table_info, $column_name) { + foreach ($table_info as $key => $row) { + if ($row['name'] == $column_name) { + return true; } - return $false; } + return $false; + } //check if a column exists - public function column_exists ($db_name, $table_name, $column_name) { + public function column_exists($db_name, $table_name, $column_name) { - if ($this->db_type == "sqlite") { - $table_info = $this->table_info($db_name, $table_name); - if ($this->sqlite_column_exists($table_info, $column_name)) { - return true; - } - else { - return false; - } - } - if ($this->db_type == "pgsql") { - $sql = "SELECT attname FROM pg_attribute WHERE attrelid = (SELECT oid FROM pg_class WHERE relname = '$table_name' limit 1) AND attname = '$column_name'; "; - } - if ($this->db_type == "mysql") { - //$sql .= "SELECT * FROM information_schema.COLUMNS where TABLE_SCHEMA = '$db_name' and TABLE_NAME = '$table_name' and COLUMN_NAME = '$column_name' "; - $sql = "show columns from $table_name where field = '$column_name' "; - } - - if ($sql) { - $prep_statement = $this->database->db->prepare($sql); - $prep_statement->execute(); - $result = $prep_statement->fetchAll(PDO::FETCH_NAMED); - if (!$result) { - return false; - } - if (count($result) > 0) { - return true; - } - else { - return false; - } - unset ($prep_statement); + if ($this->db_type == "sqlite") { + $table_info = $this->table_info($db_name, $table_name); + if ($this->sqlite_column_exists($table_info, $column_name)) { + return true; + } else { + return false; } } + if ($this->db_type == "pgsql") { + $sql = "SELECT attname FROM pg_attribute WHERE attrelid = (SELECT oid FROM pg_class WHERE relname = '$table_name' limit 1) AND attname = '$column_name'; "; + } + if ($this->db_type == "mysql") { + //$sql .= "SELECT * FROM information_schema.COLUMNS where TABLE_SCHEMA = '$db_name' and TABLE_NAME = '$table_name' and COLUMN_NAME = '$column_name' "; + $sql = "show columns from $table_name where field = '$column_name' "; + } - //get the table information - public function table_info($db_name, $table_name) { - if (empty($table_name)) { return false; } - if ($this->db_type == "sqlite") { - $sql = "PRAGMA table_info(".$table_name.");"; - } - if ($this->db_type == "pgsql") { - $sql = "SELECT ordinal_position, "; - $sql .= "column_name, "; - $sql .= "data_type, "; - $sql .= "column_default, "; - $sql .= "is_nullable, "; - $sql .= "character_maximum_length, "; - $sql .= "numeric_precision "; - $sql .= "FROM information_schema.columns "; - $sql .= "WHERE table_name = '".$table_name."' "; - $sql .= "and table_catalog = '".$db_name."' "; - $sql .= "ORDER BY ordinal_position; "; - } - if ($this->db_type == "mysql") { - $sql = "describe ".$table_name.";"; - } + if ($sql) { $prep_statement = $this->database->db->prepare($sql); $prep_statement->execute(); - return $prep_statement->fetchAll(PDO::FETCH_ASSOC); + $result = $prep_statement->fetchAll(PDO::FETCH_NAMED); + if (!$result) { + return false; + } + if (count($result) > 0) { + return true; + } else { + return false; + } + unset($prep_statement); } + } + + //get the table information + public function table_info($db_name, $table_name) { + if (empty($table_name)) { + return false; + } + if ($this->db_type == "sqlite") { + $sql = "PRAGMA table_info(" . $table_name . ");"; + } + if ($this->db_type == "pgsql") { + $sql = "SELECT ordinal_position, "; + $sql .= "column_name, "; + $sql .= "data_type, "; + $sql .= "column_default, "; + $sql .= "is_nullable, "; + $sql .= "character_maximum_length, "; + $sql .= "numeric_precision "; + $sql .= "FROM information_schema.columns "; + $sql .= "WHERE table_name = '" . $table_name . "' "; + $sql .= "and table_catalog = '" . $db_name . "' "; + $sql .= "ORDER BY ordinal_position; "; + } + if ($this->db_type == "mysql") { + $sql = "describe " . $table_name . ";"; + } + $prep_statement = $this->database->db->prepare($sql); + $prep_statement->execute(); + return $prep_statement->fetchAll(PDO::FETCH_ASSOC); + } //database table exists alternate - private function db_table_exists_alternate ($db_type, $table_name) { - $sql = "select count(*) from $table_name "; - $result = $this->database->query($sql); - if ($result > 0) { - return true; //table exists - } - else { - return false; //table doesn't exist - } + private function db_table_exists_alternate($db_type, $table_name) { + $sql = "select count(*) from $table_name "; + $result = $this->database->query($sql); + if ($result > 0) { + return true; //table exists + } else { + return false; //table doesn't exist } + } //database table exists - private function db_table_exists ($db_type, $db_name, $table_name) { - $sql = ""; - if ($db_type == "sqlite") { - $sql .= "SELECT * FROM sqlite_master WHERE type='table' and name='$table_name' "; + private function db_table_exists($db_type, $db_name, $table_name) { + $sql = ""; + if ($db_type == "sqlite") { + $sql .= "SELECT * FROM sqlite_master WHERE type='table' and name='$table_name' "; + } + if ($db_type == "pgsql") { + $sql .= "select * from pg_tables where schemaname='public' and tablename = '$table_name' "; + } + if ($db_type == "mysql") { + $sql .= "SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema = '$db_name' and TABLE_NAME = '$table_name' "; + } + $prep_statement = $this->database->db->prepare(check_sql($sql)); + $prep_statement->execute(); + $result = $prep_statement->fetchAll(PDO::FETCH_NAMED); + if (count($result) > 0) { + return true; //table exists + } else { + return false; //table doesn't exist + } + } + + //database table information + private function db_table_info($db_name, $db_type, $table_name) { + if (empty($table_name)) { + return false; + } + if ($db_type == "sqlite") { + $sql = "PRAGMA table_info(" . $table_name . ");"; + } + if ($db_type == "pgsql") { + $sql = "SELECT ordinal_position, "; + $sql .= "column_name, "; + $sql .= "data_type, "; + $sql .= "column_default, "; + $sql .= "is_nullable, "; + $sql .= "character_maximum_length, "; + $sql .= "numeric_precision "; + $sql .= "FROM information_schema.columns "; + $sql .= "WHERE table_name = '" . $table_name . "' "; + $sql .= "and table_catalog = '" . $db_name . "' "; + $sql .= "ORDER BY ordinal_position; "; + } + if ($db_type == "mysql") { + $sql = "describe " . $table_name . ";"; + } + $prep_statement = $this->database->db->prepare($sql); + $prep_statement->execute(); + return $prep_statement->fetchAll(PDO::FETCH_ASSOC); + } + + //database type + private function db_data_type($db_type, $table_info, $column_name) { + if ($db_type == "sqlite") { + foreach ($table_info as $key => $row) { + if ($row['name'] == $column_name) { + return $row['type']; + } } - if ($db_type == "pgsql") { - $sql .= "select * from pg_tables where schemaname='public' and tablename = '$table_name' "; + } + if ($db_type == "pgsql") { + foreach ($table_info as $key => $row) { + if ($row['column_name'] == $column_name) { + return $row['data_type']; + } } - if ($db_type == "mysql") { - $sql .= "SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema = '$db_name' and TABLE_NAME = '$table_name' "; + } + if ($db_type == "mysql") { + foreach ($table_info as $key => $row) { + if ($row['Field'] == $column_name) { + return $row['Type']; + } } + } + } + + //sqlite column exists + private function db_sqlite_column_exists($table_info, $column_name) { + foreach ($table_info as $key => $row) { + if ($row['name'] == $column_name) { + return true; + } + } + return $false; + } + + //database column exists + private function db_column_exists($db_type, $db_name, $table_name, $column_name) { + + if ($db_type == "sqlite") { + $table_info = $this->db_table_info($db_name, $db_type, $table_name); + if ($this->db_sqlite_column_exists($table_info, $column_name)) { + return true; + } else { + return false; + } + } + if ($db_type == "pgsql") { + $sql = "SELECT attname FROM pg_attribute WHERE attrelid = (SELECT oid FROM pg_class WHERE relname = '$table_name' limit 1) AND attname = '$column_name'; "; + } + if ($db_type == "mysql") { + //$sql .= "SELECT * FROM information_schema.COLUMNS where TABLE_SCHEMA = '$db_name' and TABLE_NAME = '$table_name' and COLUMN_NAME = '$column_name' "; + $sql = "show columns from $table_name where field = '$column_name' "; + } + if ($sql) { $prep_statement = $this->database->db->prepare(check_sql($sql)); $prep_statement->execute(); $result = $prep_statement->fetchAll(PDO::FETCH_NAMED); - if (count($result) > 0) { - return true; //table exists - } - else { - return false; //table doesn't exist - } - } - - //database table information - private function db_table_info($db_name, $db_type, $table_name) { - if (empty($table_name)) { return false; } - if ($db_type == "sqlite") { - $sql = "PRAGMA table_info(".$table_name.");"; - } - if ($db_type == "pgsql") { - $sql = "SELECT ordinal_position, "; - $sql .= "column_name, "; - $sql .= "data_type, "; - $sql .= "column_default, "; - $sql .= "is_nullable, "; - $sql .= "character_maximum_length, "; - $sql .= "numeric_precision "; - $sql .= "FROM information_schema.columns "; - $sql .= "WHERE table_name = '".$table_name."' "; - $sql .= "and table_catalog = '".$db_name."' "; - $sql .= "ORDER BY ordinal_position; "; - } - if ($db_type == "mysql") { - $sql = "describe ".$table_name.";"; - } - $prep_statement = $this->database->db->prepare($sql); - $prep_statement->execute(); - return $prep_statement->fetchAll(PDO::FETCH_ASSOC); - } - - //database type - private function db_data_type($db_type, $table_info, $column_name) { - if ($db_type == "sqlite") { - foreach ($table_info as $key => $row) { - if ($row['name'] == $column_name) { - return $row['type']; - } - } - } - if ($db_type == "pgsql") { - foreach ($table_info as $key => $row) { - if ($row['column_name'] == $column_name) { - return $row['data_type']; - } - } - } - if ($db_type == "mysql") { - foreach ($table_info as $key => $row) { - if ($row['Field'] == $column_name) { - return $row['Type']; - } - } - } - } - - //sqlite column exists - private function db_sqlite_column_exists($table_info, $column_name) { - foreach ($table_info as $key => $row) { - if ($row['name'] == $column_name) { - return true; - } - } - return $false; - } - - //database column exists - private function db_column_exists ($db_type, $db_name, $table_name, $column_name) { - - if ($db_type == "sqlite") { - $table_info = $this->db_table_info($db_name, $db_type, $table_name); - if ($this->db_sqlite_column_exists($table_info, $column_name)) { - return true; - } - else { - return false; - } - } - if ($db_type == "pgsql") { - $sql = "SELECT attname FROM pg_attribute WHERE attrelid = (SELECT oid FROM pg_class WHERE relname = '$table_name' limit 1) AND attname = '$column_name'; "; - } - if ($db_type == "mysql") { - //$sql .= "SELECT * FROM information_schema.COLUMNS where TABLE_SCHEMA = '$db_name' and TABLE_NAME = '$table_name' and COLUMN_NAME = '$column_name' "; - $sql = "show columns from $table_name where field = '$column_name' "; - } - if ($sql) { - $prep_statement = $this->database->db->prepare(check_sql($sql)); - $prep_statement->execute(); - $result = $prep_statement->fetchAll(PDO::FETCH_NAMED); - if (!empty($result)) { - return true; - } - else { - return false; - } - unset ($prep_statement); + if (!empty($result)) { + return true; + } else { + return false; } + unset($prep_statement); } + } //database column data type - private function db_column_data_type ($db_type, $db_name, $table_name, $column_name) { - $table_info = $this->db_table_info($db_name, $db_type, $table_name); - return $this->db_data_type($db_type, $table_info, $column_name); - } + private function db_column_data_type($db_type, $db_name, $table_name, $column_name) { + $table_info = $this->db_table_info($db_name, $db_type, $table_name); + return $this->db_data_type($db_type, $table_info, $column_name); + } //database create table - public function db_create_table ($apps, $db_type, $table) { - if (empty($apps)) { return false; } - if (is_array($apps)) foreach ($apps as $x => $app) { - if (!empty($app['db']) && is_array($app['db'])) foreach ($app['db'] as $y => $row) { - if (!empty($row['table']['name']) && is_array($row['table']['name'])) { - $table_name = $row['table']['name']['text']; - } - else { - $table_name = $row['table']['name']; - } - if ($table_name == $table) { - $sql = "CREATE TABLE " . $table_name . " (\n"; - (int)$field_count = 0; - if (!empty($row['fields']) && is_array($row['fields'])) foreach ($row['fields'] as $field) { - if (!empty($field['deprecated']) && $field['deprecated'] == "true") { - //skip this row - } - else { - if ($field_count > 0 ) { $sql .= ",\n"; } - if (!empty($field['name']) &&is_array($field['name'])) { - $sql .= $field['name']['text'] . " "; - } - else { - $sql .= $field['name'] . " "; - } - if (!empty($field['type']) &&is_array($field['type'])) { - $sql .= $field['type'][$db_type]; - } - else { - $sql .= $field['type']; - } - if (!empty($field['key']['type']) && $field['key']['type'] == "primary") { - $sql .= " PRIMARY KEY"; - } - $field_count++; - } + public function db_create_table($apps, $db_type, $table) { + if (empty($apps)) { + return false; + } + if (is_array($apps)) { + foreach ($apps as $x => $app) { + if (!empty($app['db']) && is_array($app['db'])) { + foreach ($app['db'] as $y => $row) { + if (!empty($row['table']['name']) && is_array($row['table']['name'])) { + $table_name = $row['table']['name']['text']; + } else { + $table_name = $row['table']['name']; + } + if ($table_name == $table) { + $sql = "CREATE TABLE " . $table_name . " (\n"; + (int) $field_count = 0; + if (!empty($row['fields']) && is_array($row['fields'])) { + foreach ($row['fields'] as $field) { + if (!empty($field['deprecated']) && $field['deprecated'] == "true") { + //skip this row + } else { + if ($field_count > 0) { + $sql .= ",\n"; + } + if (!empty($field['name']) && is_array($field['name'])) { + $sql .= $field['name']['text'] . " "; + } else { + $sql .= $field['name'] . " "; + } + if (!empty($field['type']) && is_array($field['type'])) { + $sql .= $field['type'][$db_type]; + } else { + $sql .= $field['type']; + } + if (!empty($field['key']['type']) && $field['key']['type'] == "primary") { + $sql .= " PRIMARY KEY"; + } + $field_count++; + } + } + } + $sql .= ");\n"; + return $sql; } - $sql .= ");\n"; - return $sql; } } } } + } //database insert - private function db_insert_into ($apps, $db_type, $table) { - global $db_name; - foreach ($apps as $x => $app) { - foreach ($app['db'] as $y => $row) { - if ($row['table']['name'] == $table) { - $sql = "INSERT INTO " . $row['table']['name'] . " ("; - $field_count = 0; - foreach ($row['fields'] as $field) { - if (!empty($field['deprecated']) && $field['deprecated'] == "true") { - //skip this field + private function db_insert_into($apps, $db_type, $table) { + global $db_name; + foreach ($apps as $x => $app) { + foreach ($app['db'] as $y => $row) { + if ($row['table']['name'] == $table) { + $sql = "INSERT INTO " . $row['table']['name'] . " ("; + $field_count = 0; + foreach ($row['fields'] as $field) { + if (!empty($field['deprecated']) && $field['deprecated'] == "true") { + //skip this field + } else { + if ($field_count > 0) { + $sql .= ","; } - else { - if ($field_count > 0 ) { $sql .= ","; } - if (is_array($field['name'])) { + if (is_array($field['name'])) { + $sql .= $field['name']['text']; + } else { + $sql .= $field['name']; + } + $field_count++; + } + } + $sql .= ")\n"; + $sql .= "SELECT "; + $field_count = 0; + foreach ($row['fields'] as $field) { + if (!empty($field['deprecated']) && $field['deprecated'] == "true") { + //skip this field + } else { + if ($field_count > 0) { + $sql .= ","; + } + if (is_array($field['name'])) { + if ($field['exists'] == "false") { + if (is_array($field['name']['deprecated'])) { + $found = false; + foreach ($field['name']['deprecated'] as $row) { + if ($this->db_column_exists($db_type, $db_name, 'tmp_' . $table, $row)) { + $sql .= $row; + $found = true; + break; + } + } + if (!$found) { + $sql .= "''"; + } + } else { + if ($this->db_column_exists($db_type, $db_name, 'tmp_' . $table, $field['name']['deprecated'])) { + $sql .= $field['name']['deprecated']; + } else { + $sql .= "''"; + } + } + } else { $sql .= $field['name']['text']; } - else { - $sql .= $field['name']; - } - $field_count++; + } else { + $sql .= $field['name']; } + $field_count++; } - $sql .= ")\n"; - $sql .= "SELECT "; - $field_count = 0; - foreach ($row['fields'] as $field) { + } + $sql .= " FROM tmp_" . $table . ";\n"; + return $sql; + } + } + } + } + + //datatase schema + public function schema($format = '') { + + //set the global variable + global $text, $output_format; + + if ($format == '') { + $format = $output_format; + } + + //get the db variables + //require_once "resources/classes/config.php"; + //$config = new config; + //$config_exists = $config->exists(); + //$config_path = $config->find(); + //$config->get(); + //$db_type = $config->db_type; + //$db_name = $config->db_name; + //$db_username = $config->db_username; + //$db_password = $config->db_password; + //$db_host = $config->db_host; + //$db_path = $config->db_path; + //$db_port = $config->db_port; + //includes files + require dirname(__DIR__, 2) . "/resources/require.php"; + + //add multi-lingual support + if (!isset($text)) { + $language = new text; + $text = $language->get(null, 'core/upgrade'); + } + + //PHP PDO check if table or column exists + //check if table exists + // SELECT * FROM sqlite_master WHERE type='table' AND name='v_cdr' + //check if column exists + // SELECT * FROM sqlite_master WHERE type='table' AND name='v_cdr' AND sql LIKE '%caller_id_name TEXT,%' + //aditional information + // http://www.sqlite.org/faq.html#q9 + //postgresql + //list all tables in the database + // SELECT table_name FROM pg_tables WHERE schemaname='public'; + //check if table exists + // SELECT * FROM pg_tables WHERE schemaname='public' AND table_name = 'v_groups' + //check if column exists + // SELECT attname FROM pg_attribute WHERE attrelid = (SELECT oid FROM pg_class WHERE relname = 'v_cdr') AND attname = 'caller_id_name'; + //mysql + //list all tables in the database + // SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema = 'fusionpbx' + //check if table exists + // SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema = 'fusionpbx' AND TABLE_NAME = 'v_groups' + //check if column exists + // SELECT * FROM information_schema.COLUMNS where TABLE_SCHEMA = 'fusionpbx' AND TABLE_NAME = 'v_cdr' AND COLUMN_NAME = 'context' + //oracle + //check if table exists + // SELECT TABLE_NAME FROM ALL_TABLES + //update the app db array add exists true or false + $sql = ''; + foreach ($this->apps as $x => $app) { + if (isset($app['db'])) { + foreach ($app['db'] as $y => $row) { + if (isset($row['table']['name'])) { + if (is_array($row['table']['name'])) { + $table_name = $row['table']['name']['text']; + } else { + $table_name = $row['table']['name']; + } + } else { + //old array syntax + if (is_array($row['table'])) { + $table_name = $row['table']['text']; + } else { + $table_name = $row['table']; + } + } + if (!empty($table_name)) { + + //check if the table exists + if ($this->db_table_exists($db_type, $db_name, $table_name)) { + $this->apps[$x]['db'][$y]['exists'] = 'true'; + } else { + $this->apps[$x]['db'][$y]['exists'] = 'false'; + } + //check if the column exists + foreach ($row['fields'] as $z => $field) { if (!empty($field['deprecated']) && $field['deprecated'] == "true") { //skip this field - } - else { - if ($field_count > 0 ) { $sql .= ","; } + } else { if (is_array($field['name'])) { - if ($field['exists'] == "false") { - if (is_array($field['name']['deprecated'])) { - $found = false; - foreach ($field['name']['deprecated'] as $row) { - if ($this->db_column_exists ($db_type, $db_name, 'tmp_'.$table, $row)) { - $sql .= $row; - $found = true; - break; - } - } - if (!$found) { $sql .= "''"; } - } - else { - if ($this->db_column_exists ($db_type, $db_name, 'tmp_'.$table, $field['name']['deprecated'])) { - $sql .= $field['name']['deprecated']; - } - else { - $sql .= "''"; - } - } - } - else { - $sql .= $field['name']['text']; + $field_name = $field['name']['text']; + } else { + $field_name = $field['name']; + } + if (!empty($field_name)) { + if ($this->db_column_exists($db_type, $db_name, $table_name, $field_name)) { + //found + $this->apps[$x]['db'][$y]['fields'][$z]['exists'] = 'true'; + } else { + //not found + $this->apps[$x]['db'][$y]['fields'][$z]['exists'] = 'false'; } } - else { - $sql .= $field['name']; - } - $field_count++; + unset($field_name); } } - $sql .= " FROM tmp_".$table.";\n"; - return $sql; + unset($table_name); } } } } - //datatase schema - public function schema ($format = '') { + //prepare the variables + $sql_update = ''; - //set the global variable - global $text, $output_format; + //add missing tables and fields + foreach ($this->apps as $x => $app) { + if (isset($app['db'])) { + foreach ($app['db'] as $y => $row) { + if (is_array($row['table']['name'])) { + $table_name = $row['table']['name']['text']; + if ($this->db_table_exists($db_type, $db_name, $row['table']['name']['deprecated'])) { + $row['exists'] = "false"; //testing + if ($db_type == "pgsql") { + $sql_update .= "ALTER TABLE " . $row['table']['name']['deprecated'] . " RENAME TO " . $row['table']['name']['text'] . ";\n"; + } + if ($db_type == "mysql") { + $sql_update .= "RENAME TABLE " . $row['table']['name']['deprecated'] . " TO " . $row['table']['name']['text'] . ";\n"; + } + if ($db_type == "sqlite") { + $sql_update .= "ALTER TABLE " . $row['table']['name']['deprecated'] . " RENAME TO " . $row['table']['name']['text'] . ";\n"; + } + } else { + if ($this->db_table_exists($db_type, $db_name, $row['table']['name']['text'])) { + $row['exists'] = "true"; + } else { + $row['exists'] = "false"; + $sql_update .= $this->db_create_table($this->apps, $db_type, $row['table']['name']['text']); + } + } + } else { + if ($this->db_table_exists($db_type, $db_name, $row['table']['name'])) { + $row['exists'] = "true"; + } else { + $row['exists'] = "false"; + } + $table_name = $row['table']['name']; + } - if ($format == '') $format = $output_format; + //check if the table exists + if ($row['exists'] == "true") { + if (count($row['fields']) > 0) { + foreach ($row['fields'] as $z => $field) { + if (!empty($field['deprecated']) && $field['deprecated'] == "true") { + //skip this field + } else { + //get the data type + if (is_array($field['type'])) { + $field_type = $field['type'][$db_type]; + } else { + $field_type = $field['type']; + } + //get the field name + if (is_array($field['name'])) { + $field_name = $field['name']['text']; + } else { + $field_name = $field['name']; + } - //get the db variables - //require_once "resources/classes/config.php"; - //$config = new config; - //$config_exists = $config->exists(); - //$config_path = $config->find(); - //$config->get(); - //$db_type = $config->db_type; - //$db_name = $config->db_name; - //$db_username = $config->db_username; - //$db_password = $config->db_password; - //$db_host = $config->db_host; - //$db_path = $config->db_path; - //$db_port = $config->db_port; + //check if the field exists + // if ($this->db_column_exists($db_type, $db_name, $table_name, $field_name)) { + // $field['exists'] = "true"; + // } + // else { + // $field['exists'] = "false"; + // } + //add or rename fields + if (isset($field['name']['deprecated']) && $this->db_column_exists($db_type, $db_name, $table_name, $field['name']['deprecated'])) { + if ($db_type == "pgsql") { + $sql_update .= "ALTER TABLE " . $table_name . " RENAME COLUMN " . $field['name']['deprecated'] . " to " . $field['name']['text'] . ";\n"; + } + if ($db_type == "mysql") { + $field_type = str_replace("AUTO_INCREMENT PRIMARY KEY", "", $field_type); + $sql_update .= "ALTER TABLE " . $table_name . " CHANGE " . $field['name']['deprecated'] . " " . $field['name']['text'] . " " . $field_type . ";\n"; + } + if ($db_type == "sqlite") { + //a change has been made to the field name + $this->apps[$x]['db'][$y]['rebuild'] = 'true'; + } + } else { + //find missing fields and add them + if ($field['exists'] == "false") { + $sql_update .= "ALTER TABLE " . $table_name . " ADD " . $field_name . " " . $field_type . ";\n"; + } + } - //includes files - require dirname(__DIR__, 2) . "/resources/require.php"; + //change the data type if it has been changed + //if the data type in the app db array is different than the type in the database then change the data type + if ($this->data_types) { + $db_field_type = $this->db_column_data_type($db_type, $db_name, $table_name, $field_name); + $field_type_array = explode("(", $field_type); + $field_type = $field_type_array[0]; + if (trim($db_field_type) != trim($field_type) && !empty($db_field_type)) { + if ($db_type == "pgsql") { + if (strtolower($field_type) == "uuid") { + $sql_update .= "ALTER TABLE " . $table_name . " ALTER COLUMN " . $field_name . " TYPE uuid USING\n"; + $sql_update .= "CAST(regexp_replace(" . $field_name . ", '([A-Z0-9]{4})([A-Z0-9]{12})', E'\\1-\\2')\n"; + $sql_update .= "AS uuid);\n"; + } else { + //field type has not changed + if ($db_field_type == "integer" && strtolower($field_type) == "serial") { - //add multi-lingual support - if (!isset($text)) { - $language = new text; - $text = $language->get(null,'core/upgrade'); + } else if ($db_field_type == "timestamp without time zone" && strtolower($field_type) == "timestamp") { + + } else if ($db_field_type == "timestamp without time zone" && strtolower($field_type) == "datetime") { + + } else if ($db_field_type == "timestamp with time zone" && strtolower($field_type) == "timestamptz") { + + } else if ($db_field_type == "integer" && strtolower($field_type) == "numeric") { + + } else if ($db_field_type == "character" && strtolower($field_type) == "char") { + + } + //field type has changed + else { + switch ($field_type) { + case 'numeric': $using = $field_name . "::numeric"; + break; + case 'timestamp': + case 'datetime': $using = $field_name . "::timestamp without time zone"; + break; + case 'timestamptz': $using = $field_name . "::timestamp with time zone"; + break; + case 'boolean': $using = $field_name . "::boolean"; + break; + default: unset($using); + } + $sql_update .= "ALTER TABLE " . $table_name . " ALTER COLUMN " . $field_name . " TYPE " . $field_type . " " . ($using ? "USING " . $using : null) . ";\n"; + } + } + } + if ($db_type == "mysql") { + $type = explode("(", $db_field_type); + if ($type[0] == $field_type) { + //do nothing + } else if ($field_type == "numeric" && $type[0] == "decimal") { + //do nothing + } else { + $sql_update .= "ALTER TABLE " . $table_name . " modify " . $field_name . " " . $field_type . ";\n"; + } + unset($type); + } + if ($db_type == "sqlite") { + //a change has been made to the field type + $this->apps[$x]['db'][$y]['rebuild'] = 'true'; + } + } + } + } + } + } + } elseif (!is_array($row['table']['name'])) { + //create table + $sql_update .= $this->db_create_table($this->apps, $db_type, $row['table']['name']); + } } - - //PHP PDO check if table or column exists - //check if table exists - // SELECT * FROM sqlite_master WHERE type='table' AND name='v_cdr' - //check if column exists - // SELECT * FROM sqlite_master WHERE type='table' AND name='v_cdr' AND sql LIKE '%caller_id_name TEXT,%' - //aditional information - // http://www.sqlite.org/faq.html#q9 - - //postgresql - //list all tables in the database - // SELECT table_name FROM pg_tables WHERE schemaname='public'; - //check if table exists - // SELECT * FROM pg_tables WHERE schemaname='public' AND table_name = 'v_groups' - //check if column exists - // SELECT attname FROM pg_attribute WHERE attrelid = (SELECT oid FROM pg_class WHERE relname = 'v_cdr') AND attname = 'caller_id_name'; - //mysql - //list all tables in the database - // SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema = 'fusionpbx' - //check if table exists - // SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema = 'fusionpbx' AND TABLE_NAME = 'v_groups' - //check if column exists - // SELECT * FROM information_schema.COLUMNS where TABLE_SCHEMA = 'fusionpbx' AND TABLE_NAME = 'v_cdr' AND COLUMN_NAME = 'context' - //oracle - //check if table exists - // SELECT TABLE_NAME FROM ALL_TABLES - - //update the app db array add exists true or false - $sql = ''; - foreach ($this->apps as $x => $app) { - if (isset($app['db'])) foreach ($app['db'] as $y => $row) { - if (isset($row['table']['name'])) { - if (is_array($row['table']['name'])) { - $table_name = $row['table']['name']['text']; - } - else { - $table_name = $row['table']['name']; - } - } - else { - //old array syntax - if (is_array($row['table'])) { - $table_name = $row['table']['text']; - } - else { - $table_name = $row['table']; - } - } - if (!empty($table_name)) { - - //check if the table exists - if ($this->db_table_exists($db_type, $db_name, $table_name)) { - $this->apps[$x]['db'][$y]['exists'] = 'true'; - } - else { - $this->apps[$x]['db'][$y]['exists'] = 'false'; - } - //check if the column exists - foreach ($row['fields'] as $z => $field) { - if (!empty($field['deprecated']) && $field['deprecated'] == "true") { - //skip this field - } - else { - if (is_array($field['name'])) { - $field_name = $field['name']['text']; - } - else { - $field_name = $field['name']; - } - if (!empty($field_name)) { - if ($this->db_column_exists ($db_type, $db_name, $table_name, $field_name)) { - //found - $this->apps[$x]['db'][$y]['fields'][$z]['exists'] = 'true'; - } - else { - //not found - $this->apps[$x]['db'][$y]['fields'][$z]['exists'] = 'false'; - } - } - unset($field_name); - } - } - unset($table_name); + } + } + //rebuild and populate the table + foreach ($this->apps as $x => $app) { + if (isset($app['db'])) { + foreach ($app['db'] as $y => $row) { + if (is_array($row['table']['name'])) { + $table_name = $row['table']['name']['text']; + } else { + $table_name = $row['table']['name']; + } + if (!empty($field['rebuild']) && $row['rebuild'] == "true") { + if ($db_type == "sqlite") { + //start the transaction + //$sql_update .= "BEGIN TRANSACTION;\n"; + //rename the table + $sql_update .= "ALTER TABLE " . $table_name . " RENAME TO tmp_" . $table_name . ";\n"; + //create the table + $sql_update .= $this->db_create_table($this->apps, $db_type, $table_name); + //insert the data into the new table + $sql_update .= $this->db_insert_into($this->apps, $db_type, $table_name); + //drop the old table + $sql_update .= "DROP TABLE tmp_" . $table_name . ";\n"; + //commit the transaction + //$sql_update .= "COMMIT;\n"; } } } + } + } - //prepare the variables - $sql_update = ''; + // initialize response variable + $response = ''; - //add missing tables and fields - foreach ($this->apps as $x => $app) { - if (isset($app['db'])) foreach ($app['db'] as $y => $row) { + //display results as html + if ($format == "html") { + //show the database type + $response .= "" . $text['header-database_type'] . ": " . $db_type . "

"; + //start the table + $response .= "\n"; + //show the changes + if (!empty($sql_update)) { + $response .= "\n"; + $response .= "\n"; + $response .= "\n"; + } + //list all tables + $response .= "\n"; + $response .= "\n"; + $response .= "\n"; + $response .= "\n"; + $response .= "\n"; + //build the html while looping through the app db array + $sql = ''; + foreach ($this->apps as $app) { + if (isset($app['db'])) { + foreach ($app['db'] as $row) { if (is_array($row['table']['name'])) { $table_name = $row['table']['name']['text']; - if ($this->db_table_exists($db_type, $db_name, $row['table']['name']['deprecated'])) { - $row['exists'] = "false"; //testing - if ($db_type == "pgsql") { - $sql_update .= "ALTER TABLE ".$row['table']['name']['deprecated']." RENAME TO ".$row['table']['name']['text'].";\n"; - } - if ($db_type == "mysql") { - $sql_update .= "RENAME TABLE ".$row['table']['name']['deprecated']." TO ".$row['table']['name']['text'].";\n"; - } - if ($db_type == "sqlite") { - $sql_update .= "ALTER TABLE ".$row['table']['name']['deprecated']." RENAME TO ".$row['table']['name']['text'].";\n"; - } - } - else { - if ($this->db_table_exists($db_type, $db_name, $row['table']['name']['text'])) { - $row['exists'] = "true"; - } - else { - $row['exists'] = "false"; - $sql_update .= $this->db_create_table($this->apps, $db_type, $row['table']['name']['text']); - } - } - } - else { - if ($this->db_table_exists($db_type, $db_name, $row['table']['name'])) { - $row['exists'] = "true"; - } - else { - $row['exists'] = "false"; - } + } else { $table_name = $row['table']['name']; } + $response .= "\n"; //check if the table exists - if ($row['exists'] == "true") { - if (count($row['fields']) > 0) { - foreach ($row['fields'] as $z => $field) { - if (!empty($field['deprecated']) && $field['deprecated'] == "true") { - //skip this field - } - else { - //get the data type - if (is_array($field['type'])) { - $field_type = $field['type'][$db_type]; - } - else { - $field_type = $field['type']; - } - //get the field name - if (is_array($field['name'])) { - $field_name = $field['name']['text']; - } - else { - $field_name = $field['name']; - } + if ($row['exists'] == "true") { + $response .= "\n"; + $response .= "\n"; - //check if the field exists - // if ($this->db_column_exists($db_type, $db_name, $table_name, $field_name)) { - // $field['exists'] = "true"; - // } - // else { - // $field['exists'] = "false"; - // } - - //add or rename fields - if (isset($field['name']['deprecated']) && $this->db_column_exists ($db_type, $db_name, $table_name, $field['name']['deprecated'])) { - if ($db_type == "pgsql") { - $sql_update .= "ALTER TABLE ".$table_name." RENAME COLUMN ".$field['name']['deprecated']." to ".$field['name']['text'].";\n"; - } - if ($db_type == "mysql") { - $field_type = str_replace("AUTO_INCREMENT PRIMARY KEY", "", $field_type); - $sql_update .= "ALTER TABLE ".$table_name." CHANGE ".$field['name']['deprecated']." ".$field['name']['text']." ".$field_type.";\n"; - } - if ($db_type == "sqlite") { - //a change has been made to the field name - $this->apps[$x]['db'][$y]['rebuild'] = 'true'; - } - } - else { - //find missing fields and add them - if ($field['exists'] == "false") { - $sql_update .= "ALTER TABLE ".$table_name." ADD ".$field_name." ".$field_type.";\n"; - } - } - - //change the data type if it has been changed - //if the data type in the app db array is different than the type in the database then change the data type - if ($this->data_types) { - $db_field_type = $this->db_column_data_type ($db_type, $db_name, $table_name, $field_name); - $field_type_array = explode("(", $field_type); - $field_type = $field_type_array[0]; - if (trim($db_field_type) != trim($field_type) && !empty($db_field_type)) { - if ($db_type == "pgsql") { - if (strtolower($field_type) == "uuid") { - $sql_update .= "ALTER TABLE ".$table_name." ALTER COLUMN ".$field_name." TYPE uuid USING\n"; - $sql_update .= "CAST(regexp_replace(".$field_name.", '([A-Z0-9]{4})([A-Z0-9]{12})', E'\\1-\\2')\n"; - $sql_update .= "AS uuid);\n"; - } - else { - //field type has not changed - if ($db_field_type == "integer" && strtolower($field_type) == "serial") { } - else if ($db_field_type == "timestamp without time zone" && strtolower($field_type) == "timestamp") { } - else if ($db_field_type == "timestamp without time zone" && strtolower($field_type) == "datetime") { } - else if ($db_field_type == "timestamp with time zone" && strtolower($field_type) == "timestamptz") { } - else if ($db_field_type == "integer" && strtolower($field_type) == "numeric") { } - else if ($db_field_type == "character" && strtolower($field_type) == "char") { } - //field type has changed - else { - switch ($field_type) { - case 'numeric': $using = $field_name."::numeric"; break; - case 'timestamp': - case 'datetime': $using = $field_name."::timestamp without time zone"; break; - case 'timestamptz': $using = $field_name."::timestamp with time zone"; break; - case 'boolean': $using = $field_name."::boolean"; break; - default: unset($using); - } - $sql_update .= "ALTER TABLE ".$table_name." ALTER COLUMN ".$field_name." TYPE ".$field_type." ".($using ? "USING ".$using : null).";\n"; - } - } - } - if ($db_type == "mysql") { - $type = explode("(", $db_field_type); - if ($type[0] == $field_type) { - //do nothing - } - else if ($field_type == "numeric" && $type[0] == "decimal") { - //do nothing - } - else { - $sql_update .= "ALTER TABLE ".$table_name." modify ".$field_name." ".$field_type.";\n"; - } - unset($type); - } - if ($db_type == "sqlite") { - //a change has been made to the field type - $this->apps[$x]['db'][$y]['rebuild'] = 'true'; - } - } - } - } - } - } - } - elseif (!is_array($row['table']['name'])) { - //create table - $sql_update .= $this->db_create_table($this->apps, $db_type, $row['table']['name']); - } - } - } - //rebuild and populate the table - foreach ($this->apps as $x => $app) { - if (isset($app['db'])) foreach ($app['db'] as $y => $row) { - if (is_array($row['table']['name'])) { - $table_name = $row['table']['name']['text']; - } - else { - $table_name = $row['table']['name']; - } - if (!empty($field['rebuild']) && $row['rebuild'] == "true") { - if ($db_type == "sqlite") { - //start the transaction - //$sql_update .= "BEGIN TRANSACTION;\n"; - //rename the table - $sql_update .= "ALTER TABLE ".$table_name." RENAME TO tmp_".$table_name.";\n"; - //create the table - $sql_update .= $this->db_create_table($this->apps, $db_type, $table_name); - //insert the data into the new table - $sql_update .= $this->db_insert_into($this->apps, $db_type, $table_name); - //drop the old table - $sql_update .= "DROP TABLE tmp_".$table_name.";\n"; - //commit the transaction - //$sql_update .= "COMMIT;\n"; - } - } - } - } - - // initialize response variable - $response = ''; - - //display results as html - if ($format == "html") { - //show the database type - $response .= "".$text['header-database_type'].": ".$db_type. "

"; - //start the table - $response .= "
\n"; + $response .= "
\n"; + $response .= "" . $text['label-sql_changes'] . ":
\n"; + $response .= "
\n";
+					$response .= $sql_update;
+					$response .= "
\n"; + $response .= "
\n"; + $response .= "
" . $text['label-table'] . "" . $text['label-exists'] . "" . $text['label-details'] . "
" . $table_name . "" . $text['option-true'] . "
\n"; - //show the changes - if (!empty($sql_update)) { - $response .= "\n"; - $response .= "\n"; - $response .= "\n"; - } - //list all tables - $response .= "\n"; - $response .= "\n"; - $response .= "\n"; - $response .= "\n"; - $response .= "\n"; - //build the html while looping through the app db array - $sql = ''; - foreach ($this->apps as $app) { - if (isset($app['db'])) foreach ($app['db'] as $row) { - if (is_array($row['table']['name'])) { - $table_name = $row['table']['name']['text']; - } - else { - $table_name = $row['table']['name']; - } + if (count($row['fields']) > 0) { + $response .= "\n"; } + } else { + $response .= "\n"; + $response .= "\n"; + $response .= "\n"; } - //end the list of tables - $response .= "
\n"; - $response .= "
\n"; - $response .= "".$text['label-sql_changes'].":
\n"; - $response .= "
\n";
-								$response .= $sql_update;
-								$response .= "
\n"; - $response .= "
\n"; - $response .= "
".$text['label-table']."".$text['label-exists']."".$text['label-details']."
\n"; + //show the list of columns + $response .= "\n"; $response .= "\n"; - - //check if the table exists - if ($row['exists'] == "true") { - $response .= "\n"; - $response .= "\n"; - - if (count($row['fields']) > 0) { - $response .= "\n"; + $response .= "\n"; + $response .= "\n"; + $response .= "\n"; + $response .= "\n"; + foreach ($row['fields'] as $field) { + if (!empty($field['deprecated']) && $field['deprecated'] == "true") { + //skip this field + } else { + if (is_array($field['name'])) { + $field_name = $field['name']['text']; + } else { + $field_name = $field['name']; } + if (is_array($field['type'])) { + $field_type = $field['type'][$db_type]; + } else { + $field_type = $field['type']; + } + $response .= "\n"; + $response .= "\n"; + $response .= "\n"; + if ($field['exists'] == "true") { + $response .= "\n"; + $response .= "\n"; + } else { + $response .= "\n"; + $response .= "\n"; + } + $response .= "\n"; } - else { - $response .= "\n"; - $response .= "\n"; - $response .= "\n"; - } - $response .= "\n"; + } + $response .= "
".$table_name."".$text['option-true']."\n"; - //show the list of columns - $response .= "\n"; - $response .= "\n"; - $response .= "\n"; - $response .= "\n"; - $response .= "\n"; - $response .= "\n"; - foreach ($row['fields'] as $field) { - if (!empty($field['deprecated']) && $field['deprecated'] == "true") { - //skip this field - } - else { - if (is_array($field['name'])) { - $field_name = $field['name']['text']; - } - else { - $field_name = $field['name']; - } - if (is_array($field['type'])) { - $field_type = $field['type'][$db_type]; - } - else { - $field_type = $field['type']; - } - $response .= "\n"; - $response .= "\n"; - $response .= "\n"; - if ($field['exists'] == "true") { - $response .= "\n"; - $response .= "\n"; - } - else { - $response .= "\n"; - $response .= "\n"; - } - $response .= "\n"; - } - } - $response .= "
".$text['label-name']."".$text['label-type']."".$text['label-exists']."
".$field_name."".$field_type."".$text['option-true']." ".$text['option-false']." 
\n"; - $response .= "
" . $text['label-name'] . "" . $text['label-type'] . "" . $text['label-exists'] . "
" . $field_name . "" . $field_type . "" . $text['option-true'] . " " . $text['option-false'] . " 
$table_name".$text['label-exists']."
".$text['option-false']."
 
\n"; + $response .= "
$table_name" . $text['label-exists'] . "
" . $text['option-false'] . "
 
\n"; - $response .= "
\n"; - - } - - //loop line by line through all the lines of sql code - $x = 0; - if (empty($sql_update) && $format == "text") { - $response .= " ".$text['label-schema'].": ".$text['label-no_change']."\n"; + $response .= "\n"; } - else { + } + } + //end the list of tables + $response .= "\n"; + $response .= "
\n"; + } + + //loop line by line through all the lines of sql code + $x = 0; + if (empty($sql_update) && $format == "text") { + $response .= " " . $text['label-schema'] . ": " . $text['label-no_change'] . "\n"; + } else { + if ($format == "text") { + $response .= " " . $text['label-schema'] . "\n"; + } + //$this->db->beginTransaction(); + $update_array = explode(";", $sql_update); + foreach ($update_array as $sql) { + if (strlen(trim($sql))) { + try { + $this->database->db->query(trim($sql)); if ($format == "text") { - $response .= " ".$text['label-schema']."\n"; + $response .= " $sql;\n"; } - //$this->db->beginTransaction(); - $update_array = explode(";", $sql_update); - foreach($update_array as $sql) { - if (strlen(trim($sql))) { - try { - $this->database->db->query(trim($sql)); - if ($format == "text") { - $response .= " $sql;\n"; - } - } - catch (PDOException $error) { - $response .= " error: " . $error->getMessage() . " sql: $sql\n"; - } - } - } - //$this->db->commit(); - $response .= "\n"; - unset ($sql_update, $sql); - } - - //refresh each postgresql subscription with its publication - if ($db_type == "pgsql") { - //get the list of postgresql subscriptions - $sql = "select subname from pg_subscription; "; - $pg_subscriptions = $this->database->select($sql, null, 'all'); - unset($sql, $parameters); - - //refresh each subscription publication - foreach ($pg_subscriptions as $row) { - $sql = "ALTER SUBSCRIPTION ".$row['subname']." REFRESH PUBLICATION;"; - $response .= $sql; - $this->database->execute($sql); + } catch (PDOException $error) { + $response .= " error: " . $error->getMessage() . " sql: $sql\n"; } } + } + //$this->db->commit(); + $response .= "\n"; + unset($sql_update, $sql); + } - //handle response - //if ($output == "echo") { - // echo $response; - //} - //else if ($output == "return") { - return $response; - //} - } //end function + //refresh each postgresql subscription with its publication + if ($db_type == "pgsql") { + //get the list of postgresql subscriptions + $sql = "select subname from pg_subscription; "; + $pg_subscriptions = $this->database->select($sql, null, 'all'); + unset($sql, $parameters); + + //refresh each subscription publication + foreach ($pg_subscriptions as $row) { + $sql = "ALTER SUBSCRIPTION " . $row['subname'] . " REFRESH PUBLICATION;"; + $response .= $sql; + $this->database->execute($sql); + } + } + + //handle response + //if ($output == "echo") { + // echo $response; + //} + //else if ($output == "return") { + return $response; + //} + } //end function } + } //example use - //require_once "resources/classes/schema.php"; - //$obj = new schema; - //$obj->db_type = $db_type; - //$obj->schema(); - //$result_array = $schema->obj['sql']; - //print_r($result_array); - +//require_once "resources/classes/schema.php"; +//$obj = new schema; +//$obj->db_type = $db_type; +//$obj->schema(); +//$result_array = $schema->obj['sql']; +//print_r($result_array); ?> From bc22ab8cc4263dcd1bdf6cdcea243d04f7d80504 Mon Sep 17 00:00:00 2001 From: fusionate Date: Tue, 28 Jan 2025 17:18:28 -0700 Subject: [PATCH 042/196] Contact - View: Show speed dial prefix and number after a Contact's number, if defined. --- core/contacts/contact_phones_view.php | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/core/contacts/contact_phones_view.php b/core/contacts/contact_phones_view.php index 4f0cf25874..81fe1f4278 100644 --- a/core/contacts/contact_phones_view.php +++ b/core/contacts/contact_phones_view.php @@ -51,6 +51,29 @@ //show if exists if (!empty($contact_phones)) { + //detect speed dial prefix from dialplan + $sql = "select dialplan_detail_data from v_dialplan_details "; + $sql .= "where domain_uuid = :domain_uuid "; + $sql .= "and dialplan_uuid = ( "; + $sql .= " select dialplan_uuid from v_dialplan_details "; + $sql .= " where domain_uuid = :domain_uuid "; + $sql .= " and dialplan_detail_data like 'app.lua speed_dial%' "; + $sql .= " and (dialplan_detail_enabled = true or dialplan_detail_enabled is null) "; + $sql .= " limit 1 "; + $sql .= ") "; + $sql .= "and dialplan_detail_tag = 'condition' "; + $sql .= "and dialplan_detail_type = 'destination_number' "; + $sql .= "and dialplan_detail_data like '^\\\\%' "; + $sql .= "and (dialplan_detail_enabled = true or dialplan_detail_enabled is null) "; + $sql .= "limit 1"; + $parameters['domain_uuid'] = $domain_uuid; + $database = new database; + $speed_dial_condition = $database->select($sql, $parameters, 'column'); + if (!empty($speed_dial_condition)) { + $speed_dial_prefix = str_replace('(.*)', '', trim($speed_dial_condition,'^\$')); // default: ^\*0(.*)$ + } + unset($sql, $speed_dial_condition); + //javascript function: send_cmd echo "\n"; ?> + diff --git a/app/devices/device_vendors.php b/app/devices/device_vendors.php index 9d4a24e75d..9aed554771 100644 --- a/app/devices/device_vendors.php +++ b/app/devices/device_vendors.php @@ -178,8 +178,12 @@ if (is_array($result) && @sizeof($result) != 0) { $x = 0; foreach($result as $row) { + $list_row_url = ''; if (permission_exists('device_vendor_edit')) { $list_row_url = "device_vendor_edit.php?id=".urlencode($row['device_vendor_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('device_vendor_edit') || permission_exists('device_vendor_delete')) { @@ -222,3 +226,4 @@ require_once "resources/footer.php"; ?> + diff --git a/app/devices/devices.php b/app/devices/devices.php index ec56e1a667..7c251692a5 100644 --- a/app/devices/devices.php +++ b/app/devices/devices.php @@ -397,8 +397,12 @@ } } + $list_row_url = ''; if (permission_exists('device_edit')) { $list_row_url = "device_edit.php?id=".urlencode($row['device_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } $device_provisioned_method = ''; @@ -473,3 +477,4 @@ require_once "resources/footer.php"; ?> + diff --git a/app/dialplans/dialplans.php b/app/dialplans/dialplans.php index 296b764c34..81c7f11b16 100644 --- a/app/dialplans/dialplans.php +++ b/app/dialplans/dialplans.php @@ -551,9 +551,13 @@ $x = 0; foreach ($dialplans as $row) { + $list_row_url = ''; if ($row['app_uuid'] == "4b821450-926b-175a-af93-a03c441818b1") { if (permission_exists('time_condition_edit') || permission_exists('dialplan_edit')) { $list_row_url = PROJECT_PATH."/app/time_conditions/time_condition_edit.php?id=".urlencode($row['dialplan_uuid']).(is_uuid($app_uuid) ? "&app_uuid=".urlencode($app_uuid) : null); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } } else if ( @@ -563,6 +567,9 @@ permission_exists('dialplan_edit') ) { $list_row_url = "dialplan_edit.php?id=".urlencode($row['dialplan_uuid']).(is_uuid($app_uuid) ? "&app_uuid=".urlencode($app_uuid) : null); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } else { unset($list_row_url); @@ -648,3 +655,4 @@ require_once "resources/footer.php"; ?> + diff --git a/app/email_queue/email_queue.php b/app/email_queue/email_queue.php index faa6abc0c8..13e1d92e8e 100644 --- a/app/email_queue/email_queue.php +++ b/app/email_queue/email_queue.php @@ -337,8 +337,12 @@ if (is_array($email_queue) && @sizeof($email_queue) != 0) { $x = 0; foreach ($email_queue as $row) { + $list_row_url = ''; if (permission_exists('email_queue_edit')) { $list_row_url = "email_queue_edit.php?id=".urlencode($row['email_queue_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('email_queue_add') || permission_exists('email_queue_edit') || permission_exists('email_queue_delete')) { diff --git a/app/email_templates/email_templates.php b/app/email_templates/email_templates.php index ae1b22216a..36ae8687f0 100644 --- a/app/email_templates/email_templates.php +++ b/app/email_templates/email_templates.php @@ -257,8 +257,12 @@ if (!empty($result)) { $x = 0; foreach($result as $row) { + $list_row_url = ''; if (permission_exists('email_template_edit')) { $list_row_url = "email_template_edit.php?id=".urlencode($row['email_template_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('email_template_add') || permission_exists('email_template_edit') || permission_exists('email_template_delete')) { @@ -323,3 +327,4 @@ require_once "resources/footer.php"; ?> + diff --git a/app/event_guard/event_guard_logs.php b/app/event_guard/event_guard_logs.php index 7e40486006..38dce4027f 100644 --- a/app/event_guard/event_guard_logs.php +++ b/app/event_guard/event_guard_logs.php @@ -244,8 +244,12 @@ if (is_array($event_guard_logs) && @sizeof($event_guard_logs) != 0) { $x = 0; foreach ($event_guard_logs as $row) { + $list_row_url = ''; if (permission_exists('event_guard_log_edit')) { $list_row_url = "event_guard_log_edit.php?id=".urlencode($row['event_guard_log_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('event_guard_log_add') || permission_exists('event_guard_log_edit') || permission_exists('event_guard_log_delete')) { diff --git a/app/extensions/extensions.php b/app/extensions/extensions.php index 12eb539b7d..fac86bdfb3 100644 --- a/app/extensions/extensions.php +++ b/app/extensions/extensions.php @@ -339,8 +339,12 @@ if (is_array($extensions) && @sizeof($extensions) != 0) { $x = 0; foreach($extensions as $row) { + $list_row_url = ''; if (permission_exists('extension_edit')) { $list_row_url = "extension_edit.php?id=".urlencode($row['extension_uuid']).(is_numeric($page) ? '&page='.urlencode($page) : null); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('extension_enabled') || permission_exists('extension_delete')) { @@ -447,3 +451,4 @@ require_once "resources/footer.php"; ?> + diff --git a/app/fax/fax.php b/app/fax/fax.php index f87e1e63df..125a7b1305 100644 --- a/app/fax/fax.php +++ b/app/fax/fax.php @@ -247,8 +247,12 @@ if (is_array($result) && @sizeof($result) != 0) { $x = 0; foreach ($result as $row) { + $list_row_url = ''; if (permission_exists('fax_extension_edit')) { $list_row_url = "fax_edit.php?id=".urlencode($row['fax_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('fax_extension_add') || permission_exists('fax_extension_delete')) { @@ -325,3 +329,4 @@ require_once "resources/footer.php"; ?> + diff --git a/app/fax_queue/fax_queue.php b/app/fax_queue/fax_queue.php index 1822255f86..5e51787f56 100644 --- a/app/fax_queue/fax_queue.php +++ b/app/fax_queue/fax_queue.php @@ -332,8 +332,12 @@ if (!empty($fax_queue)) { $x = 0; foreach ($fax_queue as $row) { + $list_row_url = ''; if ($permission['fax_queue_edit']) { $list_row_url = "fax_queue_edit.php?id=".urlencode($row['fax_queue_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if ($permission['fax_queue_add'] || $permission['fax_queue_edit'] || $permission['fax_queue_delete']) { diff --git a/app/fifo/fifo.php b/app/fifo/fifo.php index 898a333c82..54e50a05a0 100644 --- a/app/fifo/fifo.php +++ b/app/fifo/fifo.php @@ -264,6 +264,9 @@ foreach ($fifo as $row) { if (permission_exists('fifo_edit')) { $list_row_url = "fifo_edit.php?id=".urlencode($row['fifo_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('fifo_add') || permission_exists('fifo_edit') || permission_exists('fifo_delete')) { @@ -320,3 +323,4 @@ require_once "resources/footer.php"; ?> + diff --git a/app/gateways/gateways.php b/app/gateways/gateways.php index cd6299c25f..06f3a7bcc7 100644 --- a/app/gateways/gateways.php +++ b/app/gateways/gateways.php @@ -286,8 +286,12 @@ if (!empty($gateways)) { $x = 0; foreach($gateways as $row) { + $list_row_url = ''; if (permission_exists('gateway_edit')) { $list_row_url = "gateway_edit.php?id=".urlencode($row['gateway_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('gateway_add') || permission_exists('gateway_edit') || permission_exists('gateway_delete')) { @@ -391,3 +395,4 @@ require_once "resources/footer.php"; ?> + diff --git a/app/ivr_menus/ivr_menus.php b/app/ivr_menus/ivr_menus.php index 2c4968369d..287a2a66f5 100644 --- a/app/ivr_menus/ivr_menus.php +++ b/app/ivr_menus/ivr_menus.php @@ -236,8 +236,12 @@ if (!empty($ivr_menus)) { $x = 0; foreach($ivr_menus as $row) { + $list_row_url = ''; if (permission_exists('ivr_menu_edit')) { $list_row_url = "ivr_menu_edit.php?id=".urlencode($row['ivr_menu_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('ivr_menu_add') || permission_exists('ivr_menu_edit') || permission_exists('ivr_menu_delete')) { @@ -298,3 +302,4 @@ require_once "resources/footer.php"; ?> + diff --git a/app/modules/modules.php b/app/modules/modules.php index f2ec07b185..bb3a16a2dc 100644 --- a/app/modules/modules.php +++ b/app/modules/modules.php @@ -202,8 +202,12 @@ echo "\n"; write_header($row["module_category"]); } + $list_row_url = ''; if (permission_exists('module_edit')) { $list_row_url = "module_edit.php?id=".urlencode($row['module_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('module_edit') || permission_exists('module_delete')) { @@ -283,3 +287,4 @@ require_once "resources/footer.php"; ?> + diff --git a/app/number_translations/number_translations.php b/app/number_translations/number_translations.php index bc02e4fef8..3b58216bf3 100644 --- a/app/number_translations/number_translations.php +++ b/app/number_translations/number_translations.php @@ -225,8 +225,12 @@ if (!empty($number_translations)) { $x = 0; foreach ($number_translations as $row) { + $list_row_url = ''; if (permission_exists('number_translation_edit')) { $list_row_url = "number_translation_edit.php?id=".urlencode($row['number_translation_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('number_translation_add') || permission_exists('number_translation_edit') || permission_exists('number_translation_delete')) { @@ -276,3 +280,4 @@ require_once "resources/footer.php"; ?> + diff --git a/app/phrases/phrases.php b/app/phrases/phrases.php index e8b5bd16ab..0edd4f6559 100644 --- a/app/phrases/phrases.php +++ b/app/phrases/phrases.php @@ -211,8 +211,12 @@ if (is_array($phrases) && @sizeof($phrases) != 0) { $x = 0; foreach($phrases as $row) { + $list_row_url = ''; if (permission_exists('phrase_edit')) { $list_row_url = "phrase_edit.php?id=".urlencode($row['phrase_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('phrase_add') || permission_exists('phrase_edit') || permission_exists('phrase_delete')) { @@ -273,3 +277,4 @@ require_once "resources/footer.php"; ?> + diff --git a/app/pin_numbers/pin_numbers.php b/app/pin_numbers/pin_numbers.php index 1740c631a2..e7581cecf7 100644 --- a/app/pin_numbers/pin_numbers.php +++ b/app/pin_numbers/pin_numbers.php @@ -189,8 +189,12 @@ if (is_array($pin_numbers) && @sizeof($pin_numbers) != 0) { $x = 0; foreach ($pin_numbers as $row) { + $list_row_url = ''; if (permission_exists('pin_number_edit')) { $list_row_url = "pin_number_edit.php?id=".urlencode($row['pin_number_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('pin_number_add') || permission_exists('pin_number_edit') || permission_exists('pin_number_delete')) { @@ -241,3 +245,4 @@ require_once "resources/footer.php"; ?> + diff --git a/app/recordings/recordings.php b/app/recordings/recordings.php index b429120270..0a8f68b13b 100644 --- a/app/recordings/recordings.php +++ b/app/recordings/recordings.php @@ -529,8 +529,12 @@ echo "\n"; echo "\n"; // dummy row to maintain alternating background color } + $list_row_url = ''; if (permission_exists('recording_edit')) { $list_row_url = "recording_edit.php?id=".urlencode($row['recording_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('recording_delete')) { @@ -710,3 +714,4 @@ } ?> + diff --git a/app/ring_groups/ring_groups.php b/app/ring_groups/ring_groups.php index 59473180d1..f995d7cdf0 100644 --- a/app/ring_groups/ring_groups.php +++ b/app/ring_groups/ring_groups.php @@ -257,8 +257,12 @@ if (is_array($ring_groups) && @sizeof($ring_groups) != 0) { $x = 0; foreach ($ring_groups as $row) { + $list_row_url = ''; if (permission_exists('ring_group_edit')) { $list_row_url = "ring_group_edit.php?id=".urlencode($row['ring_group_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('ring_group_add') || permission_exists('ring_group_edit') || permission_exists('ring_group_delete')) { @@ -315,3 +319,4 @@ require_once "resources/footer.php"; ?> + diff --git a/app/sip_profiles/sip_profiles.php b/app/sip_profiles/sip_profiles.php index a18b92c5e5..956d0727ea 100644 --- a/app/sip_profiles/sip_profiles.php +++ b/app/sip_profiles/sip_profiles.php @@ -188,8 +188,12 @@ if (!empty($sip_profiles) && @sizeof($sip_profiles) != 0) { $x = 0; foreach ($sip_profiles as $row) { + $list_row_url = ''; if (permission_exists('sip_profile_edit')) { $list_row_url = "sip_profile_edit.php?id=".urlencode($row['sip_profile_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('sip_profile_add') || permission_exists('sip_profile_edit') || permission_exists('sip_profile_delete')) { @@ -239,3 +243,4 @@ require_once "resources/footer.php"; ?> + diff --git a/app/sip_status/sip_status.php b/app/sip_status/sip_status.php index 364023a108..5dfb85360e 100644 --- a/app/sip_status/sip_status.php +++ b/app/sip_status/sip_status.php @@ -331,3 +331,4 @@ require_once "resources/footer.php"; ?> + diff --git a/app/sofia_global_settings/sofia_global_settings.php b/app/sofia_global_settings/sofia_global_settings.php index deb31716d5..12a40fb1ec 100644 --- a/app/sofia_global_settings/sofia_global_settings.php +++ b/app/sofia_global_settings/sofia_global_settings.php @@ -209,8 +209,12 @@ if (!empty($sofia_global_settings) && @sizeof($sofia_global_settings) != 0) { $x = 0; foreach ($sofia_global_settings as $row) { + $list_row_url = ''; if (permission_exists('sofia_global_setting_edit')) { $list_row_url = "sofia_global_setting_edit.php?id=".urlencode($row['sofia_global_setting_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('sofia_global_setting_add') || permission_exists('sofia_global_setting_edit') || permission_exists('sofia_global_setting_delete')) { @@ -261,3 +265,4 @@ require_once "resources/footer.php"; ?> + diff --git a/app/streams/streams.php b/app/streams/streams.php index 5b872b764a..c065cad90b 100644 --- a/app/streams/streams.php +++ b/app/streams/streams.php @@ -248,8 +248,12 @@ if (!empty($streams)) { $x = 0; foreach ($streams as $row) { + $list_row_url = ''; if (permission_exists('stream_edit')) { $list_row_url = "stream_edit.php?id=".urlencode($row['stream_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('stream_add') || permission_exists('stream_edit') || permission_exists('stream_delete')) { @@ -315,3 +319,4 @@ require_once "resources/footer.php"; ?> + diff --git a/app/time_conditions/time_conditions.php b/app/time_conditions/time_conditions.php index 63c826305e..6f5eede525 100644 --- a/app/time_conditions/time_conditions.php +++ b/app/time_conditions/time_conditions.php @@ -218,8 +218,12 @@ if (is_array($dialplans) && @sizeof($dialplans) != 0) { $x = 0; foreach ($dialplans as $row) { + $list_row_url = ''; if (permission_exists('time_condition_edit')) { $list_row_url = "time_condition_edit.php?id=".urlencode($row['dialplan_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('time_condition_add') || permission_exists('time_condition_edit') || permission_exists('time_condition_delete')) { @@ -282,3 +286,4 @@ require_once "resources/footer.php"; ?> + diff --git a/app/vars/vars.php b/app/vars/vars.php index d954ff394d..3e17ca5a23 100644 --- a/app/vars/vars.php +++ b/app/vars/vars.php @@ -224,8 +224,12 @@ echo "\n"; write_header($row["var_category"]); } + $list_row_url = ''; if (permission_exists('var_edit')) { $list_row_url = "var_edit.php?id=".urlencode($row['var_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('var_add') || permission_exists('var_edit') || permission_exists('var_delete')) { @@ -283,3 +287,4 @@ require_once "resources/footer.php"; ?> + diff --git a/app/voicemail_greetings/voicemail_greetings.php b/app/voicemail_greetings/voicemail_greetings.php index 93a5674dac..49eec2c8bb 100644 --- a/app/voicemail_greetings/voicemail_greetings.php +++ b/app/voicemail_greetings/voicemail_greetings.php @@ -437,8 +437,12 @@ echo "\n"; echo "\n"; // dummy row to maintain alternating background color } + $list_row_url = ''; if (permission_exists('voicemail_greeting_edit')) { $list_row_url = "voicemail_greeting_edit.php?id=".urlencode($row['voicemail_greeting_uuid'])."&voicemail_id=".urlencode($voicemail_id); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('voicemail_greeting_delete')) { @@ -605,3 +609,4 @@ } ?> + diff --git a/app/voicemails/voicemails.php b/app/voicemails/voicemails.php index 250e0b7160..ad6d6c1903 100644 --- a/app/voicemails/voicemails.php +++ b/app/voicemails/voicemails.php @@ -297,8 +297,12 @@ if (is_array($voicemails) && sizeof($voicemails) != 0) { $x = 0; foreach ($voicemails as $row) { + $list_row_url = ''; if (permission_exists('voicemail_edit')) { $list_row_url = "voicemail_edit.php?id=".urlencode($row['voicemail_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('voicemail_edit') || permission_exists('voicemail_delete')) { @@ -373,3 +377,4 @@ //include the footer require_once "resources/footer.php"; + diff --git a/app/xml_cdr/xml_cdr.php b/app/xml_cdr/xml_cdr.php index 2b59f228a3..68669d90a8 100644 --- a/app/xml_cdr/xml_cdr.php +++ b/app/xml_cdr/xml_cdr.php @@ -877,8 +877,12 @@ $content .= "\n"; $content .= "\n"; // dummy row to maintain alternating background color } + $list_row_url = ''; if ($permission['xml_cdr_details']) { $list_row_url = "xml_cdr_details.php?id=".urlencode($row['xml_cdr_uuid']).($_REQUEST['show'] ? "&show=all" : null); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } $content .= "\n"; if (!$archive_request && $permission['xml_cdr_delete']) { @@ -1059,3 +1063,4 @@ require_once "resources/footer.php"; ?> + diff --git a/core/contacts/contact_addresses.php b/core/contacts/contact_addresses.php index 7d17fd0180..8e375a3480 100644 --- a/core/contacts/contact_addresses.php +++ b/core/contacts/contact_addresses.php @@ -88,8 +88,12 @@ $x = 0; foreach ($contact_addresses as $row) { $map_query = $row['address_street']." ".$row['address_extended'].", ".$row['address_locality'].", ".$row['address_region'].", ".$row['address_region'].", ".$row['address_postal_code']; + $list_row_url = ''; if (permission_exists('contact_address_edit')) { $list_row_url = "contact_address_edit.php?contact_uuid=".urlencode($row['contact_uuid'])."&id=".urlencode($row['contact_address_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('contact_address_delete')) { @@ -123,3 +127,4 @@ } ?> + diff --git a/core/contacts/contact_attachments.php b/core/contacts/contact_attachments.php index 7986b3fbb7..8b2c913c78 100644 --- a/core/contacts/contact_attachments.php +++ b/core/contacts/contact_attachments.php @@ -107,8 +107,12 @@ foreach ($contact_attachments as $row) { $attachment_type = strtolower(pathinfo($row['attachment_filename'], PATHINFO_EXTENSION)); $attachment_type_label = $attachment_type == 'jpg' || $attachment_type == 'jpeg' || $attachment_type == 'gif' || $attachment_type == 'png' ? $text['label-image'] : $text['label-file']; + $list_row_url = ''; if (permission_exists('contact_attachment_edit')) { $list_row_url = "contact_attachment_edit.php?contact_uuid=".urlencode($row['contact_uuid'])."&id=".urlencode($row['contact_attachment_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('contact_attachment_delete')) { @@ -147,3 +151,4 @@ } ?> + diff --git a/core/contacts/contact_emails.php b/core/contacts/contact_emails.php index c89e9da80b..6afcb02539 100644 --- a/core/contacts/contact_emails.php +++ b/core/contacts/contact_emails.php @@ -79,8 +79,12 @@ if (!empty($contact_emails)) { $x = 0; foreach ($contact_emails as $row) { + $list_row_url = ''; if (permission_exists('contact_email_edit')) { $list_row_url = "contact_email_edit.php?contact_uuid=".urlencode($row['contact_uuid'])."&id=".urlencode($row['contact_email_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('contact_email_delete')) { @@ -110,3 +114,4 @@ } ?> + diff --git a/core/contacts/contact_extensions.php b/core/contacts/contact_extensions.php index 96678d5e8f..a848bd0976 100644 --- a/core/contacts/contact_extensions.php +++ b/core/contacts/contact_extensions.php @@ -77,8 +77,12 @@ if (!empty($contact_extensions)) { $x = 0; foreach ($contact_extensions as $row) { + $list_row_url = ''; if (permission_exists('extension_edit')) { $list_row_url = PROJECT_PATH.'/app/extensions/extension_edit.php?id='.urlencode($row['extension_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; echo " "; @@ -109,3 +113,4 @@ } ?> + diff --git a/core/contacts/contact_notes.php b/core/contacts/contact_notes.php index 07d45b94db..0e66f265ec 100644 --- a/core/contacts/contact_notes.php +++ b/core/contacts/contact_notes.php @@ -82,8 +82,12 @@ $contact_note = $row['contact_note']; $contact_note = escape($contact_note); $contact_note = str_replace("\n","
",$contact_note); + $list_row_url = ''; if (permission_exists('contact_note_add')) { $list_row_url = "contact_note_edit.php?contact_uuid=".escape($row['contact_uuid'])."&id=".escape($row['contact_note_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('contact_note_delete')) { @@ -112,3 +116,4 @@ } ?> + diff --git a/core/contacts/contact_phones.php b/core/contacts/contact_phones.php index b70759f153..51d18b2c14 100644 --- a/core/contacts/contact_phones.php +++ b/core/contacts/contact_phones.php @@ -93,8 +93,12 @@ if (!empty($contact_phones)) { $x = 0; foreach ($contact_phones as $row) { + $list_row_url = ''; if (permission_exists('contact_phone_edit')) { $list_row_url = "contact_phone_edit.php?contact_uuid=".urlencode($row['contact_uuid'])."&id=".urlencode($row['contact_phone_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('contact_phone_delete')) { @@ -144,3 +148,4 @@ } ?> + diff --git a/core/contacts/contact_relations.php b/core/contacts/contact_relations.php index 01e2c77779..36e006cf8b 100644 --- a/core/contacts/contact_relations.php +++ b/core/contacts/contact_relations.php @@ -93,8 +93,12 @@ if (!empty($contact_relations)) { $x = 0; foreach ($contact_relations as $row) { + $list_row_url = ''; if (permission_exists('contact_relation_edit')) { $list_row_url = "contact_relation_edit.php?contact_uuid=".urlencode($contact_uuid)."&id=".urlencode($row['contact_relation_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('contact_relation_delete')) { @@ -124,3 +128,4 @@ } ?> + diff --git a/core/contacts/contact_settings.php b/core/contacts/contact_settings.php index 0fa2d63a3b..6ded1b022a 100644 --- a/core/contacts/contact_settings.php +++ b/core/contacts/contact_settings.php @@ -86,8 +86,12 @@ if (!empty($contact_settings)) { $x = 0; foreach ($contact_settings as $row) { + $list_row_url = ''; if (permission_exists('contact_setting_edit')) { $list_row_url = "contact_setting_edit.php?contact_uuid=".urlencode($contact_uuid)."&id=".urlencode($row['contact_setting_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('contact_setting_delete')) { @@ -133,3 +137,4 @@ } ?> + diff --git a/core/contacts/contact_times.php b/core/contacts/contact_times.php index 1ab5fcf912..193fa0f911 100644 --- a/core/contacts/contact_times.php +++ b/core/contacts/contact_times.php @@ -97,8 +97,12 @@ } $tmp = explode(' ', $row['time_start']); $time_start = $tmp[0]; + $list_row_url = ''; if (permission_exists('contact_time_edit')) { $list_row_url = "contact_time_edit.php?contact_uuid=".urlencode($row['contact_uuid'])."&id=".urlencode($row['contact_time_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('contact_time_delete')) { @@ -129,3 +133,4 @@ } ?> + diff --git a/core/contacts/contact_urls.php b/core/contacts/contact_urls.php index d04d70cbb5..7de4cb087d 100644 --- a/core/contacts/contact_urls.php +++ b/core/contacts/contact_urls.php @@ -81,8 +81,12 @@ if (!empty($contact_urls)) { $x = 0; foreach ($contact_urls as $row) { + $list_row_url = ''; if (permission_exists('contact_url_edit')) { $list_row_url = "contact_url_edit.php?contact_uuid=".urlencode($row['contact_uuid'])."&id=".urlencode($row['contact_url_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('contact_url_delete')) { @@ -112,3 +116,4 @@ } ?> + diff --git a/core/contacts/contacts.php b/core/contacts/contacts.php index f35857b5bc..abdbdbfe2f 100644 --- a/core/contacts/contacts.php +++ b/core/contacts/contacts.php @@ -396,6 +396,9 @@ $x = 0; foreach($contacts as $row) { $list_row_url = "contact_view.php?id=".urlencode($row['contact_uuid'])."&query_string=".urlencode($_SERVER["QUERY_STRING"]); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } echo "\n"; if (permission_exists('contact_delete')) { echo " \n"; @@ -469,3 +472,5 @@ require_once "resources/footer.php"; ?> + + diff --git a/core/dashboard/dashboard.php b/core/dashboard/dashboard.php index 7d3076b9dd..841a95ce4f 100644 --- a/core/dashboard/dashboard.php +++ b/core/dashboard/dashboard.php @@ -202,8 +202,12 @@ if (!empty($dashboard)) { $x = 0; foreach ($dashboard as $row) { + $list_row_url = ''; if (permission_exists('dashboard_edit')) { $list_row_url = "dashboard_edit.php?id=".urlencode($row['dashboard_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('dashboard_add') || permission_exists('dashboard_edit') || permission_exists('dashboard_delete')) { @@ -256,3 +260,4 @@ require_once "resources/footer.php"; ?> + diff --git a/core/databases/databases.php b/core/databases/databases.php index 9e5280ebb6..a579b486ef 100644 --- a/core/databases/databases.php +++ b/core/databases/databases.php @@ -200,3 +200,4 @@ require_once "resources/footer.php"; ?> + diff --git a/core/users/users.php b/core/users/users.php index cffbe80a8e..304f6a3d32 100644 --- a/core/users/users.php +++ b/core/users/users.php @@ -276,8 +276,12 @@ if (is_array($users) && @sizeof($users) != 0) { $x = 0; foreach ($users as $row) { + $list_row_url = ''; if (permission_exists('user_edit')) { $list_row_url = "user_edit.php?id=".urlencode($row['user_uuid']); + if ($row['domain_uuid'] != $_SESSION['domain_uuid'] && permission_exists('domain_select')) { + $list_row_url .= '&domain_uuid='.urlencode($row['domain_uuid']).'&domain_change=true'; + } } echo "\n"; if (permission_exists('user_add') || permission_exists('user_edit') || permission_exists('user_delete')) { @@ -337,3 +341,4 @@ require_once "resources/footer.php"; ?> + From 3adcad3e5e3b197292b22d7eca0ec6f7cc392875 Mon Sep 17 00:00:00 2001 From: chansizzle <14916599+chansizzle@users.noreply.github.com> Date: Thu, 20 Feb 2025 21:28:22 -0700 Subject: [PATCH 107/196] date column before time column (#7266) change the order of the columns --- app/emergency/emergency.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/emergency/emergency.php b/app/emergency/emergency.php index 899abb3f4e..6452043b3c 100644 --- a/app/emergency/emergency.php +++ b/app/emergency/emergency.php @@ -189,8 +189,8 @@ echo "\n"; if (!empty($show) && $show == 'all' && permission_exists('emergency_logs_view_all')) { echo th_order_by('domain_name', $text['label-domain'], $order_by, $order); } -echo "".$text['label-emergency_time']."\n"; echo "".$text['label-emergency_date']."\n"; +echo "".$text['label-emergency_time']."\n"; echo "".$text['label-emergency_extension']."\n"; echo "".$text['label-emergency_event']."\n"; echo "\n"; @@ -202,8 +202,8 @@ if (!empty($emergency_logs) && is_array($emergency_logs) && @sizeof($emergency_l if (!empty($_GET['show']) && $_GET['show'] == 'all' && permission_exists('emergency_logs_view_all')) { echo " ".escape($_SESSION['domains'][$row['domain_uuid']]['domain_name'])."\n"; } - echo " ".escape($row['time_formatted'])."\n"; echo " ".escape($row['date_formatted'])."\n"; + echo " ".escape($row['time_formatted'])."\n"; echo " ".escape($row['extension'])."\n"; echo " ".escape($row['event'])."\n"; echo "\n"; From b85eaaac73f37fdb63e8b3d3dd2f1d1c46d2781d Mon Sep 17 00:00:00 2001 From: fusionate Date: Fri, 21 Feb 2025 08:51:52 -0700 Subject: [PATCH 108/196] Upgrade - Source: Move Preview styles to theme CSS file, style after modal. --- core/upgrade/index.php | 33 ++---------------------------- themes/default/css.php | 46 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 31 deletions(-) diff --git a/core/upgrade/index.php b/core/upgrade/index.php index f9ed6c7c77..eb56ed9fce 100644 --- a/core/upgrade/index.php +++ b/core/upgrade/index.php @@ -221,12 +221,12 @@ } } echo "\n"; - echo "".$text['header-source_code_upgrade_preview']."\n"; + echo "
".$text['header-source_code_upgrade_preview']."
\n"; echo "

\n"; if (!empty($response) && is_array($response)) { echo str_replace('APP_NAME', (!empty($_GET['title']) ? "".$_GET['title']."" : null), $text['description-source_code_changes_found']); echo "


\n"; - echo "
\n"; + echo "
\n"; if (!empty($response) && is_array($response)) { echo implode("
\n
\n", $response); } @@ -254,35 +254,6 @@ require_once "resources/header.php"; //source preview layer - echo "\n"; - echo ""; echo "

"; if ($action == "update") { diff --git a/core/contacts/contact_email_edit.php b/core/contacts/contact_email_edit.php index 1f41f0ba77..f8a1229e67 100644 --- a/core/contacts/contact_email_edit.php +++ b/core/contacts/contact_email_edit.php @@ -239,6 +239,7 @@ if (!empty($_GET["contact_uuid"]) && is_uuid($_GET["contact_uuid"])) { } echo "

\n"; + echo "
\n"; echo "\n"; echo "\n"; @@ -311,6 +312,7 @@ if (!empty($_GET["contact_uuid"]) && is_uuid($_GET["contact_uuid"])) { echo "\n"; echo "
"; + echo "
\n"; echo "

"; echo "\n"; From e08a79e64d538fe2a7e292629efda6761dba7b4e Mon Sep 17 00:00:00 2001 From: Alex <40072887+alexdcrane@users.noreply.github.com> Date: Tue, 25 Feb 2025 12:48:50 -0700 Subject: [PATCH 117/196] Add missing required class to required fields (#7273) * Add missing required class to required fields * Update destination_edit.php * Update device_edit.php * Update voicemail_edit.php * Update dashboard_edit.php * Update call_block_edit.php * Update destination_edit.php --- app/call_block/call_block_edit.php | 4 ++-- app/destinations/destination_edit.php | 4 ++-- app/devices/device_edit.php | 6 +++--- app/voicemails/voicemail_edit.php | 4 ++-- core/dashboard/dashboard_edit.php | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/call_block/call_block_edit.php b/app/call_block/call_block_edit.php index 669a1f6c57..b4e986a149 100644 --- a/app/call_block/call_block_edit.php +++ b/app/call_block/call_block_edit.php @@ -17,7 +17,7 @@ The Initial Developer of the Original Code is Mark J Crane - Portions created by the Initial Developer are Copyright (C) 2008-2024 + Portions created by the Initial Developer are Copyright (C) 2008-2025 the Initial Developer. All Rights Reserved. Contributor(s): @@ -557,7 +557,7 @@ if (permission_exists('call_block_all') || permission_exists('call_block_ring_gr } echo "\n"; - echo "\n"; + echo "\n"; echo " ".$text['label-enabled']."\n"; echo "\n"; echo "\n"; diff --git a/app/destinations/destination_edit.php b/app/destinations/destination_edit.php index bdcae911f5..bd57431454 100644 --- a/app/destinations/destination_edit.php +++ b/app/destinations/destination_edit.php @@ -17,7 +17,7 @@ The Initial Developer of the Original Code is Mark J Crane - Portions created by the Initial Developer are Copyright (C) 2008-2024 + Portions created by the Initial Developer are Copyright (C) 2008-2025 the Initial Developer. All Rights Reserved. Contributor(s): @@ -2097,7 +2097,7 @@ //enabled echo "\n"; - echo "\n"; + echo "\n"; echo " ".$text['label-destination_enabled']."\n"; echo "\n"; echo "\n"; diff --git a/app/devices/device_edit.php b/app/devices/device_edit.php index b8cedfff56..f5567759fe 100644 --- a/app/devices/device_edit.php +++ b/app/devices/device_edit.php @@ -17,7 +17,7 @@ The Initial Developer of the Original Code is Mark J Crane - Portions created by the Initial Developer are Copyright (C) 2008-2024 + Portions created by the Initial Developer are Copyright (C) 2008-2025 the Initial Developer. All Rights Reserved. */ @@ -1101,7 +1101,7 @@ echo "\n"; echo "\n"; - echo "\n"; echo "\n"; - echo "\n"; echo "\n"; - echo "\n"; echo "\n"; echo "\n"; } - + if ($dashboard_chart_type == "icon") { echo "\n"; echo "\n"; echo "\n"; - echo "\n"; echo "
\n"; + echo "\n"; echo " ".$text['label-device_address']."\n"; echo "\n"; @@ -1992,7 +1992,7 @@ if (permission_exists('device_enable')) { echo "
\n"; + echo "\n"; echo " ".$text['label-device_enabled']."\n"; echo "\n"; diff --git a/app/voicemails/voicemail_edit.php b/app/voicemails/voicemail_edit.php index 083c525d59..61637bd4c2 100644 --- a/app/voicemails/voicemail_edit.php +++ b/app/voicemails/voicemail_edit.php @@ -17,7 +17,7 @@ The Initial Developer of the Original Code is Mark J Crane - Portions created by the Initial Developer are Copyright (C) 2008-2024 + Portions created by the Initial Developer are Copyright (C) 2008-2025 the Initial Developer. All Rights Reserved. Contributor(s): @@ -949,7 +949,7 @@ } echo "
\n"; + echo "\n"; echo " ".$text['label-voicemail_enabled']."\n"; echo "\n"; diff --git a/core/dashboard/dashboard_edit.php b/core/dashboard/dashboard_edit.php index 24915a82c3..3ed5dc78aa 100644 --- a/core/dashboard/dashboard_edit.php +++ b/core/dashboard/dashboard_edit.php @@ -18,7 +18,7 @@ The Initial Developer of the Original Code is Mark J Crane - Portions created by the Initial Developer are Copyright (C) 2021-2024 + Portions created by the Initial Developer are Copyright (C) 2021-2025 the Initial Developer. All Rights Reserved. */ @@ -938,7 +938,7 @@ echo "
\n"; @@ -1175,7 +1175,7 @@ echo "
\n"; + echo "\n"; echo " ".$text['label-dashboard_enabled']."\n"; echo "\n"; From c22080d2fc3d5a7cb268ce2d01d29bd793ec8936 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Tue, 25 Feb 2025 13:09:49 -0700 Subject: [PATCH 118/196] Fix an unclosed {if} tag Caused by Commit 40f78c3 --- resources/templates/provision/grandstream/dp750/{$mac}.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/templates/provision/grandstream/dp750/{$mac}.xml b/resources/templates/provision/grandstream/dp750/{$mac}.xml index fdf95542fd..d9dcc91f9b 100644 --- a/resources/templates/provision/grandstream/dp750/{$mac}.xml +++ b/resources/templates/provision/grandstream/dp750/{$mac}.xml @@ -3095,6 +3095,7 @@ {elseif $grandstream_automatic_provisioning == 3} 2 {/if} +{/if} From 2f955d4fef155d1f77805ba46cfb9b4771d10d6e Mon Sep 17 00:00:00 2001 From: Alex <40072887+alexdcrane@users.noreply.github.com> Date: Tue, 25 Feb 2025 13:23:06 -0700 Subject: [PATCH 119/196] Fix queue edit content alignment (#7274) --- app/fifo/fifo_edit.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/fifo/fifo_edit.php b/app/fifo/fifo_edit.php index cb2937581f..e247ab121b 100644 --- a/app/fifo/fifo_edit.php +++ b/app/fifo/fifo_edit.php @@ -511,7 +511,7 @@ echo "\n"; echo "\n"; - echo "\n"; echo "\n"; @@ -310,6 +311,7 @@ //echo " \n"; //echo " \n"; //echo " \n"; + echo " \n"; if (permission_exists('user_edit')) { echo " \n"; } echo "\n"; - if (is_array($users) && @sizeof($users) != 0) { $x = 0; foreach ($users as $row) { @@ -303,10 +284,8 @@ } echo " \n"; echo " \n"; - if ($show_contact_fields) { - echo " \n"; - echo " \n"; - } + echo " \n"; + echo " \n"; //echo " \n"; //echo " \n"; //echo " \n"; From f3986290eaf3e3b65b792da803e21ff4969c0113 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Thu, 27 Feb 2025 10:48:29 -0700 Subject: [PATCH 126/196] Add enable-rfc-5626 to the internal profile --- app/switch/resources/conf/sip_profiles/internal-ipv6.xml.noload | 2 ++ app/switch/resources/conf/sip_profiles/internal.xml.noload | 2 ++ 2 files changed, 4 insertions(+) diff --git a/app/switch/resources/conf/sip_profiles/internal-ipv6.xml.noload b/app/switch/resources/conf/sip_profiles/internal-ipv6.xml.noload index 2c376ce0d0..f7bf02d931 100644 --- a/app/switch/resources/conf/sip_profiles/internal-ipv6.xml.noload +++ b/app/switch/resources/conf/sip_profiles/internal-ipv6.xml.noload @@ -11,6 +11,8 @@ + + diff --git a/app/switch/resources/conf/sip_profiles/internal.xml.noload b/app/switch/resources/conf/sip_profiles/internal.xml.noload index 872de9f47c..951af3f741 100644 --- a/app/switch/resources/conf/sip_profiles/internal.xml.noload +++ b/app/switch/resources/conf/sip_profiles/internal.xml.noload @@ -83,6 +83,8 @@ + + From 863de97270ae156daf7b59d724070f6726ec6ae5 Mon Sep 17 00:00:00 2001 From: frytimo Date: Thu, 27 Feb 2025 22:47:27 -0400 Subject: [PATCH 127/196] Update grandstream template loop (#7281) --- resources/templates/provision/grandstream/grp2612/{$mac}.xml | 2 +- resources/templates/provision/grandstream/grp2612w/{$mac}.xml | 2 +- resources/templates/provision/grandstream/grp2613/{$mac}.xml | 2 +- resources/templates/provision/grandstream/grp2614/{$mac}.xml | 2 +- resources/templates/provision/grandstream/grp2615/{$mac}.xml | 2 +- resources/templates/provision/grandstream/grp2616/{$mac}.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/resources/templates/provision/grandstream/grp2612/{$mac}.xml b/resources/templates/provision/grandstream/grp2612/{$mac}.xml index d6d6634ac2..ba1ea01ede 100644 --- a/resources/templates/provision/grandstream/grp2612/{$mac}.xml +++ b/resources/templates/provision/grandstream/grp2612/{$mac}.xml @@ -4565,7 +4565,7 @@ - + {$row.device_key_value} {/foreach} diff --git a/resources/templates/provision/grandstream/grp2612w/{$mac}.xml b/resources/templates/provision/grandstream/grp2612w/{$mac}.xml index 423013911b..7a6765af35 100644 --- a/resources/templates/provision/grandstream/grp2612w/{$mac}.xml +++ b/resources/templates/provision/grandstream/grp2612w/{$mac}.xml @@ -4560,7 +4560,7 @@ - + {$row.device_key_value} {/foreach} diff --git a/resources/templates/provision/grandstream/grp2613/{$mac}.xml b/resources/templates/provision/grandstream/grp2613/{$mac}.xml index 8fe7f212a0..ab148d963c 100644 --- a/resources/templates/provision/grandstream/grp2613/{$mac}.xml +++ b/resources/templates/provision/grandstream/grp2613/{$mac}.xml @@ -4566,7 +4566,7 @@ - + {$row.device_key_value} {/foreach} diff --git a/resources/templates/provision/grandstream/grp2614/{$mac}.xml b/resources/templates/provision/grandstream/grp2614/{$mac}.xml index d6d6634ac2..ba1ea01ede 100644 --- a/resources/templates/provision/grandstream/grp2614/{$mac}.xml +++ b/resources/templates/provision/grandstream/grp2614/{$mac}.xml @@ -4565,7 +4565,7 @@ - + {$row.device_key_value} {/foreach} diff --git a/resources/templates/provision/grandstream/grp2615/{$mac}.xml b/resources/templates/provision/grandstream/grp2615/{$mac}.xml index 01b07777d0..5311dec42e 100644 --- a/resources/templates/provision/grandstream/grp2615/{$mac}.xml +++ b/resources/templates/provision/grandstream/grp2615/{$mac}.xml @@ -4558,7 +4558,7 @@ - + {$row.device_key_value} {/foreach} diff --git a/resources/templates/provision/grandstream/grp2616/{$mac}.xml b/resources/templates/provision/grandstream/grp2616/{$mac}.xml index d6d6634ac2..ba1ea01ede 100644 --- a/resources/templates/provision/grandstream/grp2616/{$mac}.xml +++ b/resources/templates/provision/grandstream/grp2616/{$mac}.xml @@ -4565,7 +4565,7 @@ - + {$row.device_key_value} {/foreach} From f8e1e815460bc58c502e76cd6ae79f658a92ef22 Mon Sep 17 00:00:00 2001 From: frytimo Date: Fri, 28 Feb 2025 00:09:31 -0400 Subject: [PATCH 128/196] fix wrong logical check (#7282) Forgot to remove the '!' (not) operator from the cache check when re-organizing the update cache function --- resources/classes/auto_loader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/classes/auto_loader.php b/resources/classes/auto_loader.php index 63042eb2d7..1b5ed65549 100644 --- a/resources/classes/auto_loader.php +++ b/resources/classes/auto_loader.php @@ -55,7 +55,7 @@ class auto_loader { public function update_cache(string $file = ''): bool { //guard against writing an empty file - if (!empty($this->classes)) { + if (empty($this->classes)) { return false; } From c1296f26e0840c4321605082378e9d793899c09c Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Thu, 27 Feb 2025 23:16:42 -0700 Subject: [PATCH 129/196] Update users.php --- core/users/users.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/users/users.php b/core/users/users.php index 7f0890e625..fa6e34b052 100644 --- a/core/users/users.php +++ b/core/users/users.php @@ -52,7 +52,7 @@ $users = $_POST['users'] ?? ''; } -S//process the http post data by action +//process the http post data by action if (!empty($action) && is_array($users) && @sizeof($users) != 0) { switch ($action) { case 'copy': @@ -321,4 +321,4 @@ S//process the http post data by action //include the footer require_once "resources/footer.php"; -?> \ No newline at end of file +?> From 3de202b987d243b133455b1b278db8352706ff67 Mon Sep 17 00:00:00 2001 From: fusionate Date: Fri, 28 Feb 2025 09:36:42 -0700 Subject: [PATCH 130/196] Contact - Attachment: Store image files in same format as uploaded. --- core/contacts/contact_attachment_edit.php | 46 ++++++++++++++--------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/core/contacts/contact_attachment_edit.php b/core/contacts/contact_attachment_edit.php index 23642505a0..62b05e1d08 100644 --- a/core/contacts/contact_attachment_edit.php +++ b/core/contacts/contact_attachment_edit.php @@ -70,15 +70,15 @@ //get the attachment type if (empty($attachment) || sizeof($attachment) == 0) { - $attachment_type = strtolower(pathinfo($_POST['attachment_filename'], PATHINFO_EXTENSION)); + $attachment_extension = strtolower(pathinfo($_POST['attachment_filename'], PATHINFO_EXTENSION)); } else { - $attachment_type = strtolower(pathinfo($attachment['name'], PATHINFO_EXTENSION)); + $attachment_extension = strtolower(pathinfo($attachment['name'], PATHINFO_EXTENSION)); } //unflag others as primary $allowed_primary_attachment = false; - if ($attachment_primary && ($attachment_type == 'jpg' || $attachment_type == 'jpeg' || $attachment_type == 'gif' || $attachment_type == 'png')) { + if ($attachment_primary && ($attachment_extension == 'jpg' || $attachment_extension == 'jpeg' || $attachment_extension == 'gif' || $attachment_extension == 'png')) { $sql = "update v_contact_attachments set attachment_primary = 0 "; $sql .= "where domain_uuid = :domain_uuid "; $sql .= "and contact_uuid = :contact_uuid "; @@ -94,29 +94,41 @@ //get the allowed extensions $allowed_extensions = array_keys(json_decode($_SESSION['contact']['allowed_attachment_types']['text'], true)); - //get the attachment extension - $attachment_extension = strtolower(pathinfo($attachment['name'], PATHINFO_EXTENSION)); - //check the allowed extensions if ($attachment['error'] == '0' && in_array($attachment_extension, $allowed_extensions)) { //get the attachment content $attachment_content = file_get_contents($attachment['tmp_name']); - //list of image extensions - $image_extensions = array('png','jpg','jpeg','gif','bmp', 'webp'); - //read the image from the string then output the image without meta data - if (in_array($attachment_extension, $image_extensions)) { + if (in_array($attachment_extension, ['png','jpg','jpeg','gif','bmp', 'webp'])) { //create the image object from the content string $image = imagecreatefromstring($attachment_content); - imagealphablending($image, FALSE); - imagesavealpha($image, TRUE); //start output buffering to capture the image data ob_start(); //output the image without the EXIF data - imagepng($image); + switch ($attachment_extension) { + case 'png': + imagealphablending($image, FALSE); + imagesavealpha($image, TRUE); + imagepng($image); + break; + case 'jpg': + case 'jpeg': + imagejpeg($image); + break; + case 'gif': + imagesavealpha($image, TRUE); + imagegif($image); + break; + case 'bmp': + imagebmp($image); + break; + case 'webp': + imagewebp($image); + break; + } //get the image from the buffer $attachment_content = ob_get_contents(); @@ -215,11 +227,11 @@ echo " ".$text['label-attachment']."\n"; echo "\n"; echo "\n"; echo "\n"; - if ($action == 'update' && ($attachment_type == 'jpg' || $attachment_type == 'jpeg' || $attachment_type == 'gif' || $attachment_type == 'png')) { + if ($action == 'update' && ($attachment_extension == 'jpg' || $attachment_extension == 'jpeg' || $attachment_extension == 'gif' || $attachment_extension == 'png')) { echo "\n"; echo "
\n"; + echo "\n"; echo " ".$text['label-fifo_name']."\n"; echo "\n"; @@ -789,4 +789,4 @@ //include the footer require_once "resources/footer.php"; -?> \ No newline at end of file +?> From 305f585b17ec53d7e56dbff43f9be7d6d97c4eb8 Mon Sep 17 00:00:00 2001 From: Alex <40072887+alexdcrane@users.noreply.github.com> Date: Tue, 25 Feb 2025 16:24:16 -0700 Subject: [PATCH 120/196] Add missing counter divs (#7277) * Add counter div to voicemail messages and domain settings * Update domain_settings.php * Update menu_item_list.php * Update domain_settings.php * Update voicemail_messages.php --- app/voicemails/voicemail_messages.php | 4 ++-- core/domain_settings/domain_settings.php | 4 ++-- core/menu/menu_item_list.php | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/voicemails/voicemail_messages.php b/app/voicemails/voicemail_messages.php index 24290edc9b..39d815fa5b 100644 --- a/app/voicemails/voicemail_messages.php +++ b/app/voicemails/voicemail_messages.php @@ -17,7 +17,7 @@ The Initial Developer of the Original Code is Mark J Crane - Portions created by the Initial Developer are Copyright (C) 2008-2024 + Portions created by the Initial Developer are Copyright (C) 2008-2025 the Initial Developer. All Rights Reserved. Contributor(s): @@ -322,7 +322,7 @@ //show the content echo "
\n"; - echo "
".$text['title-voicemail_messages']." (".$total_rows.")
\n"; + echo "
".$text['title-voicemail_messages']."
".number_format($total_rows)."
\n"; echo "
\n"; echo button::create(['type'=>'button','label'=>$text['button-back'],'icon'=>$_SESSION['theme']['button_icon_back'],'id'=>'btn_back','link'=>$_SESSION['back'][$_SERVER['PHP_SELF']]]); $margin_left = false; diff --git a/core/domain_settings/domain_settings.php b/core/domain_settings/domain_settings.php index 0f3df5c5ec..60d9d01245 100644 --- a/core/domain_settings/domain_settings.php +++ b/core/domain_settings/domain_settings.php @@ -17,7 +17,7 @@ The Initial Developer of the Original Code is Mark J Crane - Portions created by the Initial Developer are Copyright (C) 2008 - 2023 + Portions created by the Initial Developer are Copyright (C) 2008-2025 the Initial Developer. All Rights Reserved. Contributor(s): @@ -161,7 +161,7 @@ //show the content echo "
\n"; - echo "
".$domain_name." (".$num_rows.")
\n"; //$text['title-domain_settings'] + echo "
".$domain_name."
".number_format($num_rows)."
\n"; //$text['title-domain_settings'] echo "
\n"; echo button::create(['type'=>'button','label'=>$text['button-back'],'icon'=>$_SESSION['theme']['button_icon_back'],'id'=>'action_bar_sub_button_back','style'=>'','link'=>PROJECT_PATH.'/core/domains/domains.php']); if (permission_exists('default_setting_view') && $num_rows) { diff --git a/core/menu/menu_item_list.php b/core/menu/menu_item_list.php index 1b3a596e89..282fe7e9bf 100644 --- a/core/menu/menu_item_list.php +++ b/core/menu/menu_item_list.php @@ -17,7 +17,7 @@ The Initial Developer of the Original Code is Mark J Crane - Portions created by the Initial Developer are Copyright (C) 2008-2024 + Portions created by the Initial Developer are Copyright (C) 2008-2025 the Initial Developer. All Rights Reserved. Contributor(s): @@ -240,7 +240,7 @@ echo "\n"; echo "
\n"; - echo "
".$text['header-menu_items']." ()
\n"; + echo "
".$text['header-menu_items']."
\n"; echo "
\n"; echo button::create(['type'=>'button','id'=>'action_bar_sub_button_back','label'=>$text['button-back'],'icon'=>$_SESSION['theme']['button_icon_back'],'collapse'=>'hide-xs','style'=>'margin-right: 15px; display: none;','link'=>'menu.php']); if (permission_exists('menu_item_add')) { From d919a3cc1b9711063f3341c8dd797d8f734db4af Mon Sep 17 00:00:00 2001 From: frytimo Date: Tue, 25 Feb 2025 20:21:41 -0400 Subject: [PATCH 121/196] Add the apcu caching ability for performance (#7276) * add the apcu caching ability for performance When the PHP extension APCu is loaded, the settings class and the auto_loader will cache their results across requests in RAM. For more information about the APCu extension visit the PHP page: https://www.php.net/apcu * use global instead of default terminology --- app/sip_status/sip_status.php | 1 - .../default_settings_reload.php | 2 +- core/domain_settings/domain_setting_edit.php | 3 + core/user_settings/user_setting_edit.php | 3 + resources/classes/auto_loader.php | 73 ++++++++--- resources/classes/cache.php | 11 ++ resources/classes/settings.php | 115 +++++++++++++++--- 7 files changed, 171 insertions(+), 37 deletions(-) diff --git a/app/sip_status/sip_status.php b/app/sip_status/sip_status.php index 5dfb85360e..364023a108 100644 --- a/app/sip_status/sip_status.php +++ b/app/sip_status/sip_status.php @@ -331,4 +331,3 @@ require_once "resources/footer.php"; ?> - diff --git a/core/default_settings/default_settings_reload.php b/core/default_settings/default_settings_reload.php index 1400e7b976..916d51add7 100644 --- a/core/default_settings/default_settings_reload.php +++ b/core/default_settings/default_settings_reload.php @@ -46,7 +46,7 @@ $search = $_REQUEST['search'] ?? ''; $domain_uuid = $_GET['id'] ?? null; //reload default settings -require "resources/classes/domains.php"; +settings::clear_cache(); $domain = new domains(); $domain->set(); diff --git a/core/domain_settings/domain_setting_edit.php b/core/domain_settings/domain_setting_edit.php index 80b8395569..e9294fd58a 100644 --- a/core/domain_settings/domain_setting_edit.php +++ b/core/domain_settings/domain_setting_edit.php @@ -307,6 +307,9 @@ } } + //clear domain apcu cache due to changes + settings::clear_cache('domain'); + //redirect the browser if ($action == "update") { message::add($text['message-update']); diff --git a/core/user_settings/user_setting_edit.php b/core/user_settings/user_setting_edit.php index b480be6f05..3e0ec3fc2f 100644 --- a/core/user_settings/user_setting_edit.php +++ b/core/user_settings/user_setting_edit.php @@ -298,6 +298,9 @@ if (!empty($_POST) && empty($_POST["persistformvar"])) { } } + //clear the user settings cache + settings::clear_cache('user'); + //redirect the browser if ($action == "update") { message::add($text['message-update']); diff --git a/resources/classes/auto_loader.php b/resources/classes/auto_loader.php index 85dbcdb261..63042eb2d7 100644 --- a/resources/classes/auto_loader.php +++ b/resources/classes/auto_loader.php @@ -27,10 +27,21 @@ class auto_loader { const FILE = 'autoloader_cache.php'; + const CACHE_KEY = 'autoloader_classes'; private $classes; + /** + * Tracks the APCu extension for caching to RAM drive across requests + * @var bool + */ + private $apcu_enabled; + public function __construct($project_path = '') { + + //set if we can use RAM cache + $this->apcu_enabled = function_exists('apcu_enabled') && apcu_enabled(); + //classes must be loaded before this object is registered if (!$this->load_cache()) { //cache miss so load them @@ -43,34 +54,49 @@ class auto_loader { } public function update_cache(string $file = ''): bool { + //guard against writing an empty file + if (!empty($this->classes)) { + return false; + } + + //update RAM cache when available + if ($this->apcu_enabled) { + apcu_store(self::CACHE_KEY, $this->classes); + } + //ensure we have somewhere to put the file if (empty($file)) { $file = sys_get_temp_dir() . '/' . self::FILE; } - //guard against writing an empty file - if (!empty($this->classes)) { - //export the classes array using PHP engine - $data = var_export($this->classes, true); + //export the classes array using PHP engine + $data = var_export($this->classes, true); - //put the array in a form that it can be loaded directly to an array - $result = file_put_contents($file, "classes = []; + + //use apcu when available + if ($this->apcu_enabled && apcu_exists(self::CACHE_KEY)) { + $this->classes = apcu_fetch(self::CACHE_KEY, $success); + if ($success) return true; + } + //use a standard file if (empty($file)) { $file = sys_get_temp_dir() . '/'. self::FILE; @@ -81,6 +107,10 @@ class auto_loader { } //assign to an array if (!empty($this->classes)) { + //cache edge case of first time using apcu cache + if ($this->apcu_enabled) { + apcu_store(self::CACHE_KEY, $this->classes); + } return true; } return false; @@ -125,6 +155,11 @@ class auto_loader { return true; } + //Smarty has it's own autoloader so reject the request + if ($class_name === 'Smarty_Autoloader') { + return false; + } + //cache miss if (!empty($_REQUEST['debug']) && $_REQUEST['debug'] == 'true') { openlog("PHP", LOG_PID | LOG_PERROR, LOG_LOCAL0); @@ -186,4 +221,10 @@ class auto_loader { } return ''; } + + public static function clear_cache() { + if (function_exists('apcu_enabled') && apcu_enabled()) { + apcu_delete(self::CACHE_KEY); + } + } } diff --git a/resources/classes/cache.php b/resources/classes/cache.php index 557d2cda63..f0ef9056ee 100644 --- a/resources/classes/cache.php +++ b/resources/classes/cache.php @@ -187,6 +187,17 @@ class cache { closelog(); } + //check for apcu extension + if (function_exists('apcu_enabled') && apcu_enabled()) { + //flush everything + apcu_clear_cache(); + } + + //remove the autoloader file cache + if (file_exists(sys_get_temp_dir() . '/' . auto_loader::FILE)) { + @unlink(sys_get_temp_dir() . '/' . auto_loader::FILE); + } + //cache method memcache if ($this->method === "memcache") { // connect to event socket diff --git a/resources/classes/settings.php b/resources/classes/settings.php index b2a85e024a..3a9a21c452 100644 --- a/resources/classes/settings.php +++ b/resources/classes/settings.php @@ -53,6 +53,12 @@ class settings { */ private $database; + /** + * Tracks if the APCu extension is loaded for database queries + * @var bool + */ + private $apcu_enabled; + /** * Create a settings object using key/value pairs in the $setting_array. * @@ -63,6 +69,16 @@ class settings { */ public function __construct($setting_array = []) { + //try to use RAM cache by default + if (!isset($setting_array['allow_caching'])) { + $setting_array['allow_caching'] = true; + } + + //track ram caching + if ($setting_array['allow_caching']) { + $this->apcu_enabled = function_exists('apcu_enabled') && apcu_enabled(); + } + //open a database connection if (empty($setting_array['database'])) { $this->database = database::new(); @@ -155,7 +171,7 @@ class settings { * @param bool $enabled (optional) True or False. Default is True. * @param string $description (optional) Description. Default is empty string. */ - public function set(string $table_prefix, string $uuid, string $category, string $subcategory, string $type = 'text', string $value = "", bool $enabled = true, string $description = "") { + public function set(string $table_prefix, string $uuid, string $category, string $subcategory, string $value = "", string $type = 'text', bool $enabled = true, string $description = "") { //set the table name $table_name = $table_prefix.'_settings'; @@ -207,6 +223,15 @@ class settings { */ private function default_settings() { + //set the key for global defaults + $key = 'settings_global_' . $this->category; + + //if the apcu extension is loaded get the already parsed array + if ($this->apcu_enabled && apcu_exists($key)) { + $this->settings = apcu_fetch($key); + return; + } + //get the default settings $sql = "select * from v_default_settings "; $sql .= "where default_setting_enabled = 'true' "; @@ -247,7 +272,11 @@ class settings { } } } - unset($sql, $result, $row); + + //if the apcu extension is loaded store the result + if ($this->apcu_enabled) { + apcu_store($key, $this->settings); + } } /** @@ -255,13 +284,22 @@ class settings { * @access private */ private function domain_settings() { - - $sql = "select * from v_domain_settings "; - $sql .= "where domain_uuid = :domain_uuid "; - $sql .= "and domain_setting_enabled = 'true' "; - $parameters['domain_uuid'] = $this->domain_uuid; - $result = $this->database->select($sql, $parameters, 'all'); - unset($sql, $parameters); + $key = 'settings_domain_'.$this->domain_uuid; + $result = ''; + //if the apcu extension is loaded get the cached database result + if ($this->apcu_enabled && apcu_exists($key)) { + $result = apcu_fetch($key); + } else { + $sql = "select * from v_domain_settings "; + $sql .= "where domain_uuid = :domain_uuid "; + $sql .= "and domain_setting_enabled = 'true' "; + $parameters['domain_uuid'] = $this->domain_uuid; + $result = $this->database->select($sql, $parameters, 'all'); + //if the apcu extension is loaded store the result + if ($this->apcu_enabled) { + apcu_store($key, $result); + } + } if (!empty($result)) { //domain setting array types override the default settings set as type array foreach ($result as $row) { @@ -305,7 +343,6 @@ class settings { } } - unset($result, $row); } /** @@ -314,15 +351,25 @@ class settings { * @depends $this->domain_uuid */ private function user_settings() { - - $sql = "select * from v_user_settings "; - $sql .= "where domain_uuid = :domain_uuid "; - $sql .= "and user_uuid = :user_uuid "; - $sql .= " order by user_setting_order asc "; - $parameters['domain_uuid'] = $this->domain_uuid; - $parameters['user_uuid'] = $this->user_uuid; - $result = $this->database->select($sql, $parameters, 'all'); - if (is_array($result)) { + $key = 'settings_user_'.$this->user_uuid; + $result = ''; + //if the apcu extension is loaded get the cached database result + if ($this->apcu_enabled && apcu_exists($key)) { + $result = apcu_fetch($key); + } else { + $sql = "select * from v_user_settings "; + $sql .= "where domain_uuid = :domain_uuid "; + $sql .= "and user_uuid = :user_uuid "; + $sql .= " order by user_setting_order asc "; + $parameters['domain_uuid'] = $this->domain_uuid; + $parameters['user_uuid'] = $this->user_uuid; + $result = $this->database->select($sql, $parameters, 'all'); + //if the apcu extension is loaded store the result + if ($this->apcu_enabled) { + apcu_store($key, $result); + } + } + if (!empty($result)) { foreach ($result as $row) { if ($row['user_setting_enabled'] == 'true') { $name = $row['user_setting_name']; @@ -406,4 +453,34 @@ class settings { } } } + + /** + * Clears the settings cache + * @param string $type Empty clears all settings. Values can be global, domain, or user. + */ + public static function clear_cache(string $type = '') { + if (function_exists('apcu_enabled') && apcu_enabled()) { + switch ($type) { + case 'all': + case '': + default: + $type = ""; + break; + case 'global': + case 'domain': + case 'user': + $type .= "_"; + break; + } + $cache = apcu_cache_info(false); + if (!empty($cache['cache_list'])) { + foreach ($cache['cache_list'] as $entry) { + $key = $entry['info']; + if (str_starts_with($key, 'settings_' . $type)) { + apcu_delete($key); + } + } + } + } + } } From bd54c07e50e60691f9437ef77daac5f0e0b2ed26 Mon Sep 17 00:00:00 2001 From: markjcrane Date: Wed, 26 Feb 2025 10:29:45 -0700 Subject: [PATCH 122/196] Move email_templates to core --- {app => core}/email_templates/app_config.php | 0 {app => core}/email_templates/app_defaults.php | 0 {app => core}/email_templates/app_languages.php | 0 {app => core}/email_templates/app_menu.php | 0 .../email_templates/email_template_edit.php | 0 {app => core}/email_templates/email_templates.php | 0 .../resources/classes/email_templates.php | 0 .../email_templates/resources/images/icon_file.png | Bin .../resources/images/icon_folder.png | Bin .../email_templates/resources/images/icon_gear.png | Bin 10 files changed, 0 insertions(+), 0 deletions(-) rename {app => core}/email_templates/app_config.php (100%) rename {app => core}/email_templates/app_defaults.php (100%) rename {app => core}/email_templates/app_languages.php (100%) rename {app => core}/email_templates/app_menu.php (100%) rename {app => core}/email_templates/email_template_edit.php (100%) rename {app => core}/email_templates/email_templates.php (100%) rename {app => core}/email_templates/resources/classes/email_templates.php (100%) rename {app => core}/email_templates/resources/images/icon_file.png (100%) rename {app => core}/email_templates/resources/images/icon_folder.png (100%) rename {app => core}/email_templates/resources/images/icon_gear.png (100%) diff --git a/app/email_templates/app_config.php b/core/email_templates/app_config.php similarity index 100% rename from app/email_templates/app_config.php rename to core/email_templates/app_config.php diff --git a/app/email_templates/app_defaults.php b/core/email_templates/app_defaults.php similarity index 100% rename from app/email_templates/app_defaults.php rename to core/email_templates/app_defaults.php diff --git a/app/email_templates/app_languages.php b/core/email_templates/app_languages.php similarity index 100% rename from app/email_templates/app_languages.php rename to core/email_templates/app_languages.php diff --git a/app/email_templates/app_menu.php b/core/email_templates/app_menu.php similarity index 100% rename from app/email_templates/app_menu.php rename to core/email_templates/app_menu.php diff --git a/app/email_templates/email_template_edit.php b/core/email_templates/email_template_edit.php similarity index 100% rename from app/email_templates/email_template_edit.php rename to core/email_templates/email_template_edit.php diff --git a/app/email_templates/email_templates.php b/core/email_templates/email_templates.php similarity index 100% rename from app/email_templates/email_templates.php rename to core/email_templates/email_templates.php diff --git a/app/email_templates/resources/classes/email_templates.php b/core/email_templates/resources/classes/email_templates.php similarity index 100% rename from app/email_templates/resources/classes/email_templates.php rename to core/email_templates/resources/classes/email_templates.php diff --git a/app/email_templates/resources/images/icon_file.png b/core/email_templates/resources/images/icon_file.png similarity index 100% rename from app/email_templates/resources/images/icon_file.png rename to core/email_templates/resources/images/icon_file.png diff --git a/app/email_templates/resources/images/icon_folder.png b/core/email_templates/resources/images/icon_folder.png similarity index 100% rename from app/email_templates/resources/images/icon_folder.png rename to core/email_templates/resources/images/icon_folder.png diff --git a/app/email_templates/resources/images/icon_gear.png b/core/email_templates/resources/images/icon_gear.png similarity index 100% rename from app/email_templates/resources/images/icon_gear.png rename to core/email_templates/resources/images/icon_gear.png From 9591ce0cbd4da12ba16f9bc02867f02046a0596e Mon Sep 17 00:00:00 2001 From: markjcrane Date: Wed, 26 Feb 2025 10:30:39 -0700 Subject: [PATCH 123/196] Change the path in the menu to use core --- core/email_templates/app_menu.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/email_templates/app_menu.php b/core/email_templates/app_menu.php index 570bc8ee4d..62078d1092 100644 --- a/core/email_templates/app_menu.php +++ b/core/email_templates/app_menu.php @@ -29,7 +29,7 @@ $apps[$x]['menu'][$y]['parent_uuid'] = "594d99c5-6128-9c88-ca35-4b33392cec0f"; $apps[$x]['menu'][$y]['category'] = "internal"; $apps[$x]['menu'][$y]['icon'] = ""; - $apps[$x]['menu'][$y]['path'] = "/app/email_templates/email_templates.php"; + $apps[$x]['menu'][$y]['path'] = "/core/email_templates/email_templates.php"; $apps[$x]['menu'][$y]['order'] = ""; $apps[$x]['menu'][$y]['groups'][] = "superadmin"; $y++; From 1fba94d92b210cdcf70f0fbdf13ba8f3546f954d Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Wed, 26 Feb 2025 12:01:20 -0700 Subject: [PATCH 124/196] Add contact note to users --- core/users/app_defaults.php | 2 +- core/users/app_languages.php | 28 +++++++++++++++++++++++++++- core/users/users.php | 9 +++++---- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/core/users/app_defaults.php b/core/users/app_defaults.php index 75c00a25c1..66968669be 100644 --- a/core/users/app_defaults.php +++ b/core/users/app_defaults.php @@ -35,7 +35,7 @@ if ($domains_processed == 1) { $sql = "CREATE VIEW view_users AS ( \n"; $sql .= " select u.domain_uuid, u.user_uuid, d.domain_name, u.username, u.user_status, u.user_enabled, u.add_date, \n"; - $sql .= " c.contact_uuid, c.contact_organization, c.contact_name_given ||' '|| c.contact_name_family as contact_name, c.contact_name_given, c.contact_name_family, \n"; + $sql .= " c.contact_uuid, c.contact_organization, c.contact_name_given ||' '|| c.contact_name_family as contact_name, c.contact_name_given, c.contact_name_family, c.contact_note, \n"; $sql .= " ( \n"; $sql .= " select \n"; $sql .= " string_agg(g.group_name, ', ') \n"; diff --git a/core/users/app_languages.php b/core/users/app_languages.php index ca0ff692f9..27cdb13300 100644 --- a/core/users/app_languages.php +++ b/core/users/app_languages.php @@ -1975,6 +1975,32 @@ $text['label-user_enabled']['zh-cn'] = "启用"; $text['label-user_enabled']['ja-jp'] = "有効"; $text['label-user_enabled']['ko-kr'] = "사용"; +$text['label-contact_note']['en-us'] = "Note"; +$text['label-contact_note']['en-gb'] = "Note"; +$text['label-contact_note']['ar-eg'] = "ملحوظة"; +$text['label-contact_note']['de-at'] = "Notiz"; +$text['label-contact_note']['de-ch'] = "Notiz"; +$text['label-contact_note']['de-de'] = "Notiz"; +$text['label-contact_note']['el-gr'] = "Σημείωση"; +$text['label-contact_note']['es-cl'] = "Nota"; +$text['label-contact_note']['es-mx'] = "Nota"; +$text['label-contact_note']['fr-ca'] = "Note"; +$text['label-contact_note']['fr-fr'] = "Note"; +$text['label-contact_note']['he-il'] = "הערה"; +$text['label-contact_note']['it-it'] = "Nota"; +$text['label-contact_note']['ka-ge'] = "შენიშვნა"; +$text['label-contact_note']['nl-nl'] = "Notitie"; +$text['label-contact_note']['pl-pl'] = "Notatka"; +$text['label-contact_note']['pt-br'] = "Nota"; +$text['label-contact_note']['pt-pt'] = "Nota"; +$text['label-contact_note']['ro-ro'] = "Notă"; +$text['label-contact_note']['ru-ru'] = "Примечание"; +$text['label-contact_note']['sv-se'] = "Notering"; +$text['label-contact_note']['uk-ua'] = "Нотатка"; +$text['label-contact_note']['zh-cn'] = "笔记"; +$text['label-contact_note']['ja-jp'] = "ノート"; +$text['label-contact_note']['ko-kr'] = "메모"; + $text['label-additional_info']['en-us'] = "Additional Info"; $text['label-additional_info']['en-gb'] = "Additional Info"; $text['label-additional_info']['ar-eg'] = "معلومات إضافية"; @@ -2866,4 +2892,4 @@ $text['button-permissions']['zh-cn'] = "权限"; $text['button-permissions']['ja-jp'] = "パーミッション"; $text['button-permissions']['ko-kr'] = "권한"; -?> +?> \ No newline at end of file diff --git a/core/users/users.php b/core/users/users.php index 304f6a3d32..d787de164d 100644 --- a/core/users/users.php +++ b/core/users/users.php @@ -113,7 +113,7 @@ $sql_search .= " or lower(group_names) like :search "; $sql_search .= " or lower(contact_organization) like :search "; $sql_search .= " or lower(contact_name) like :search "; - //$sql_search .= " or lower(user_status) like :search "; + $sql_search .= " or lower(contact_note) like :search "; $sql_search .= ") "; $parameters['search'] = '%'.$search.'%'; } @@ -154,7 +154,7 @@ //get the list $sql = "select domain_name, domain_uuid, user_uuid, username, group_names, "; if ($show_contact_fields) { - $sql .= "contact_organization,contact_name, "; + $sql .= "contact_organization,contact_name,contact_note, "; } $sql .= "cast(user_enabled as text) "; $sql .= "from view_users "; @@ -267,6 +267,7 @@ //echo th_order_by('contact_name_family', $text['label-contact_name_family'], $order_by, $order); //echo th_order_by('user_status', $text['label-user_status'], $order_by, $order); //echo th_order_by('add_date', $text['label-add_date'], $order_by, $order); + echo th_order_by('contact_note', $text['label-contact_note'], $order_by, $order, null, "class='center'", $param); echo th_order_by('user_enabled', $text['label-user_enabled'], $order_by, $order, null, "class='center'", $param); if (permission_exists('user_edit') && $list_row_edit_button == 'true') { echo "
 ".escape($row['contact_name_family'])."".escape($row['user_status'])."".escape($row['add_date'])."".escape($row['contact_note'])." 
".escape($row['group_names'])."".escape($row['contact_organization'])."".escape($row['contact_name'])."".escape($row['contact_organization'])."".escape($row['contact_name'])."".escape($row['contact_name_given'])."".escape($row['contact_name_family'])."".escape($row['user_status'])."\n"; - $attachment_type = strtolower(pathinfo($attachment_filename ?? '', PATHINFO_EXTENSION)); + $attachment_extension = strtolower(pathinfo($attachment_filename ?? '', PATHINFO_EXTENSION)); if ($action == 'update') { echo "\n"; - if ($attachment_type == 'jpg' || $attachment_type == 'jpeg' || $attachment_type == 'gif' || $attachment_type == 'png') { - echo ""; + if ($attachment_extension == 'jpg' || $attachment_extension == 'jpeg' || $attachment_extension == 'gif' || $attachment_extension == 'png') { + echo ""; } else { echo "".$attachment_filename.""; @@ -233,7 +245,7 @@ echo "
\n"; echo " ".$text['label-attachment_filename']."\n"; From f6df4fd0b3c4d85bde70189bd408e7a34009f0a9 Mon Sep 17 00:00:00 2001 From: fusionate Date: Fri, 28 Feb 2025 11:03:05 -0700 Subject: [PATCH 131/196] Contacts - List: Only retrieve a single Primary attachment, in the chance that multiple exist. --- core/contacts/contacts.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/contacts/contacts.php b/core/contacts/contacts.php index abdbdbfe2f..5e5722524b 100644 --- a/core/contacts/contacts.php +++ b/core/contacts/contacts.php @@ -245,7 +245,7 @@ //get the list $sql = "select *, "; - $sql .= "(select a.contact_attachment_uuid from v_contact_attachments as a where a.contact_uuid = c.contact_uuid and a.attachment_primary = 1) as contact_attachment_uuid "; + $sql .= "(select a.contact_attachment_uuid from v_contact_attachments as a where a.contact_uuid = c.contact_uuid and a.attachment_primary = 1 limit 1) as contact_attachment_uuid "; $sql .= "from v_contacts as c "; $sql .= "where true "; if ($show != "all" || !permission_exists('contact_all')) { From 06e69bf5df8150d0bcc46427f4abe4ea72562420 Mon Sep 17 00:00:00 2001 From: fusionate Date: Fri, 28 Feb 2025 14:36:41 -0700 Subject: [PATCH 132/196] Contact - Attachments: Prevent access without authentication. --- core/contacts/contact_attachment.php | 1 + 1 file changed, 1 insertion(+) diff --git a/core/contacts/contact_attachment.php b/core/contacts/contact_attachment.php index 11b7bac938..f07714ca1e 100644 --- a/core/contacts/contact_attachment.php +++ b/core/contacts/contact_attachment.php @@ -26,6 +26,7 @@ //includes files require_once dirname(__DIR__, 2) . "/resources/require.php"; + require_once "resources/check_auth.php"; //add multi-lingual support $language = new text; From b4de6f5e4b94f5cca8b9a1a43925c3d2a3ad4470 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Fri, 28 Feb 2025 17:09:35 -0700 Subject: [PATCH 133/196] Use status voicemail Moved voicemail status after missed calls. This way, it will show the status of voicemail when it goes to voicemail. There is still a field in the CDR for missed_call and this will still be set to true. --- app/xml_cdr/resources/classes/xml_cdr.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/xml_cdr/resources/classes/xml_cdr.php b/app/xml_cdr/resources/classes/xml_cdr.php index 9cf18165ce..8d9f14e136 100644 --- a/app/xml_cdr/resources/classes/xml_cdr.php +++ b/app/xml_cdr/resources/classes/xml_cdr.php @@ -612,12 +612,6 @@ if (!class_exists('xml_cdr')) { if ($xml->variables->hangup_cause == 'NO_ANSWER') { $status = 'no_answer'; } - if (substr($destination_number, 0, 3) == '*99') { - $status = 'voicemail'; - } - if (isset($xml->variables->voicemail_message_seconds) && $xml->variables->voicemail_message_seconds > 0) { - $status = 'voicemail'; - } if ($xml->variables->hangup_cause == 'ORIGINATOR_CANCEL') { $status = 'cancelled'; } @@ -633,12 +627,18 @@ if (!class_exists('xml_cdr')) { if ($xml->variables->cc_side == 'agent' && $xml->variables->billsec == 0) { $status = 'no_answer'; } - if (!isset($status) && $xml->variables->billsec == 0) { + if (!isset($status) && $xml->variables->billsec == 0) { $status = 'no_answer'; } if ($missed_call == 'true') { $status = 'missed'; } + if (substr($destination_number, 0, 3) == '*99') { + $status = 'voicemail'; + } + if (!empty($xml->variables->voicemail_message_seconds)) { + $status = 'voicemail'; + } //set the key $key = 'xml_cdr'; From e4ddb4561e1d3d7be46d9e92958042b2fbc6d78e Mon Sep 17 00:00:00 2001 From: chansizzle <14916599+chansizzle@users.noreply.github.com> Date: Fri, 28 Feb 2025 17:22:22 -0700 Subject: [PATCH 134/196] fix email category mispelling (#7280) --- app/switch/resources/scripts/app/emergency/index.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/switch/resources/scripts/app/emergency/index.lua b/app/switch/resources/scripts/app/emergency/index.lua index f4bffd0936..009e72c2f0 100644 --- a/app/switch/resources/scripts/app/emergency/index.lua +++ b/app/switch/resources/scripts/app/emergency/index.lua @@ -94,7 +94,7 @@ local sql = "SELECT * FROM v_email_templates "; sql = sql .. "WHERE template_category = :category "; sql = sql .. "AND template_subcategory = :subcategory "; sql = sql .. "AND template_enabled = :status "; - local params = {category = 'plugins', subcategory = 'emergency', status = 'true'} + local params = {category = 'plugin', subcategory = 'emergency', status = 'true'} dbh:query(sql, params, function(row) subject = row.template_subject; body = row.template_body; From de516ed210cde73aed08e36c43a2396340b0198c Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Sat, 1 Mar 2025 20:59:48 -0700 Subject: [PATCH 135/196] Minor version update 5.4.2 --- core/software/resources/classes/software.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/software/resources/classes/software.php b/core/software/resources/classes/software.php index 7fe0436ccd..7a84332caf 100644 --- a/core/software/resources/classes/software.php +++ b/core/software/resources/classes/software.php @@ -12,7 +12,7 @@ if (!class_exists('software')) { * version */ public static function version() { - return '5.4.1'; + return '5.4.2'; } /** From 06c20ef292841cb5db8c4bf93ad4cde245c7a914 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Sat, 1 Mar 2025 22:25:06 -0700 Subject: [PATCH 136/196] Fix contact notes with line feeds. When saving contact notes, it would add extra line feeds. The escaping caused this issue. --- core/contacts/contact_edit.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/contacts/contact_edit.php b/core/contacts/contact_edit.php index e95f3c1393..5e8e288bee 100644 --- a/core/contacts/contact_edit.php +++ b/core/contacts/contact_edit.php @@ -2719,8 +2719,9 @@ if (permission_exists('contact_note_view')) { $x = 0; foreach($contact_notes as $row) { $contact_note = $row['contact_note']; - $contact_note = escape($contact_note); - $contact_note = str_replace("\n","
",$contact_note); + if (!empty($contact_note)) { + $contact_note = htmlspecialcars($contact_note, ENT_QUOTES, 'UTF-8'); + } if (permission_exists('contact_note_add')) { $list_row_url = "contact_note_edit.php?contact_uuid=".escape($row['contact_uuid'])."&id=".escape($row['contact_note_uuid']); } From 48e44814de5300a5fc034d5241f5cc630cff2ed7 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Sun, 2 Mar 2025 10:38:34 -0700 Subject: [PATCH 137/196] Update email_send.php --- app/email_queue/resources/jobs/email_send.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/email_queue/resources/jobs/email_send.php b/app/email_queue/resources/jobs/email_send.php index bdfa84c3d1..82a0180358 100755 --- a/app/email_queue/resources/jobs/email_send.php +++ b/app/email_queue/resources/jobs/email_send.php @@ -298,7 +298,7 @@ //echo "Body: ".$email_body."\n"; //update the message transcription - if (isset($voicemail_transcription_enabled) && $voicemail_transcription_enabled == 'true' && isset($transcribe_message)) { + if (isset($voicemail_transcription_enabled) && $voicemail_transcription_enabled && isset($transcribe_message)) { $sql = "update v_voicemail_messages "; $sql .= "set message_transcription = :message_transcription "; $sql .= "where voicemail_message_uuid = :voicemail_message_uuid; "; From a15488a708eebce27a0471e2e65ccc46e7c1bb19 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Sun, 2 Mar 2025 10:45:31 -0700 Subject: [PATCH 138/196] Update the condition for validate certificate for a boolean value --- resources/classes/email.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/resources/classes/email.php b/resources/classes/email.php index 81cf026dd3..dc419897b0 100644 --- a/resources/classes/email.php +++ b/resources/classes/email.php @@ -445,7 +445,7 @@ if (!class_exists('email')) { $smtp['password'] = $this->settings->get('email','smtp_password'); $smtp['from'] = $this->settings->get('voicemail','smtp_from') ?? $this->settings->get('email','smtp_from'); $smtp['from_name'] = $this->settings->get('voicemail','smtp_from_name') ?? $this->settings->get('email','smtp_from_name'); - $smtp['validate_certificate'] = $this->settings->get('email','smtp_validate_certificate'); + $smtp['validate_certificate'] = $this->settings->get('email','smtp_validate_certificate', true); $smtp['crypto_method'] = $this->settings->get('email','smtp_crypto_method') ?? null; //override the domain-specific smtp server settings, if any @@ -506,7 +506,7 @@ if (!class_exists('email')) { $mail->SMTPSecure = $smtp['secure']; } - if ($smtp_secure && isset($smtp['validate_certificate']) && $smtp['validate_certificate'] == "false") { + if ($smtp_secure && isset($smtp['validate_certificate']) && !$smtp['validate_certificate']) { //bypass certificate check e.g. for self-signed certificates $smtp_options['ssl']['verify_peer'] = false; $smtp_options['ssl']['verify_peer_name'] = false; @@ -638,5 +638,3 @@ $email->attachments = $email_attachments; $response = $mail->error; $sent = $email->send(); */ - -?> From 7d62cc1e639e3ec668b2046c3b51916ffa9b11f6 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Mon, 3 Mar 2025 12:29:56 -0700 Subject: [PATCH 139/196] Fix the server 2 address and sip transport --- .../provision/grandstream/gxp2130/{$mac}.xml | 2 ++ .../provision/grandstream/gxp2135/{$mac}.xml | 6 ++++++ .../provision/grandstream/gxp2140/{$mac}.xml | 15 ++++++++++----- .../provision/grandstream/gxp2160/{$mac}.xml | 15 ++++++++++----- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/resources/templates/provision/grandstream/gxp2130/{$mac}.xml b/resources/templates/provision/grandstream/gxp2130/{$mac}.xml index 9162c1b7e3..4de008c7a4 100644 --- a/resources/templates/provision/grandstream/gxp2130/{$mac}.xml +++ b/resources/templates/provision/grandstream/gxp2130/{$mac}.xml @@ -180,6 +180,7 @@ + {if $row.sip_transport == ''}1{/if} {if $row.sip_transport == 'udp'}0{/if} {if $row.sip_transport == 'tcp'}1{/if} @@ -913,6 +914,7 @@ {if $grandstream_lan_port_vlan == '0'}No{else}Yes{/if} + diff --git a/resources/templates/provision/grandstream/gxp2135/{$mac}.xml b/resources/templates/provision/grandstream/gxp2135/{$mac}.xml index c17ee0a6e9..3038d56bbb 100644 --- a/resources/templates/provision/grandstream/gxp2135/{$mac}.xml +++ b/resources/templates/provision/grandstream/gxp2135/{$mac}.xml @@ -38,7 +38,11 @@ {$row.server_address}:{$row.sip_port} {/if} + {if isset($row.server_address_secondary)} {$row.server_address_secondary}:{$row.sip_port} + {else} + + {/if} {if $row.sip_transport != 'dns srv' && isset($row.outbound_proxy_primary)} @@ -176,6 +180,7 @@ + {if $row.sip_transport == ''}1{/if} {if $row.sip_transport == 'udp'}0{/if} {if $row.sip_transport == 'tcp'}1{/if} @@ -909,6 +914,7 @@ {if $grandstream_lan_port_vlan == '0'}No{else}Yes{/if} + diff --git a/resources/templates/provision/grandstream/gxp2140/{$mac}.xml b/resources/templates/provision/grandstream/gxp2140/{$mac}.xml index bb5a7f2856..ca8998d462 100644 --- a/resources/templates/provision/grandstream/gxp2140/{$mac}.xml +++ b/resources/templates/provision/grandstream/gxp2140/{$mac}.xml @@ -38,7 +38,11 @@ {$row.server_address}:{$row.sip_port} {/if} + {if isset($row.server_address_secondary)} {$row.server_address_secondary}:{$row.sip_port} + {else} + + {/if} {if $row.sip_transport != 'dns srv' && isset($row.outbound_proxy_primary)} @@ -176,10 +180,11 @@ - {if $row.sip_transport == ''}TCP{/if} - {if $row.sip_transport == 'udp'}UDP{/if} - {if $row.sip_transport == 'tcp'}TCP{/if} - {if $row.sip_transport == 'tls'}Tls{/if} + + {if $row.sip_transport == ''}1{/if} + {if $row.sip_transport == 'udp'}0{/if} + {if $row.sip_transport == 'tcp'}1{/if} + {if $row.sip_transport == 'tls'}2{/if} @@ -3318,4 +3323,4 @@ {/foreach} - \ No newline at end of file + diff --git a/resources/templates/provision/grandstream/gxp2160/{$mac}.xml b/resources/templates/provision/grandstream/gxp2160/{$mac}.xml index 5bfc894586..6ece8ae8f7 100644 --- a/resources/templates/provision/grandstream/gxp2160/{$mac}.xml +++ b/resources/templates/provision/grandstream/gxp2160/{$mac}.xml @@ -38,7 +38,11 @@ {$row.server_address}:{$row.sip_port} {/if} + {if isset($row.server_address_secondary)} {$row.server_address_secondary}:{$row.sip_port} + {else} + + {/if} {if $row.sip_transport != 'dns srv' && isset($row.outbound_proxy_primary)} @@ -176,10 +180,11 @@ - {if $row.sip_transport == ''}TCP{/if} - {if $row.sip_transport == 'udp'}UDP{/if} - {if $row.sip_transport == 'tcp'}TCP{/if} - {if $row.sip_transport == 'tls'}Tls{/if} + + {if $row.sip_transport == ''}1{/if} + {if $row.sip_transport == 'udp'}0{/if} + {if $row.sip_transport == 'tcp'}1{/if} + {if $row.sip_transport == 'tls'}2{/if} @@ -3318,4 +3323,4 @@ {/foreach} - \ No newline at end of file + From 7b3b3aa5f906e905975de785a9d87474fa8fab1a Mon Sep 17 00:00:00 2001 From: fusionate Date: Mon, 3 Mar 2025 14:08:05 -0700 Subject: [PATCH 140/196] Menu: New option to set icon colors. --- core/menu/app_config.php | 4 ++++ core/menu/app_languages.php | 27 +++++++++++++++++++++++++++ core/menu/menu_item_edit.php | 12 +++++++++++- core/menu/menu_item_list.php | 8 +++++--- resources/classes/menu.php | 15 +++++++++------ resources/fontawesome/fa_icons.php | 2 +- themes/default/css.php | 1 - 7 files changed, 57 insertions(+), 12 deletions(-) diff --git a/core/menu/app_config.php b/core/menu/app_config.php index df80515875..bf46c8ab0c 100644 --- a/core/menu/app_config.php +++ b/core/menu/app_config.php @@ -184,6 +184,10 @@ $apps[$x]['db'][$y]['fields'][$z]['type'] = "text"; $apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = ""; $z++; + $apps[$x]['db'][$y]['fields'][$z]['name'] = "menu_item_icon_color"; + $apps[$x]['db'][$y]['fields'][$z]['type'] = "text"; + $apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = ""; + $z++; $apps[$x]['db'][$y]['fields'][$z]['name'] = "menu_item_category"; $apps[$x]['db'][$y]['fields'][$z]['type'] = "text"; $apps[$x]['db'][$y]['fields'][$z]['search'] = "true"; diff --git a/core/menu/app_languages.php b/core/menu/app_languages.php index 723f57d730..35cd87c29e 100644 --- a/core/menu/app_languages.php +++ b/core/menu/app_languages.php @@ -540,6 +540,33 @@ $text['label-icon']['zh-cn'] = "图标"; $text['label-icon']['ja-jp'] = "アイコン"; $text['label-icon']['ko-kr'] = "아이콘"; +$text['label-icon_color']['en-us'] = "Icon Color"; +$text['label-icon_color']['en-gb'] = "Icon Color"; +$text['label-icon_color']['ar-eg'] = "لون الأيقونة"; +$text['label-icon_color']['de-at'] = "Symbolfarbe"; +$text['label-icon_color']['de-ch'] = "Symbolfarbe"; +$text['label-icon_color']['de-de'] = "Symbolfarbe"; +$text['label-icon_color']['el-gr'] = "Χρώμα εικονιδίου"; +$text['label-icon_color']['es-cl'] = "Color del icono"; +$text['label-icon_color']['es-mx'] = "Color del icono"; +$text['label-icon_color']['fr-ca'] = "Couleur de l'icône"; +$text['label-icon_color']['fr-fr'] = "Couleur de l'icône"; +$text['label-icon_color']['he-il'] = "צבע סמל"; +$text['label-icon_color']['it-it'] = "Colore dell'icona"; +$text['label-icon_color']['ka-ge'] = "ხატულა ფერი"; +$text['label-icon_color']['nl-nl'] = "Icoon Kleur"; +$text['label-icon_color']['pl-pl'] = "Kolor ikony"; +$text['label-icon_color']['pt-br'] = "Cor do ícone"; +$text['label-icon_color']['pt-pt'] = "Cor do ícone"; +$text['label-icon_color']['ro-ro'] = "Culoarea pictogramei"; +$text['label-icon_color']['ru-ru'] = "Цвет значка"; +$text['label-icon_color']['sv-se'] = "Ikon färg"; +$text['label-icon_color']['uk-ua'] = "Колір значка"; +$text['label-icon_color']['tr-tr'] = "Simge Rengi"; +$text['label-icon_color']['zh-cn'] = "图标颜色"; +$text['label-icon_color']['ja-jp'] = "アイコンの色"; +$text['label-icon_color']['ko-kr'] = "아이콘 색상"; + $text['label-groups']['en-us'] = "Groups"; $text['label-groups']['en-gb'] = "Groups"; $text['label-groups']['ar-eg'] = "المجموعات"; diff --git a/core/menu/menu_item_edit.php b/core/menu/menu_item_edit.php index dba0d09a89..a5e24a849e 100644 --- a/core/menu/menu_item_edit.php +++ b/core/menu/menu_item_edit.php @@ -51,6 +51,7 @@ $menu_item_link = ''; $menu_item_category = ''; $menu_item_icon = ''; + $menu_item_icon_color = ''; $menu_item_description = ''; $menu_item_protected = ''; $menu_item_parent_uuid = null; @@ -102,6 +103,7 @@ $menu_item_link = $_POST["menu_item_link"] ?? ''; $menu_item_category = $_POST["menu_item_category"] ?? ''; $menu_item_icon = $_POST["menu_item_icon"] ?? ''; + $menu_item_icon_color = $_POST["menu_item_icon_color"] ?? ''; $menu_item_description = $_POST["menu_item_description"] ?? ''; $menu_item_protected = $_POST["menu_item_protected"] ?? ''; $menu_item_parent_uuid = $_POST["menu_item_parent_uuid"] ?? null; @@ -173,6 +175,7 @@ $array['menu_items'][0]['menu_item_link'] = $menu_item_link; $array['menu_items'][0]['menu_item_category'] = $menu_item_category; $array['menu_items'][0]['menu_item_icon'] = $menu_item_icon; + $array['menu_items'][0]['menu_item_icon_color'] = $menu_item_icon_color; $array['menu_items'][0]['menu_item_description'] = $menu_item_description; $array['menu_items'][0]['menu_item_protected'] = $menu_item_protected; $array['menu_items'][0]['menu_item_uuid'] = $menu_item_uuid; @@ -198,6 +201,7 @@ $array['menu_items'][0]['menu_item_link'] = $menu_item_link; $array['menu_items'][0]['menu_item_category'] = $menu_item_category; $array['menu_items'][0]['menu_item_icon'] = $menu_item_icon; + $array['menu_items'][0]['menu_item_icon_color'] = $menu_item_icon_color; $array['menu_items'][0]['menu_item_description'] = $menu_item_description; $array['menu_items'][0]['menu_item_protected'] = $menu_item_protected; $array['menu_items'][0]['menu_item_uuid'] = $menu_item_uuid; @@ -313,6 +317,7 @@ $menu_item_link = $row["menu_item_link"]; $menu_item_category = $row["menu_item_category"]; $menu_item_icon = $row["menu_item_icon"]; + $menu_item_icon_color = $row["menu_item_icon_color"]; $menu_item_description = $row["menu_item_description"]; $menu_item_protected = $row["menu_item_protected"]; $menu_item_parent_uuid = $row["menu_item_parent_uuid"]; @@ -430,7 +435,7 @@ echo "\n"; echo " \n"; echo " "; echo " "; + echo " "; + echo " "; + echo " "; + echo " "; + echo " "; echo " "; echo " \n"; - if (permission_exists('bridge_edit') && !empty($list_row_edit_button) && $list_row_edit_button == 'true') { + if (permission_exists('bridge_edit') && $list_row_edit_button) { echo " \n"; } echo "\n"; @@ -270,7 +270,7 @@ } echo " \n"; echo " \n"; - if (permission_exists('bridge_edit') && !empty($list_row_edit_button) && $list_row_edit_button == 'true') { + if (permission_exists('bridge_edit') && $list_row_edit_button) { echo " \n"; diff --git a/app/call_block/call_block.php b/app/call_block/call_block.php index 6ed672bc6d..3d6ae3c27e 100644 --- a/app/call_block/call_block.php +++ b/app/call_block/call_block.php @@ -46,7 +46,7 @@ $show = $_GET["show"] ?? ''; //set from session variables - $list_row_edit_button = !empty($_SESSION['theme']['list_row_edit_button']['boolean']) ? $_SESSION['theme']['list_row_edit_button']['boolean'] : 'false'; + $list_row_edit_button = filter_var($_SESSION['theme']['list_row_edit_button']['boolean'] ?? false, FILTER_VALIDATE_BOOL); //get posted data if (!empty($_POST['call_blocks'])) { @@ -301,7 +301,7 @@ echo th_order_by('call_block_enabled', $text['label-enabled'], $order_by, $order, null, "class='center'"); echo th_order_by('insert_date', $text['label-date-added'], $order_by, $order, null, "class='shrink no-wrap'"); echo "\n"; - if (permission_exists('call_block_edit') && $list_row_edit_button == 'true') { + if (permission_exists('call_block_edit') && $list_row_edit_button) { echo " \n"; } echo "\n"; @@ -385,7 +385,7 @@ echo " \n"; echo " \n"; echo " \n"; - if (permission_exists('call_block_edit') && $list_row_edit_button == 'true') { + if (permission_exists('call_block_edit') && $list_row_edit_button) { echo " \n"; diff --git a/app/call_broadcast/call_broadcast.php b/app/call_broadcast/call_broadcast.php index 6e6cd20c00..aac61a9d67 100644 --- a/app/call_broadcast/call_broadcast.php +++ b/app/call_broadcast/call_broadcast.php @@ -47,7 +47,7 @@ $show = $_GET["show"] ?? ''; //set from session variables - $list_row_edit_button = !empty($_SESSION['theme']['list_row_edit_button']['boolean']) ? $_SESSION['theme']['list_row_edit_button']['boolean'] : 'false'; + $list_row_edit_button = filter_var($_SESSION['theme']['list_row_edit_button']['boolean'] ?? false, FILTER_VALIDATE_BOOL); //get posted data if (!empty($_POST['call_broadcasts'])) { @@ -219,7 +219,7 @@ echo th_order_by('broadcast_concurrent_limit', $text['label-concurrent-limit'], $order_by, $order); echo th_order_by('broadcast_start_time', $text['label-start_time'], $order_by, $order); echo th_order_by('broadcast_description', $text['label-description'], $order_by, $order); - if (permission_exists('call_broadcast_edit') && $list_row_edit_button == 'true') { + if (permission_exists('call_broadcast_edit') && $list_row_edit_button) { echo " \n"; } echo "\n"; @@ -266,7 +266,7 @@ } echo " \n"; echo " \n"; - if (permission_exists('call_broadcast_edit') && $list_row_edit_button == 'true') { + if (permission_exists('call_broadcast_edit') && $list_row_edit_button) { echo " \n"; diff --git a/app/call_centers/call_center_agents.php b/app/call_centers/call_center_agents.php index 9d76bf34bb..634b1468ac 100644 --- a/app/call_centers/call_center_agents.php +++ b/app/call_centers/call_center_agents.php @@ -43,7 +43,7 @@ $text = $language->get(); //set from session variables - $list_row_edit_button = !empty($_SESSION['theme']['list_row_edit_button']['boolean']) ? $_SESSION['theme']['list_row_edit_button']['boolean'] : 'false'; + $list_row_edit_button = filter_var($_SESSION['theme']['list_row_edit_button']['boolean'] ?? false, FILTER_VALIDATE_BOOL); //get posted data if (!empty($_POST['call_center_agents'])) { @@ -206,7 +206,7 @@ //echo th_order_by('agent_wrap_up_time', $text['label-wrap_up_time'], $order_by, $order); //echo th_order_by('agent_reject_delay_time', $text['label-reject_delay_time'], $order_by, $order); //echo th_order_by('agent_busy_delay_time', $text['label-busy_delay_time'], $order_by, $order); - if (permission_exists('call_center_agent_edit') && $list_row_edit_button == 'true') { + if (permission_exists('call_center_agent_edit') && $list_row_edit_button) { echo " \n"; } echo "\n"; @@ -270,7 +270,7 @@ //echo " \n"; //echo " \n"; //echo " \n"; - if (permission_exists('call_center_agent_edit') && $list_row_edit_button == 'true') { + if (permission_exists('call_center_agent_edit') && $list_row_edit_button) { echo " \n"; diff --git a/app/call_centers/call_center_queues.php b/app/call_centers/call_center_queues.php index 52ef61e629..50b9e93ee3 100644 --- a/app/call_centers/call_center_queues.php +++ b/app/call_centers/call_center_queues.php @@ -46,7 +46,7 @@ $show = $_GET["show"] ?? ''; //set from session variables - $list_row_edit_button = !empty($_SESSION['theme']['list_row_edit_button']['boolean']) ? $_SESSION['theme']['list_row_edit_button']['boolean'] : 'false'; + $list_row_edit_button = filter_var($_SESSION['theme']['list_row_edit_button']['boolean'] ?? false, FILTER_VALIDATE_BOOL); //get posted data if (!empty($_POST['call_center_queues']) && is_array($_POST['call_center_queues'])) { @@ -219,7 +219,7 @@ //echo th_order_by('queue_abandoned_resume_allowed', $text['label-abandoned_resume_allowed'], $order_by, $order); //echo th_order_by('queue_tier_rule_wait_multiply_level', $text['label-tier_rule_wait_multiply_level'], $order_by, $order); echo th_order_by('queue_description', $text['label-description'], $order_by, $order, null, "class='hide-sm-dn'"); - if (permission_exists('call_center_queue_edit') && $list_row_edit_button == 'true') { + if (permission_exists('call_center_queue_edit') && $list_row_edit_button) { echo " \n"; } echo "\n"; @@ -273,7 +273,7 @@ //echo " \n"; //echo " \n"; echo " \n"; - if (permission_exists('call_center_queue_edit') && $list_row_edit_button == 'true') { + if (permission_exists('call_center_queue_edit') && $list_row_edit_button) { echo " \n"; diff --git a/app/call_centers/waveform.php b/app/call_centers/waveform.php index 3408037311..f51a6a97fc 100644 --- a/app/call_centers/waveform.php +++ b/app/call_centers/waveform.php @@ -96,8 +96,8 @@ Waveform::$colorB = !empty($_SESSION['theme']['audio_player_waveform_color_b_leg']['text']) ? color_to_rgba_array($_SESSION['theme']['audio_player_waveform_color_b_leg']['text']) : [0,125,232,0.6]; // array rgba, right (b-leg) wave color Waveform::$backgroundColor = !empty($_SESSION['theme']['audio_player_waveform_color_background']['text']) ? color_to_rgba_array($_SESSION['theme']['audio_player_waveform_color_background']['text']) : [0,0,0,0]; // array rgba, default: transparent Waveform::$axisColor = !empty($_SESSION['theme']['audio_player_waveform_color_axis']['text']) ? color_to_rgba_array($_SESSION['theme']['audio_player_waveform_color_axis']['text']) : [0,0,0,0.3]; // array rgba - Waveform::$singlePhase = empty($_SESSION['theme']['audio_player_waveform_single_phase']['boolean']) || $_SESSION['theme']['audio_player_waveform_single_phase']['boolean'] !== 'true' ? false : true; // positive phase only - left (a-leg) top, right (b-leg) bottom - Waveform::$singleAxis = empty($_SESSION['theme']['audio_player_waveform_single_axis']['boolean']) || $_SESSION['theme']['audio_player_waveform_single_axis']['boolean'] !== 'false' ? true : false; // combine channels into single axis + Waveform::$singlePhase = filter_var($_SESSION['theme']['audio_player_waveform_single_phase']['boolean'] ?? false, FILTER_VALIDATE_BOOL); // positive phase only - left (a-leg) top, right (b-leg) bottom + Waveform::$singleAxis = filter_var($_SESSION['theme']['audio_player_waveform_single_axis']['boolean'] ?? false, FILTER_VALIDATE_BOOL); // combine channels into single axis $height = !empty($_SESSION['theme']['audio_player_waveform_height']['text']) && is_numeric(str_replace('px','',$_SESSION['theme']['audio_player_waveform_height']['text'])) ? 2.2 * (int) str_replace('px','',$_SESSION['theme']['audio_player_waveform_height']['text']) : null; $wf = $waveform->getWaveform($temp_filename, 1600, $height ?? 180); // input: png filename returns boolean true/false, or 'base64' returns base64 string } diff --git a/app/call_flows/call_flows.php b/app/call_flows/call_flows.php index 2cbd2d6a53..85d5182497 100644 --- a/app/call_flows/call_flows.php +++ b/app/call_flows/call_flows.php @@ -46,7 +46,7 @@ $show = $_GET["show"] ?? ''; //set from session variables - $list_row_edit_button = !empty($_SESSION['theme']['list_row_edit_button']['boolean']) ? $_SESSION['theme']['list_row_edit_button']['boolean'] : 'false'; + $list_row_edit_button = filter_var($_SESSION['theme']['list_row_edit_button']['boolean'] ?? false, FILTER_VALIDATE_BOOL); //get search $search = $_REQUEST['search'] ?? null; @@ -235,7 +235,7 @@ } echo th_order_by('call_flow_enabled', $text['label-enabled'], $order_by, $order, null, "class='center'"); echo th_order_by('call_flow_description', $text['label-call_flow_description'], $order_by, $order, null, "class='hide-sm-dn'"); - if (permission_exists('call_flow_edit') && $list_row_edit_button == 'true') { + if (permission_exists('call_flow_edit') && $list_row_edit_button) { echo " \n"; } echo "\n"; @@ -291,7 +291,7 @@ echo escape($row['call_flow_enabled']); } echo " \n"; - if (permission_exists('call_flow_edit') && $list_row_edit_button == 'true') { + if (permission_exists('call_flow_edit') && $list_row_edit_button) { echo " \n"; diff --git a/app/call_flows/waveform.php b/app/call_flows/waveform.php index 3408037311..f51a6a97fc 100644 --- a/app/call_flows/waveform.php +++ b/app/call_flows/waveform.php @@ -96,8 +96,8 @@ Waveform::$colorB = !empty($_SESSION['theme']['audio_player_waveform_color_b_leg']['text']) ? color_to_rgba_array($_SESSION['theme']['audio_player_waveform_color_b_leg']['text']) : [0,125,232,0.6]; // array rgba, right (b-leg) wave color Waveform::$backgroundColor = !empty($_SESSION['theme']['audio_player_waveform_color_background']['text']) ? color_to_rgba_array($_SESSION['theme']['audio_player_waveform_color_background']['text']) : [0,0,0,0]; // array rgba, default: transparent Waveform::$axisColor = !empty($_SESSION['theme']['audio_player_waveform_color_axis']['text']) ? color_to_rgba_array($_SESSION['theme']['audio_player_waveform_color_axis']['text']) : [0,0,0,0.3]; // array rgba - Waveform::$singlePhase = empty($_SESSION['theme']['audio_player_waveform_single_phase']['boolean']) || $_SESSION['theme']['audio_player_waveform_single_phase']['boolean'] !== 'true' ? false : true; // positive phase only - left (a-leg) top, right (b-leg) bottom - Waveform::$singleAxis = empty($_SESSION['theme']['audio_player_waveform_single_axis']['boolean']) || $_SESSION['theme']['audio_player_waveform_single_axis']['boolean'] !== 'false' ? true : false; // combine channels into single axis + Waveform::$singlePhase = filter_var($_SESSION['theme']['audio_player_waveform_single_phase']['boolean'] ?? false, FILTER_VALIDATE_BOOL); // positive phase only - left (a-leg) top, right (b-leg) bottom + Waveform::$singleAxis = filter_var($_SESSION['theme']['audio_player_waveform_single_axis']['boolean'] ?? false, FILTER_VALIDATE_BOOL); // combine channels into single axis $height = !empty($_SESSION['theme']['audio_player_waveform_height']['text']) && is_numeric(str_replace('px','',$_SESSION['theme']['audio_player_waveform_height']['text'])) ? 2.2 * (int) str_replace('px','',$_SESSION['theme']['audio_player_waveform_height']['text']) : null; $wf = $waveform->getWaveform($temp_filename, 1600, $height ?? 180); // input: png filename returns boolean true/false, or 'base64' returns base64 string } diff --git a/app/call_forward/call_forward.php b/app/call_forward/call_forward.php index 45c6c2abbd..e7de481ed3 100644 --- a/app/call_forward/call_forward.php +++ b/app/call_forward/call_forward.php @@ -296,8 +296,8 @@ echo " \n"; } echo " \n"; - $list_row_edit_button = $_SESSION['theme']['list_row_edit_button']['boolean'] ?? 'false'; - if ( $list_row_edit_button === 'true') { + $list_row_edit_button = filter_var($_SESSION['theme']['list_row_edit_button']['boolean'] ?? false, FILTER_VALIDATE_BOOL); + if ($list_row_edit_button) { echo " \n"; } echo "\n"; @@ -402,7 +402,7 @@ echo " \n"; } echo " \n"; - if ($list_row_edit_button === 'true') { + if ($list_row_edit_button) { echo " \n"; diff --git a/app/call_forward/call_forward_edit.php b/app/call_forward/call_forward_edit.php index a1b2bc6e72..a6e48e8f7c 100644 --- a/app/call_forward/call_forward_edit.php +++ b/app/call_forward/call_forward_edit.php @@ -341,7 +341,7 @@ */ //send feature event notify to the phone - if (!empty($_SESSION['device']['feature_sync']['boolean']) && $_SESSION['device']['feature_sync']['boolean'] == "true") { + if (filter_var($_SESSION['device']['feature_sync']['boolean'] ?? false, FILTER_VALIDATE_BOOL)) { $ring_count = ceil($call_timeout / 6); $feature_event_notify = new feature_event_notify; $feature_event_notify->domain_name = $_SESSION['domain_name']; @@ -358,7 +358,7 @@ else { $feature_event_notify->forward_all_destination = $forward_all_destination; } - + if ($forward_busy_destination == "") { $feature_event_notify->forward_busy_destination = "0"; } @@ -504,7 +504,7 @@ } //prepare the autocomplete - if(!empty($_SESSION['follow_me']['follow_me_autocomplete']['boolean']) && $_SESSION['follow_me']['follow_me_autocomplete']['boolean'] == 'true') { + if(filter_var($_SESSION['follow_me']['follow_me_autocomplete']['boolean'] ?? false, FILTER_VALIDATE_BOOLEAN)) { echo "\n"; echo "\n"; echo " - \n"; + echo " function get_destinations(id, destination_type, action, search) {\n"; + echo " var xhttp = new XMLHttpRequest();\n"; + echo " xhttp.onreadystatechange = function() {\n"; + echo " if (this.readyState == 4 && this.status == 200) {\n"; + echo " document.getElementById(id).innerHTML = this.responseText;\n"; + echo " }\n"; + echo " };\n"; + echo " if (action) {\n"; + echo " xhttp.open(\"GET\", \"/app/destinations/resources/destinations.php?destination_type=\"+destination_type+\"&action=\"+action, true);\n"; + echo " }\n"; + echo " else {\n"; + echo " xhttp.open(\"GET\", \"/app/destinations/resources/destinations.php?destination_type=\"+destination_type, true);\n"; + echo " }\n"; + echo " xhttp.send();\n"; + echo " }\n"; + echo "\n"; //get the destinations $destinations = $this->get($destination_type); @@ -1308,7 +1302,7 @@ if (!class_exists('destinations')) { } //method } //class -} + /* $obj = new destinations; //$destinations = $obj->destinations; @@ -1319,5 +1313,3 @@ echo $obj->select('ivr', 'example4', ''); echo $obj->select('ivr', 'example5', ''); echo $obj->select('ivr', 'example6', ''); */ - -?> diff --git a/app/dialplans/resources/classes/dialplan.php b/app/dialplans/resources/classes/dialplan.php index 5c5b1cee7b..0147b6b313 100644 --- a/app/dialplans/resources/classes/dialplan.php +++ b/app/dialplans/resources/classes/dialplan.php @@ -25,7 +25,6 @@ */ //define the dialplan class - if (!class_exists('dialplan')) { class dialplan { //variables @@ -1580,6 +1579,3 @@ } //class - } - -?> diff --git a/app/email_queue/resources/classes/email_queue.php b/app/email_queue/resources/classes/email_queue.php index 77bc6542ee..a7efc72c7e 100644 --- a/app/email_queue/resources/classes/email_queue.php +++ b/app/email_queue/resources/classes/email_queue.php @@ -2,12 +2,7 @@ /** * email_queue class - * - * @method null delete - * @method null toggle - * @method null copy */ -if (!class_exists('email_queue')) { class email_queue { /** @@ -225,6 +220,3 @@ if (!class_exists('email_queue')) { } } -} - -?> diff --git a/app/email_queue/resources/jobs/email_queue.php b/app/email_queue/resources/jobs/email_queue.php index 9e1d3952eb..0167e54796 100755 --- a/app/email_queue/resources/jobs/email_queue.php +++ b/app/email_queue/resources/jobs/email_queue.php @@ -11,7 +11,6 @@ //includes files require_once "resources/pdo.php"; - include "resources/classes/permissions.php"; require $_SERVER['DOCUMENT_ROOT']."/app/email_queue/resources/functions/transcribe.php"; //increase limits diff --git a/app/email_queue/resources/jobs/email_send.php b/app/email_queue/resources/jobs/email_send.php index 82a0180358..a0b3f8d213 100755 --- a/app/email_queue/resources/jobs/email_send.php +++ b/app/email_queue/resources/jobs/email_send.php @@ -10,7 +10,6 @@ } //include files - include "resources/classes/permissions.php"; include_once "resources/phpmailer/class.phpmailer.php"; include_once "resources/phpmailer/class.smtp.php"; diff --git a/app/email_queue/resources/service/email_queue.php b/app/email_queue/resources/service/email_queue.php index f12a023502..684dbc7b8e 100644 --- a/app/email_queue/resources/service/email_queue.php +++ b/app/email_queue/resources/service/email_queue.php @@ -9,9 +9,6 @@ exit; } -//include files - include "resources/classes/permissions.php"; - //increase limits set_time_limit(0); ini_set('max_execution_time', 0); diff --git a/app/event_guard/resources/classes/event_guard.php b/app/event_guard/resources/classes/event_guard.php index 02bafd1bc2..69ff9aefcf 100644 --- a/app/event_guard/resources/classes/event_guard.php +++ b/app/event_guard/resources/classes/event_guard.php @@ -26,12 +26,7 @@ /** * event_guard_logs class - * - * @method null delete - * @method null toggle - * @method null copy */ -if (!class_exists('event_guard')) { class event_guard { /** @@ -303,6 +298,3 @@ if (!class_exists('event_guard')) { } } -} - -?> diff --git a/app/extension_settings/resources/classes/extension_settings.php b/app/extension_settings/resources/classes/extension_settings.php index b473669e9d..15c5b2cc01 100644 --- a/app/extension_settings/resources/classes/extension_settings.php +++ b/app/extension_settings/resources/classes/extension_settings.php @@ -26,12 +26,7 @@ /** * extension_settings class - * - * @method null delete - * @method null toggle - * @method null copy */ -if (!class_exists('extension_settings')) { class extension_settings { /** @@ -272,6 +267,3 @@ if (!class_exists('extension_settings')) { } } -} - -?> diff --git a/app/extensions/extension_copy.php b/app/extensions/extension_copy.php index 9148d21b6b..0aeca685a4 100644 --- a/app/extensions/extension_copy.php +++ b/app/extensions/extension_copy.php @@ -186,7 +186,6 @@ //synchronize configuration if (is_writable($_SESSION['switch']['extensions']['dir'])) { - require_once "app/extensions/resources/classes/extension.php"; $ext = new extension; $ext->xml(); unset($ext); diff --git a/app/extensions/extension_edit.php b/app/extensions/extension_edit.php index 0bddf373df..f99c45b1b6 100644 --- a/app/extensions/extension_edit.php +++ b/app/extensions/extension_edit.php @@ -850,7 +850,6 @@ //synchronize configuration if (is_writable($switch_extensions)) { - require_once "app/extensions/resources/classes/extension.php"; $ext = new extension; $ext->xml(); unset($ext); @@ -2037,7 +2036,6 @@ echo " ".$text['label-hold_music']."\n"; echo "\n"; echo "\n"; echo "\n"; @@ -1104,7 +1099,7 @@ if (!defined('STDIN')) { for ($f = 1; $f <= 3; $f++) { echo " 1) ? "style='display: none;'" : null).">"; echo " "; - echo button::create(['type'=>'button','label'=>$text['button-clear'],'icon'=>$setting->get('theme','button_icon_reset'),'onclick'=>"reset_file_input('fax_files_".$f."'); document.getElementById('file_list_".$f."').innerHTML='';"]); + echo button::create(['type'=>'button','label'=>$text['button-clear'],'icon'=>$settings->get('theme','button_icon_reset'),'onclick'=>"reset_file_input('fax_files_".$f."'); document.getElementById('file_list_".$f."').innerHTML='';"]); echo "
"; echo " "; echo "
\n"; @@ -1119,9 +1114,9 @@ if (!defined('STDIN')) { echo "\n"; echo "\n"; echo "\n"; if (permission_exists('fax_subject')) { - $cover_subject_required = $setting->get('fax','cover_subject_required') ?? ''; + $cover_subject_required = $settings->get('fax','cover_subject_required') ?? ''; $class = ($cover_subject_required == 'true') ? 'vncellreq' : 'vncell'; $required = ($cover_subject_required == 'true') ? 'required' : ''; echo "\n"; @@ -1160,7 +1155,7 @@ if (!defined('STDIN')) { } if (permission_exists('fax_message')) { - $cover_message_required = $setting->get('fax','cover_message_required') ?? ''; + $cover_message_required = $settings->get('fax','cover_message_required') ?? ''; $class = ($cover_message_required == 'true') ? 'vncellreq' : 'vncell'; $required = ($cover_message_required == 'true') ? 'required' : ''; echo "\n"; @@ -1168,7 +1163,7 @@ if (!defined('STDIN')) { echo " ".$text['label-fax-message']."\n"; echo "\n"; echo "\n"; @@ -1181,7 +1176,7 @@ if (!defined('STDIN')) { echo " ".$text['label-fax-footer']."\n"; echo "\n"; echo "\n"; @@ -1228,4 +1223,4 @@ function showgrid($pdf) { } } */ -?> \ No newline at end of file +?> From b0a630e80a8ed1e5fc79be49c8c5cd5ed3e07a02 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Thu, 13 Mar 2025 11:25:15 -0600 Subject: [PATCH 194/196] Use no-wrap class --- app/xml_cdr/xml_cdr.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/xml_cdr/xml_cdr.php b/app/xml_cdr/xml_cdr.php index 75da41fbfa..3d0c019940 100644 --- a/app/xml_cdr/xml_cdr.php +++ b/app/xml_cdr/xml_cdr.php @@ -695,7 +695,7 @@ $col_count++; } if ($permission['xml_cdr_caller_destination']) { - echo "\n"; + echo "\n"; $col_count++; } if ($permission['xml_cdr_destination']) { @@ -913,7 +913,7 @@ } //extension if ($permission['xml_cdr_extension']) { - $content .= " \n"; + $content .= " \n"; } //domain name if ($permission['xml_cdr_all'] && $_REQUEST['show'] == "all") { From e6bfaf21ee349a743b66bef88d2bce1e9d24a062 Mon Sep 17 00:00:00 2001 From: chansizzle <14916599+chansizzle@users.noreply.github.com> Date: Thu, 13 Mar 2025 11:30:42 -0600 Subject: [PATCH 195/196] Remove escaping character typo (#7311) escaping character not needed on the template_subject --- core/email_templates/app_defaults.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/email_templates/app_defaults.php b/core/email_templates/app_defaults.php index f3280dd25d..47f422f0ee 100644 --- a/core/email_templates/app_defaults.php +++ b/core/email_templates/app_defaults.php @@ -510,7 +510,7 @@ $array['email_templates'][$x]['template_language'] = 'en-gb'; $array['email_templates'][$x]['template_category'] = 'plugin'; $array['email_templates'][$x]['template_subcategory'] = 'emergency'; - $array['email_templates'][$x]['template_subject'] = '\${event}'; + $array['email_templates'][$x]['template_subject'] = '${event}'; $array['email_templates'][$x]['template_body'] = "\n"; $array['email_templates'][$x]['template_body'] .= "\n"; $array['email_templates'][$x]['template_body'] .= "From: \${caller_id_name} \${caller_id_number}
\n"; @@ -530,7 +530,7 @@ $array['email_templates'][$x]['template_language'] = 'en-us'; $array['email_templates'][$x]['template_category'] = 'plugin'; $array['email_templates'][$x]['template_subcategory'] = 'emergency'; - $array['email_templates'][$x]['template_subject'] = '\${event}'; + $array['email_templates'][$x]['template_subject'] = '${event}'; $array['email_templates'][$x]['template_body'] = "\n"; $array['email_templates'][$x]['template_body'] .= "\n"; $array['email_templates'][$x]['template_body'] .= "From: \${caller_id_name} \${caller_id_number}
\n"; From 17b938698e289a8478dd90dc780391e296a010f5 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Thu, 13 Mar 2025 13:08:36 -0600 Subject: [PATCH 196/196] Start with the require.php --- app/fax/fax_send.php | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/app/fax/fax_send.php b/app/fax/fax_send.php index a3918a49d5..6a1996df08 100644 --- a/app/fax/fax_send.php +++ b/app/fax/fax_send.php @@ -28,22 +28,25 @@ Corey Moullas */ +//includes files + require_once dirname(__DIR__, 2) . "/resources/require.php"; + //check if windows if (stristr(PHP_OS, 'WIN')) { $IS_WINDOWS = true; } else { $IS_WINDOWS = false; } -//executed via command line -if (defined('STDIN')) { +//command line + if (defined('STDIN')) { - //add multi-lingual support - $language = new text; - $text = $language->get($settings->get('domain','language','en-us'), 'app/fax'); + //add multi-lingual support + $language = new text; + $text = $language->get($settings->get('domain','language','en-us'), 'app/fax'); -} -//executed via browser -else { + } - //includes files - require_once dirname(__DIR__, 2) . "/resources/require.php"; +//web server + if (!defined('STDIN')) { + + //additional include require_once "resources/check_auth.php"; //set the domain_uuid and domain_name
\n"; - echo " \n"; echo " \n"; foreach ($font_awesome_icons as $icon) { $selected = $menu_item_icon == implode(' ', $icon['classes']) ? "selected" : null; @@ -470,6 +475,11 @@ echo "
".$text['label-icon_color']."
".$text['label-parent_menu'].""; diff --git a/core/menu/menu_item_list.php b/core/menu/menu_item_list.php index 282fe7e9bf..9da3c1c654 100644 --- a/core/menu/menu_item_list.php +++ b/core/menu/menu_item_list.php @@ -104,6 +104,7 @@ $menu_item_title = $row2['menu_item_title']; $menu_item_link = $row2['menu_item_link']; $menu_item_icon = $row2['menu_item_icon']; + $menu_item_icon_color = $row2['menu_item_icon_color']; //get the groups that have been assigned to the menu $sql = "select "; @@ -149,7 +150,7 @@ } //format icon - $menu_item_icon = !empty($menu_item_icon) ? "" : null; + $menu_item_icon = !empty($menu_item_icon) ? "" : null; //display the content of the list if (permission_exists('menu_item_edit')) { @@ -291,6 +292,7 @@ $menu_item_title = $row['menu_item_title']; $menu_item_link = $row['menu_item_link']; $menu_item_icon = $row['menu_item_icon']; + $menu_item_icon_color = $row['menu_item_icon_color']; $menu_item_protected = $row['menu_item_protected']; //get the groups that have been assigned to the menu @@ -336,7 +338,7 @@ } //format icon - $menu_item_icon = !empty($menu_item_icon) ? "" : null; + $menu_item_icon = !empty($menu_item_icon) ? "" : null; //display the content of the list if (permission_exists('menu_item_edit')) { @@ -437,4 +439,4 @@ echo "\n"; -?> +?> \ No newline at end of file diff --git a/resources/classes/menu.php b/resources/classes/menu.php index 86c8b8983c..9df1c94320 100644 --- a/resources/classes/menu.php +++ b/resources/classes/menu.php @@ -427,6 +427,7 @@ if (!class_exists('menu')) { $menu_item_parent_uuid = $uuid_array[$menu['parent_uuid']] ?? null; $menu_item_category = $menu['category']; $menu_item_icon = $menu['icon'] ?? null; + $menu_item_icon_color = $menu['icon_color'] ?? null; $menu_item_path = $menu['path']; $menu_item_order = $menu['order'] ?? null; $menu_item_description = $menu['desc'] ?? null; @@ -471,6 +472,7 @@ if (!class_exists('menu')) { $array['menu_items'][$x]['menu_item_link'] = $menu_item_path; $array['menu_items'][$x]['menu_item_category'] = $menu_item_category; $array['menu_items'][$x]['menu_item_icon'] = $menu_item_icon; + $array['menu_items'][$x]['menu_item_icon_color'] = $menu_item_icon_color; if (!empty($menu_item_order)) { $array['menu_items'][$x]['menu_item_order'] = $menu_item_order; } @@ -745,7 +747,7 @@ if (!class_exists('menu')) { //get the menu from the database $sql = "select i.menu_item_link, l.menu_item_title as menu_language_title, "; $sql .= "i.menu_item_title, i.menu_item_protected, i.menu_item_category, "; - $sql .= "i.menu_item_icon, i.menu_item_uuid, i.menu_item_parent_uuid "; + $sql .= "i.menu_item_icon, i.menu_item_icon_color, i.menu_item_uuid, i.menu_item_parent_uuid "; $sql .= "from v_menu_items as i, v_menu_languages as l "; $sql .= "where i.menu_item_uuid = l.menu_item_uuid "; $sql .= "and l.menu_language = :menu_language "; @@ -814,7 +816,7 @@ if (!class_exists('menu')) { } //get the child menu from the database - $sql = "select i.menu_item_link, l.menu_item_title as menu_language_title, i.menu_item_title, i.menu_item_protected, i.menu_item_category, i.menu_item_icon, i.menu_item_uuid, i.menu_item_parent_uuid "; + $sql = "select i.menu_item_link, l.menu_item_title as menu_language_title, i.menu_item_title, i.menu_item_protected, i.menu_item_category, i.menu_item_icon, i.menu_item_icon_color, i.menu_item_uuid, i.menu_item_parent_uuid "; $sql .= "from v_menu_items as i, v_menu_languages as l "; $sql .= "where i.menu_item_uuid = l.menu_item_uuid "; $sql .= "and l.menu_language = :menu_language "; @@ -854,6 +856,7 @@ if (!class_exists('menu')) { $menu_item_link = $row['menu_item_link']; $menu_item_category = $row['menu_item_category']; $menu_item_icon = $row['menu_item_icon']; + $menu_item_icon_color = $row['menu_item_icon_color']; $menu_item_uuid = $row['menu_item_uuid']; $menu_item_parent_uuid = $row['menu_item_parent_uuid']; @@ -1010,7 +1013,7 @@ if (!class_exists('menu')) { $mod_a_3 = ($menu_parent['menu_item_category'] == 'external') ? "target='_blank' " : null; if ($this->settings->get('theme', 'menu_main_icons', true) === true) { if (!empty($menu_parent['menu_item_icon']) && substr($menu_parent['menu_item_icon'], 0, 3) == 'fa-') { // font awesome icon - $menu_main_icon = ""; + $menu_main_icon = ""; } else { $menu_main_icon = null; @@ -1043,7 +1046,7 @@ if (!class_exists('menu')) { $menu_sub_icon = null; if ($this->settings->get('theme', 'menu_sub_icons', true) !== false) { if (!empty($menu_sub['menu_item_icon']) && substr($menu_sub['menu_item_icon'], 0, 3) == 'fa-') { // font awesome icon - $menu_sub_icon = ""; + $menu_sub_icon = ""; } else { $menu_sub_icon = null; @@ -1211,7 +1214,7 @@ if (!class_exists('menu')) { $html .= " \n"; } if (!empty($menu_item_main['menu_item_icon']) && substr($menu_item_main['menu_item_icon'], 0, 3) == 'fa-') { // font awesome icon - $html .= ""; + $html .= ""; } $html .= "".$menu_item_main['menu_language_title'].""; $html .= "\n"; @@ -1222,7 +1225,7 @@ if (!class_exists('menu')) { $menu_sub_icon = null; if ($this->settings->get('theme', 'menu_sub_icons', true) !== false) { if (!empty($menu_item_sub['menu_item_icon']) && substr($menu_item_sub['menu_item_icon'], 0, 3) == 'fa-') { // font awesome icon - $menu_sub_icon = ""; + $menu_sub_icon = ""; } else { $menu_sub_icon = null; diff --git a/resources/fontawesome/fa_icons.php b/resources/fontawesome/fa_icons.php index 9b2e128fed..558cea25d0 100644 --- a/resources/fontawesome/fa_icons.php +++ b/resources/fontawesome/fa_icons.php @@ -113,6 +113,6 @@ if ( !empty($font_awesome_icons) && is_array($font_awesome_icons) ) { foreach ($font_awesome_icons as $icon) { - echo "\n"; + echo "\n"; } } \ No newline at end of file diff --git a/themes/default/css.php b/themes/default/css.php index b2d13c6882..746d7a87f4 100644 --- a/themes/default/css.php +++ b/themes/default/css.php @@ -772,7 +772,6 @@ else { //default: white display: inline-block; font-size: 8pt; margin: 0 0 0 8px; - opacity: 0.30; } div.menu_side_sub > a.menu_side_item_sub > span.fas, From 150eeccd5e0a175e55cab6ba1caa09eabb5332ea Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Mon, 3 Mar 2025 18:43:29 -0700 Subject: [PATCH 141/196] Add grandstream_transfer_mode_via_vpk --- resources/templates/provision/grandstream/gxp2170/{$mac}.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/resources/templates/provision/grandstream/gxp2170/{$mac}.xml b/resources/templates/provision/grandstream/gxp2170/{$mac}.xml index 282c33c4d4..a7e742435a 100644 --- a/resources/templates/provision/grandstream/gxp2170/{$mac}.xml +++ b/resources/templates/provision/grandstream/gxp2170/{$mac}.xml @@ -2138,7 +2138,11 @@ + {if isset($grandstream_transfer_mode_via_vpk)} + {$grandstream_transfer_mode_via_vpk} + {else} BlindTransfer + {/if} Yes From 6baa6973f36fcc91ea3460030646f33799d195d1 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Mon, 3 Mar 2025 18:47:28 -0700 Subject: [PATCH 142/196] Add grandstream_transfer_mode_via_vpk --- resources/templates/provision/grandstream/gxp2160/{$mac}.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/resources/templates/provision/grandstream/gxp2160/{$mac}.xml b/resources/templates/provision/grandstream/gxp2160/{$mac}.xml index 6ece8ae8f7..5241c940a7 100644 --- a/resources/templates/provision/grandstream/gxp2160/{$mac}.xml +++ b/resources/templates/provision/grandstream/gxp2160/{$mac}.xml @@ -2138,7 +2138,11 @@ + {if isset($grandstream_transfer_mode_via_vpk)} + {$grandstream_transfer_mode_via_vpk} + {else} BlindTransfer + {/if} Yes From 9fcfc7276a3fc6c57998196a27f22a2664a029ff Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Mon, 3 Mar 2025 18:50:44 -0700 Subject: [PATCH 143/196] Add grandstream_transfer_mode_via_vpk --- resources/templates/provision/grandstream/gxp2140/{$mac}.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/resources/templates/provision/grandstream/gxp2140/{$mac}.xml b/resources/templates/provision/grandstream/gxp2140/{$mac}.xml index ca8998d462..bfea8b4834 100644 --- a/resources/templates/provision/grandstream/gxp2140/{$mac}.xml +++ b/resources/templates/provision/grandstream/gxp2140/{$mac}.xml @@ -2138,7 +2138,11 @@ + {if isset($grandstream_transfer_mode_via_vpk)} + {$grandstream_transfer_mode_via_vpk} + {else} BlindTransfer + {/if} Yes From c47eac110ac28246b1483cade1c65b6ecd8d6ae9 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Mon, 3 Mar 2025 18:50:58 -0700 Subject: [PATCH 144/196] Add grandstream_transfer_mode_via_vpk --- resources/templates/provision/grandstream/gxp2135/{$mac}.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/resources/templates/provision/grandstream/gxp2135/{$mac}.xml b/resources/templates/provision/grandstream/gxp2135/{$mac}.xml index 3038d56bbb..e0d1b4748f 100644 --- a/resources/templates/provision/grandstream/gxp2135/{$mac}.xml +++ b/resources/templates/provision/grandstream/gxp2135/{$mac}.xml @@ -2138,7 +2138,11 @@ + {if isset($grandstream_transfer_mode_via_vpk)} {$grandstream_transfer_mode_via_vpk} + {else} + BlindTransfer + {/if} Yes From bb02c97c64a79cca7d866319bc6d1bc683102a81 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Mon, 3 Mar 2025 18:51:19 -0700 Subject: [PATCH 145/196] Add grandstream_transfer_mode_via_vpk --- resources/templates/provision/grandstream/gxp2130/{$mac}.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/resources/templates/provision/grandstream/gxp2130/{$mac}.xml b/resources/templates/provision/grandstream/gxp2130/{$mac}.xml index 4de008c7a4..efb75a3402 100644 --- a/resources/templates/provision/grandstream/gxp2130/{$mac}.xml +++ b/resources/templates/provision/grandstream/gxp2130/{$mac}.xml @@ -2138,7 +2138,11 @@ + {if isset($grandstream_transfer_mode_via_vpk)} + {$grandstream_transfer_mode_via_vpk} + {else} BlindTransfer + {/if} Yes From 1b19e40be4a17689024510062a660618e45d6ee8 Mon Sep 17 00:00:00 2001 From: Antonio Fernandez Date: Tue, 4 Mar 2025 12:53:23 -0500 Subject: [PATCH 146/196] Consistent email wording (#7283) --- app/extensions/app_languages.php | 52 ++++++++++++++++---------------- app/voicemails/app_languages.php | 52 ++++++++++++++++---------------- 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/app/extensions/app_languages.php b/app/extensions/app_languages.php index ee1eee2d55..36b623abf6 100644 --- a/app/extensions/app_languages.php +++ b/app/extensions/app_languages.php @@ -2698,32 +2698,32 @@ $text['description-voicemail_password']['zh-cn'] = "在此处输入数字语音 $text['description-voicemail_password']['ja-jp'] = "ここに数値のボイスメール パスワードを入力します。"; $text['description-voicemail_password']['ko-kr'] = "여기에 숫자 음성사서함 암호를 입력합니다."; -$text['description-voicemail_mail_to']['en-us'] = "Enter the email address to send voicemail to (optional)."; -$text['description-voicemail_mail_to']['en-gb'] = "Enter the email address to send voicemail to (optional)."; -$text['description-voicemail_mail_to']['ar-eg'] = "أدخل العنوان الإلكتروني لإرسال البريد الصوتي إلى (اختياري)."; -$text['description-voicemail_mail_to']['de-at'] = "Geben Sie die Email Adresse an, an die Ihre Mailbox Nachricht gesendet werden soll (optional)."; -$text['description-voicemail_mail_to']['de-ch'] = "Geben Sie die Email Adresse an, an die Ihre Mailbox Nachricht gesendet werden soll (optional)."; -$text['description-voicemail_mail_to']['de-de'] = "Geben Sie die Email Adresse an, an die Ihre Mailbox Nachricht gesendet werden soll (optional)."; -$text['description-voicemail_mail_to']['el-gr'] = "Εισαγάγετε τη διεύθυνση email στην οποία θα στείλετε αυτόματο τηλεφωνητή (προαιρετικό)."; -$text['description-voicemail_mail_to']['es-cl'] = "Ingrese una dirección de correo electrónico para enviar el correo de voz (opcional)."; -$text['description-voicemail_mail_to']['es-mx'] = "Ingrese una dirección de correo electrónico para enviar el correo de voz (opcional)."; -$text['description-voicemail_mail_to']['fr-ca'] = "Insérer le courriel où sera envoyé le message de notification (optionnel)."; -$text['description-voicemail_mail_to']['fr-fr'] = "Insérer le courriel où sera envoyé le message de notification (optionnel)."; -$text['description-voicemail_mail_to']['he-il'] = "היכנס לכתובת הדואר האלקטרוני כדי לשלוח הודעות קוליות (אופציונלי)."; -$text['description-voicemail_mail_to']['it-it'] = "Inserire l'indirizzo email a cui recapitare i messaggi vocali (opzionale)."; -$text['description-voicemail_mail_to']['ka-ge'] = "შეიყვანეთ ელფოსტის მისამართი, რომელზეც ხმოვანი ფოსტა გამოიგზავნება (არასავალდებულო)."; -$text['description-voicemail_mail_to']['nl-nl'] = "Voer het E-mail adres om de voicemail naar te sturen (optioneel)."; -$text['description-voicemail_mail_to']['pl-pl'] = "Dodaj adres email na który będą wysyłane pliki poczty głosowej"; -$text['description-voicemail_mail_to']['pt-br'] = "Insira o endereço de email para enviar o correio de voz (opcional)."; -$text['description-voicemail_mail_to']['pt-pt'] = "Introduza o endereço de email para enviar o correio de voz (opcional)."; -$text['description-voicemail_mail_to']['ro-ro'] = "Introduceți adresa de e-mail la care trimiteți mesajul vocal (opțional)."; -$text['description-voicemail_mail_to']['ru-ru'] = "Введите адрес электронной почты, чтобы отправить голосовую почту (опционально)."; -$text['description-voicemail_mail_to']['sv-se'] = "Ange E-post adressen för röstbrevlådan (valfritt)."; -$text['description-voicemail_mail_to']['uk-ua'] = "Введіть адресу електронної пошти для відправки голосового повідомлення (за бажанням)."; -$text['description-voicemail_mail_to']['tr-tr'] = "Sesli mesajın gönderileceği e-posta adresini girin (isteğe bağlı)."; -$text['description-voicemail_mail_to']['zh-cn'] = "输入要向其发送语音邮件的电子邮件地址(可选)。"; -$text['description-voicemail_mail_to']['ja-jp'] = "ボイスメールの送信先の電子メール アドレスを入力します (オプション)。"; -$text['description-voicemail_mail_to']['ko-kr'] = "음성 메일을 보낼 이메일 주소를 입력합니다(선택 사항)."; +$text['description-voicemail_mail_to']['en-us'] = "Enter the email address to send voicemail to (optional). Multiple addresses may be separated by commas."; +$text['description-voicemail_mail_to']['en-gb'] = "Enter the email address to send voicemail to (optional). Multiple addresses may be separated by commas."; +$text['description-voicemail_mail_to']['ar-eg'] = "أدخل عنوان البريد الإلكتروني لإرسال البريد الصوتي إليه (اختياري). يمكن فصل العناوين المتعددة بفواصل."; +$text['description-voicemail_mail_to']['de-at'] = "Geben Sie die E-Mail-Adresse ein, an die die Voicemail gesendet werden soll (optional). Mehrere Adressen können durch Kommas getrennt werden."; +$text['description-voicemail_mail_to']['de-ch'] = "Geben Sie die E-Mail-Adresse ein, an die die Voicemail gesendet werden soll (optional). Mehrere Adressen können durch Kommas getrennt werden."; +$text['description-voicemail_mail_to']['de-de'] = "Geben Sie die E-Mail-Adresse ein, an die die Voicemail gesendet werden soll (optional). Mehrere Adressen können durch Kommas getrennt werden."; +$text['description-voicemail_mail_to']['el-gr'] = "Εισαγάγετε τη διεύθυνση email για αποστολή του φωνητικού μηνύματος (προαιρετικό). Πολλαπλές διευθύνσεις μπορούν να διαχωριστούν με κόμματα."; +$text['description-voicemail_mail_to']['es-cl'] = "Ingrese la dirección de correo electrónico para enviar el correo de voz (opcional). Se pueden separar múltiples direcciones con comas."; +$text['description-voicemail_mail_to']['es-mx'] = "Ingrese la dirección de correo electrónico para enviar el correo de voz (opcional). Se pueden separar múltiples direcciones con comas."; +$text['description-voicemail_mail_to']['fr-ca'] = "Entrez l'adresse e-mail à laquelle envoyer la messagerie vocale (facultatif). Plusieurs adresses peuvent être séparées par des virgules."; +$text['description-voicemail_mail_to']['fr-fr'] = "Entrez l'adresse e-mail à laquelle envoyer la messagerie vocale (facultatif). Plusieurs adresses peuvent être séparées par des virgules."; +$text['description-voicemail_mail_to']['he-il'] = "הזן את כתובת האימייל לשליחת הדואר הקולי (אופציונלי). ניתן להפריד בין כתובות מרובות באמצעות פסיקים."; +$text['description-voicemail_mail_to']['it-it'] = "Inserisci l'indirizzo email a cui inviare la segreteria telefonica (opzionale). Più indirizzi possono essere separati da virgole."; +$text['description-voicemail_mail_to']['ka-ge'] = "შეიყვანეთ ელ.ფოსტის მისამართი, რომელზეც გაიგზავნება ხმოვანი ფოსტა (არასავალდებულო). შესაძლებელია მრავალი მისამართის მძიმით გამოყოფა."; +$text['description-voicemail_mail_to']['nl-nl'] = "Voer het e-mailadres in om de voicemail naartoe te sturen (optioneel). Meerdere adressen kunnen worden gescheiden door komma's."; +$text['description-voicemail_mail_to']['pl-pl'] = "Wprowadź adres e-mail, na który ma zostać wysłana poczta głosowa (opcjonalnie). Wiele adresów można oddzielić przecinkami."; +$text['description-voicemail_mail_to']['pt-br'] = "Digite o endereço de e-mail para enviar o correio de voz (opcional). Vários endereços podem ser separados por vírgulas."; +$text['description-voicemail_mail_to']['pt-pt'] = "Digite o endereço de e-mail para enviar o correio de voz (opcional). Vários endereços podem ser separados por vírgulas."; +$text['description-voicemail_mail_to']['ro-ro'] = "Introduceți adresa de e-mail la care se va trimite mesageria vocală (opțional). Mai multe adrese pot fi separate prin virgule."; +$text['description-voicemail_mail_to']['ru-ru'] = "Введите адрес электронной почты для отправки голосовой почты (необязательно). Несколько адресов можно разделять запятыми."; +$text['description-voicemail_mail_to']['sv-se'] = "Ange e-postadressen som röstbrevet ska skickas till (valfritt). Flera adresser kan separeras med kommatecken."; +$text['description-voicemail_mail_to']['uk-ua'] = "Введіть адресу електронної пошти для надсилання голосової пошти (необов’язково). Декілька адрес можна розділити комами."; +$text['description-voicemail_mail_to']['tr-tr'] = "Sesli mesajın gönderileceği e-posta adresini girin (isteğe bağlı). Birden fazla adres virgülle ayrılabilir."; +$text['description-voicemail_mail_to']['zh-cn'] = "输入要发送语音邮件的电子邮件地址(可选)。多个地址可用逗号分隔。"; +$text['description-voicemail_mail_to']['ja-jp'] = "ボイスメールを送信するメールアドレスを入力してください(オプション)。複数のアドレスはコンマで区切ることができます。"; +$text['description-voicemail_mail_to']['ko-kr'] = "보이스메일을 보낼 이메일 주소를 입력하세요(선택 사항). 여러 개의 주소는 쉼표로 구분할 수 있습니다."; $text['description-voicemail_local_after_email']['en-us'] = "Choose whether to keep the voicemail in the system after sending the email notification."; $text['description-voicemail_local_after_email']['en-gb'] = "Choose whether to keep the voicemail in the system after sending the email notification."; diff --git a/app/voicemails/app_languages.php b/app/voicemails/app_languages.php index 6c0ec4839a..0b1f9520e6 100644 --- a/app/voicemails/app_languages.php +++ b/app/voicemails/app_languages.php @@ -1755,32 +1755,32 @@ $text['description-voicemail_alternate_greet_id']['zh-cn'] = "默认问候语中 $text['description-voicemail_alternate_greet_id']['ja-jp'] = "デフォルトのグリーティングで使用される代替グリーティング ID。"; $text['description-voicemail_alternate_greet_id']['ko-kr'] = "기본 인사말에 사용되는 대체 인사말 ID입니다."; -$text['description-voicemail_mail_to']['en-us'] = "Enter the email address to send voicemail to. Multiple addresses may be separated by commas."; -$text['description-voicemail_mail_to']['en-gb'] = "Enter the email address to send voicemail to. Multiple addresses may be separated by commas."; -$text['description-voicemail_mail_to']['ar-eg'] = "أدخل عنوان البريد الإلكتروني لإرسال بريد صوتي إليه. يمكن فصل العناوين المتعددة بفاصلات."; -$text['description-voicemail_mail_to']['de-at'] = "Geben Sie die Email Adresse an, an die Ihre Mailbox Nachricht gesendet werden soll (optional)."; -$text['description-voicemail_mail_to']['de-ch'] = "Geben Sie die Email Adresse an, an die Ihre Mailbox Nachricht gesendet werden soll (optional)."; -$text['description-voicemail_mail_to']['de-de'] = "Geben Sie die Email Adresse an, an die Ihre Mailbox Nachricht gesendet werden soll (optional)."; -$text['description-voicemail_mail_to']['el-gr'] = "Εισαγάγετε τη διεύθυνση email στην οποία θα στείλετε αυτόματο τηλεφωνητή. Πολλές διευθύνσεις μπορούν να διαχωριστούν με κόμμα."; -$text['description-voicemail_mail_to']['es-cl'] = "Ingrese las direcciones de correo a quien desee enviar el correo de voz."; -$text['description-voicemail_mail_to']['es-mx'] = "Ingrese las direcciones de correo a quien desee enviar el correo de voz."; -$text['description-voicemail_mail_to']['fr-ca'] = "Saisissez l'adresse e-mail à laquelle envoyer le message vocal. Plusieurs adresses peuvent être séparées par des virgules."; -$text['description-voicemail_mail_to']['fr-fr'] = "Saisissez l'adresse e-mail à laquelle envoyer le message vocal. Plusieurs adresses peuvent être séparées par des virgules."; -$text['description-voicemail_mail_to']['he-il'] = "הזן את כתובת הדואר האלקטרוני שאליה יש לשלוח דואר קולי. כתובות מרובות עשויות להיות מופרדות בפסיקים."; -$text['description-voicemail_mail_to']['it-it'] = "Inserire l'indirizzo email a cui spedire i messaggi vocali."; -$text['description-voicemail_mail_to']['ka-ge'] = "შეიყვანეთ ელფოსტის მისამართი, სადაც ხმოვანი ფოსტა გაიგზავნება. ერთზე მეტი მისამართი მძიმით უნდა გამოჰყოთ."; -$text['description-voicemail_mail_to']['nl-nl'] = "Voer het E-mail adres om de boodschap naar te sturen."; -$text['description-voicemail_mail_to']['pl-pl'] = "Dodaj adres email na który będą wysyłane pliki poczty głosowej"; -$text['description-voicemail_mail_to']['pt-br'] = "Insira o endereço de email para enviar o correio de voz (opcional)"; -$text['description-voicemail_mail_to']['pt-pt'] = "Introduza o endereço de email para enviar o correio de voz."; -$text['description-voicemail_mail_to']['ro-ro'] = "Introduceți adresa de e-mail la care trimiteți mesajul vocal. Adresele multiple pot fi separate prin virgule."; -$text['description-voicemail_mail_to']['ru-ru'] = "Введите адрес электронной почты для отправки голосовой почты."; -$text['description-voicemail_mail_to']['sv-se'] = "Ange E-post adressen dit meddelande skall skickas."; -$text['description-voicemail_mail_to']['uk-ua'] = "Введіть адресу E-Mail на яку надіслати голосове повідомлення"; -$text['description-voicemail_mail_to']['tr-tr'] = "Sesli mesajın gönderileceği e-posta adresini girin. Birden fazla adres virgülle ayrılabilir."; -$text['description-voicemail_mail_to']['zh-cn'] = "输入要向其发送语音邮件的电子邮件地址。 多个地址可以用逗号分隔。"; -$text['description-voicemail_mail_to']['ja-jp'] = "ボイスメールの送信先の電子メール アドレスを入力します。 複数のアドレスはカンマで区切ることができます。"; -$text['description-voicemail_mail_to']['ko-kr'] = "음성 메일을 보낼 이메일 주소를 입력합니다. 여러 주소는 쉼표로 구분할 수 있습니다."; +$text['description-voicemail_mail_to']['en-us'] = "Enter the email address to send voicemail to (optional). Multiple addresses may be separated by commas."; +$text['description-voicemail_mail_to']['en-gb'] = "Enter the email address to send voicemail to (optional). Multiple addresses may be separated by commas."; +$text['description-voicemail_mail_to']['ar-eg'] = "أدخل عنوان البريد الإلكتروني لإرسال البريد الصوتي إليه (اختياري). يمكن فصل العناوين المتعددة بفواصل."; +$text['description-voicemail_mail_to']['de-at'] = "Geben Sie die E-Mail-Adresse ein, an die die Voicemail gesendet werden soll (optional). Mehrere Adressen können durch Kommas getrennt werden."; +$text['description-voicemail_mail_to']['de-ch'] = "Geben Sie die E-Mail-Adresse ein, an die die Voicemail gesendet werden soll (optional). Mehrere Adressen können durch Kommas getrennt werden."; +$text['description-voicemail_mail_to']['de-de'] = "Geben Sie die E-Mail-Adresse ein, an die die Voicemail gesendet werden soll (optional). Mehrere Adressen können durch Kommas getrennt werden."; +$text['description-voicemail_mail_to']['el-gr'] = "Εισαγάγετε τη διεύθυνση email για αποστολή του φωνητικού μηνύματος (προαιρετικό). Πολλαπλές διευθύνσεις μπορούν να διαχωριστούν με κόμματα."; +$text['description-voicemail_mail_to']['es-cl'] = "Ingrese la dirección de correo electrónico para enviar el correo de voz (opcional). Se pueden separar múltiples direcciones con comas."; +$text['description-voicemail_mail_to']['es-mx'] = "Ingrese la dirección de correo electrónico para enviar el correo de voz (opcional). Se pueden separar múltiples direcciones con comas."; +$text['description-voicemail_mail_to']['fr-ca'] = "Entrez l'adresse e-mail à laquelle envoyer la messagerie vocale (facultatif). Plusieurs adresses peuvent être séparées par des virgules."; +$text['description-voicemail_mail_to']['fr-fr'] = "Entrez l'adresse e-mail à laquelle envoyer la messagerie vocale (facultatif). Plusieurs adresses peuvent être séparées par des virgules."; +$text['description-voicemail_mail_to']['he-il'] = "הזן את כתובת האימייל לשליחת הדואר הקולי (אופציונלי). ניתן להפריד בין כתובות מרובות באמצעות פסיקים."; +$text['description-voicemail_mail_to']['it-it'] = "Inserisci l'indirizzo email a cui inviare la segreteria telefonica (opzionale). Più indirizzi possono essere separati da virgole."; +$text['description-voicemail_mail_to']['ka-ge'] = "შეიყვანეთ ელ.ფოსტის მისამართი, რომელზეც გაიგზავნება ხმოვანი ფოსტა (არასავალდებულო). შესაძლებელია მრავალი მისამართის მძიმით გამოყოფა."; +$text['description-voicemail_mail_to']['nl-nl'] = "Voer het e-mailadres in om de voicemail naartoe te sturen (optioneel). Meerdere adressen kunnen worden gescheiden door komma's."; +$text['description-voicemail_mail_to']['pl-pl'] = "Wprowadź adres e-mail, na który ma zostać wysłana poczta głosowa (opcjonalnie). Wiele adresów można oddzielić przecinkami."; +$text['description-voicemail_mail_to']['pt-br'] = "Digite o endereço de e-mail para enviar o correio de voz (opcional). Vários endereços podem ser separados por vírgulas."; +$text['description-voicemail_mail_to']['pt-pt'] = "Digite o endereço de e-mail para enviar o correio de voz (opcional). Vários endereços podem ser separados por vírgulas."; +$text['description-voicemail_mail_to']['ro-ro'] = "Introduceți adresa de e-mail la care se va trimite mesageria vocală (opțional). Mai multe adrese pot fi separate prin virgule."; +$text['description-voicemail_mail_to']['ru-ru'] = "Введите адрес электронной почты для отправки голосовой почты (необязательно). Несколько адресов можно разделять запятыми."; +$text['description-voicemail_mail_to']['sv-se'] = "Ange e-postadressen som röstbrevet ska skickas till (valfritt). Flera adresser kan separeras med kommatecken."; +$text['description-voicemail_mail_to']['uk-ua'] = "Введіть адресу електронної пошти для надсилання голосової пошти (необов’язково). Декілька адрес можна розділити комами."; +$text['description-voicemail_mail_to']['tr-tr'] = "Sesli mesajın gönderileceği e-posta adresini girin (isteğe bağlı). Birden fazla adres virgülle ayrılabilir."; +$text['description-voicemail_mail_to']['zh-cn'] = "输入要发送语音邮件的电子邮件地址(可选)。多个地址可用逗号分隔。"; +$text['description-voicemail_mail_to']['ja-jp'] = "ボイスメールを送信するメールアドレスを入力してください(オプション)。複数のアドレスはコンマで区切ることができます。"; +$text['description-voicemail_mail_to']['ko-kr'] = "보이스메일을 보낼 이메일 주소를 입력하세요(선택 사항). 여러 개의 주소는 쉼표로 구분할 수 있습니다."; $text['description-voicemail_local_after_email']['en-us'] = "Choose whether to keep the voicemail in the system after sending the email notification."; $text['description-voicemail_local_after_email']['en-gb'] = "Choose whether to keep the voicemail in the system after sending the email notification."; From d529021b3fd2e51c8958e9d04d1733f7e5577554 Mon Sep 17 00:00:00 2001 From: frytimo Date: Tue, 4 Mar 2025 14:25:47 -0400 Subject: [PATCH 147/196] Use boolean setting as true boolean (#7284) * use boolean setting as true boolean * Update settings class to use the php filter_var function for boolean Using the built-in filter type for boolean seems like a better option as they are faster, already hardened, and more widely tested. I found this better method used originally by Mark J. Crane in 2022 in the content.php page so I included it here. * Update settings class to use the php filter_var function for boolean Using the built-in filter type for boolean seems like a better option as they are faster, already hardened, and more widely tested. I found this better method used originally by Mark J. Crane in 2022 in the content.php page so I included it here. --- .../resources/content.php | 4 +- app/bridges/bridges.php | 6 +-- app/call_block/call_block.php | 6 +-- app/call_broadcast/call_broadcast.php | 6 +-- app/call_centers/call_center_agents.php | 6 +-- app/call_centers/call_center_queues.php | 6 +-- app/call_centers/waveform.php | 4 +- app/call_flows/call_flows.php | 6 +-- app/call_flows/waveform.php | 4 +- app/call_forward/call_forward.php | 6 +-- app/call_forward/call_forward_edit.php | 6 +-- .../resources/classes/call_forward.php | 2 +- .../resources/classes/do_not_disturb.php | 2 +- .../resources/classes/follow_me.php | 2 +- app/call_recordings/waveform.php | 4 +- app/conference_centers/conference_centers.php | 6 +-- app/conference_centers/conference_rooms.php | 6 +-- .../conference_session_details.php | 6 +-- .../conference_sessions.php | 6 +-- app/conference_centers/waveform.php | 4 +- .../conference_control_details.php | 6 +-- .../conference_controls.php | 6 +-- .../conference_profile_params.php | 6 +-- .../conference_profiles.php | 6 +-- app/conferences/conferences.php | 6 +-- .../conferences_active_inc.php | 2 +- .../database_transactions.php | 6 +-- app/destinations/destination_imports.php | 2 +- app/destinations/destinations.php | 8 ++-- app/devices/device_profiles.php | 4 +- app/devices/device_vendor_functions.php | 4 +- app/devices/device_vendors.php | 4 +- app/dialplans/dialplan_xml.php | 6 +-- app/dialplans/dialplans.php | 22 +++++------ app/email_queue/email_queue.php | 4 +- app/email_queue/email_queue_edit.php | 8 ++-- app/event_guard/event_guard_logs.php | 4 +- app/extension_settings/extension_settings.php | 6 +-- app/extensions/extensions.php | 4 +- app/fax/fax.php | 4 +- app/fax/fax_logs.php | 4 +- app/gateways/gateways.php | 8 ++-- app/ivr_menus/ivr_menu_edit.php | 2 +- app/ivr_menus/ivr_menus.php | 6 +-- app/ivr_menus/waveform.php | 4 +- app/modules/modules.php | 6 +-- app/music_on_hold/waveform.php | 4 +- .../number_translations.php | 6 +-- app/phrases/phrases.php | 4 +- app/pin_numbers/pin_numbers.php | 4 +- app/recordings/waveform.php | 4 +- app/registrations/registrations.php | 6 +-- app/ring_groups/ring_groups.php | 4 +- app/ring_groups/waveform.php | 4 +- app/sip_profiles/sip_profiles.php | 6 +-- .../sofia_global_settings.php | 6 +-- app/streams/streams.php | 4 +- .../resources/dashboard/system_counts.php | 4 +- app/system/system.php | 6 +-- app/time_conditions/time_conditions.php | 4 +- app/vars/vars.php | 6 +-- .../voicemail_greetings.php | 4 +- app/voicemail_greetings/waveform.php | 4 +- app/voicemails/voicemail_edit.php | 16 ++++---- app/voicemails/waveform.php | 4 +- app/xml_cdr/resources/classes/xml_cdr.php | 2 +- .../resources/dashboard/missed_calls.php | 4 +- .../resources/dashboard/recent_calls.php | 4 +- app/xml_cdr/waveform.php | 4 +- app/xml_cdr/xml_cdr_inc.php | 2 +- core/contacts/contact_addresses.php | 2 +- core/contacts/contact_attachments.php | 2 +- core/contacts/contact_edit.php | 4 +- core/contacts/contact_emails.php | 6 +-- core/contacts/contact_extensions.php | 6 +-- core/contacts/contact_phones.php | 4 +- core/contacts/contact_relations.php | 6 +-- core/contacts/contact_settings.php | 6 +-- core/contacts/contact_times.php | 6 +-- core/contacts/contact_urls.php | 4 +- core/contacts/contacts.php | 6 +-- core/dashboard/dashboard.php | 4 +- core/databases/databases.php | 6 +-- core/default_settings/default_settings.php | 6 +-- core/domain_settings/domain_settings.php | 6 +-- core/domains/domains.php | 6 +-- core/email_templates/email_template_edit.php | 6 +-- core/email_templates/email_templates.php | 6 +-- core/groups/groups.php | 6 +-- core/menu/menu.php | 8 ++-- core/menu/menu_item_list.php | 8 ++-- core/user_settings/user_settings.php | 6 +-- core/users/user_edit.php | 8 ++-- core/users/users.php | 6 +-- logout.php | 2 +- resources/classes/settings.php | 38 ++----------------- resources/footer.php | 4 +- resources/php.php | 2 +- themes/default/css.php | 18 ++++----- 99 files changed, 265 insertions(+), 295 deletions(-) diff --git a/app/basic_operator_panel/resources/content.php b/app/basic_operator_panel/resources/content.php index 341a59e444..db831c2a64 100644 --- a/app/basic_operator_panel/resources/content.php +++ b/app/basic_operator_panel/resources/content.php @@ -353,7 +353,7 @@ if (is_array($activity)) { } else { //unregistered extension - if (!empty($_SESSION['operator_panel']['show_unregistered']['boolean']) && $_SESSION['operator_panel']['show_unregistered']['boolean'] == 'true') { + if (filter_var($_SESSION['operator_panel']['show_unregistered']['boolean'] ?? false, FILTER_VALIDATE_BOOL)) { $css_class = "ur_ext"; } else { @@ -551,7 +551,7 @@ if (is_array($activity)) { if (in_array($extension, $_SESSION['user']['extensions'])) { $user_extensions[] = $block; - } elseif (!empty($ext['call_group']) && filter_var($_SESSION['operator_panel']['group_extensions']['boolean'], FILTER_VALIDATE_BOOLEAN)) { + } elseif (!empty($ext['call_group']) && filter_var($_SESSION['operator_panel']['group_extensions']['boolean'] ?? false, FILTER_VALIDATE_BOOLEAN)) { $grouped_extensions[$ext['call_group']][] = $block; } else { $other_extensions[] = $block; diff --git a/app/bridges/bridges.php b/app/bridges/bridges.php index 95cf85dcef..0b263b3e60 100644 --- a/app/bridges/bridges.php +++ b/app/bridges/bridges.php @@ -47,7 +47,7 @@ $show = $_GET["show"] ?? ''; //set from session variables - $list_row_edit_button = !empty($_SESSION['theme']['list_row_edit_button']['boolean']) ? $_SESSION['theme']['list_row_edit_button']['boolean'] : 'false'; + $list_row_edit_button = filter_var($_SESSION['theme']['list_row_edit_button']['boolean'] ?? false, FILTER_VALIDATE_BOOL); //get the http post data if (!empty($_POST['bridges'])) { @@ -226,7 +226,7 @@ echo th_order_by('bridge_destination', $text['label-bridge_destination'], $order_by, $order); echo th_order_by('bridge_enabled', $text['label-bridge_enabled'], $order_by, $order, null, "class='center'"); echo " ".$text['label-bridge_description']." 
".escape($row['bridge_description'])."\n"; echo button::create(['type'=>'button','title'=>$text['button-edit'],'icon'=>$_SESSION['theme']['button_icon_edit'],'link'=>$list_row_url]); echo " ".$text['label-description']." 
".$row['date_formatted']." ".$row['time_formatted']."".escape($row['call_block_description']).""; echo button::create(['type'=>'button','title'=>$text['button-edit'],'icon'=>$_SESSION['theme']['button_icon_edit'],'link'=>$list_row_url]); echo "  
".escape($broadcast_start_time ?? '')."".escape($row['broadcast_description']).""; echo button::create(['type'=>'button','title'=>$text['button-edit'],'icon'=>$_SESSION['theme']['button_icon_edit'],'link'=>$list_row_url]); echo "  
".$row[agent_wrap_up_time]."".$row[agent_reject_delay_time]."".$row[agent_busy_delay_time].""; echo button::create(['type'=>'button','title'=>$text['button-edit'],'icon'=>$_SESSION['theme']['button_icon_edit'],'link'=>$list_row_url]); echo "  
".escape($row[queue_abandoned_resume_allowed])." ".escape($row[queue_tier_rule_wait_multiply_level])." ".escape($row['queue_description']).""; echo button::create(['type'=>'button','title'=>$text['button-edit'],'icon'=>$_SESSION['theme']['button_icon_edit'],'link'=>$list_row_url]); echo "  
".escape($row['call_flow_description'])." "; echo button::create(['type'=>'button','title'=>$text['button-edit'],'icon'=>$_SESSION['theme']['button_icon_edit'],'link'=>$list_row_url]); echo " " . $text['label-dnd'] . "" . $text['label-description'] . " 
" . escape($row['description']) . " "; echo button::create(['type' => 'button', 'title' => $text['button-edit'], 'icon' => $_SESSION['theme']['button_icon_edit'], 'link' => $list_row_url]); echo " \n"; - require_once "app/music_on_hold/resources/classes/switch_music_on_hold.php"; $options = ''; $moh = new switch_music_on_hold; echo $moh->select('hold_music', $hold_music ?? '', $options); diff --git a/app/extensions/resources/classes/extension.php b/app/extensions/resources/classes/extension.php index 8a8eab1afa..53d0f9f90a 100644 --- a/app/extensions/resources/classes/extension.php +++ b/app/extensions/resources/classes/extension.php @@ -25,7 +25,6 @@ */ //define the directory class -if (!class_exists('extension')) { class extension { /** @@ -795,6 +794,3 @@ if (!class_exists('extension')) { } } -} - -?> diff --git a/app/fax/fax_emails.php b/app/fax/fax_emails.php index a22080e67c..8a52178671 100644 --- a/app/fax/fax_emails.php +++ b/app/fax/fax_emails.php @@ -29,7 +29,6 @@ require_once dirname(__DIR__, 2) . "/resources/require.php"; require_once "resources/functions/object_to_array.php"; require_once "resources/functions/parse_message.php"; -require_once "resources/classes/text.php"; //get accounts to monitor $sql = "select d.domain_name, f.* "; diff --git a/app/fax/resources/classes/fax.php b/app/fax/resources/classes/fax.php index d3b6b8748d..e1a24157ce 100644 --- a/app/fax/resources/classes/fax.php +++ b/app/fax/resources/classes/fax.php @@ -25,7 +25,6 @@ */ //define the fax class -if (!class_exists('fax')) { class fax { /** @@ -725,7 +724,6 @@ if (!class_exists('fax')) { } } //class -} /* $o = new fax; @@ -738,5 +736,3 @@ $c->destination_number = $fax_destination_number; $c->fax_description = $fax_description; $c->dialplan(); */ - -?> \ No newline at end of file diff --git a/app/fax_queue/resources/classes/fax_queue.php b/app/fax_queue/resources/classes/fax_queue.php index f5d2897ef1..0f2378a066 100644 --- a/app/fax_queue/resources/classes/fax_queue.php +++ b/app/fax_queue/resources/classes/fax_queue.php @@ -26,12 +26,7 @@ /** * fax_queue class - * - * @method null delete - * @method null toggle - * @method null copy */ -if (!class_exists('fax_queue')) { class fax_queue { /** @@ -274,6 +269,3 @@ if (!class_exists('fax_queue')) { } } } -} - -?> diff --git a/app/fax_queue/resources/service/fax_queue.php b/app/fax_queue/resources/service/fax_queue.php index 6084254ebf..db9eb1e654 100644 --- a/app/fax_queue/resources/service/fax_queue.php +++ b/app/fax_queue/resources/service/fax_queue.php @@ -8,7 +8,6 @@ //includes files require_once dirname(__DIR__, 4) . "/resources/require.php"; require_once "resources/pdo.php"; - include "resources/classes/permissions.php"; //increase limits set_time_limit(0); diff --git a/app/fifo/resources/classes/fifo.php b/app/fifo/resources/classes/fifo.php index 4338f3f48e..450f5cd4c3 100644 --- a/app/fifo/resources/classes/fifo.php +++ b/app/fifo/resources/classes/fifo.php @@ -2,12 +2,7 @@ /** * fifo class - * - * @method null delete - * @method null toggle - * @method null copy */ -if (!class_exists('fifo')) { class fifo { /** @@ -283,6 +278,3 @@ if (!class_exists('fifo')) { } } -} - -?> \ No newline at end of file diff --git a/app/gateways/resources/classes/gateways.php b/app/gateways/resources/classes/gateways.php index cbfba52633..83ab122ad9 100644 --- a/app/gateways/resources/classes/gateways.php +++ b/app/gateways/resources/classes/gateways.php @@ -25,7 +25,6 @@ */ //define the gateways class -if (!class_exists('gateways')) { class gateways { /** @@ -583,6 +582,3 @@ if (!class_exists('gateways')) { } } -} - -?> \ No newline at end of file diff --git a/app/ivr_menus/resources/classes/ivr_menu.php b/app/ivr_menus/resources/classes/ivr_menu.php index 50a0fde239..2d91d84c15 100644 --- a/app/ivr_menus/resources/classes/ivr_menu.php +++ b/app/ivr_menus/resources/classes/ivr_menu.php @@ -25,7 +25,6 @@ */ //define the ivr_menu class -if (!class_exists('ivr_menu')) { class ivr_menu { /** @@ -489,6 +488,3 @@ if (!class_exists('ivr_menu')) { } } -} - -?> diff --git a/app/ivr_menus/waveform.php b/app/ivr_menus/waveform.php index 0c93872262..8b760cd949 100644 --- a/app/ivr_menus/waveform.php +++ b/app/ivr_menus/waveform.php @@ -27,7 +27,6 @@ //includes files require_once dirname(__DIR__, 2) . "/resources/require.php"; require_once "resources/check_auth.php"; - require_once "resources/classes/waveform.php"; use maximal\audio\Waveform; diff --git a/app/modules/resources/classes/modules.php b/app/modules/resources/classes/modules.php index 28b83949e0..8559b657b4 100644 --- a/app/modules/resources/classes/modules.php +++ b/app/modules/resources/classes/modules.php @@ -25,7 +25,6 @@ */ //define the modules class -if (!class_exists('modules')) { class modules { /** @@ -1101,10 +1100,8 @@ if (!class_exists('modules')) { } //class -} /* -require_once "resources/classes/modules.php"; $mod = new modules; $mod->dir = $_SESSION['switch']['mod']['dir']; echo $mod->dir."\n"; @@ -1138,5 +1135,3 @@ echo $mod->dir."\n"; //print_r($result); //echo "\n"; */ - -?> diff --git a/app/music_on_hold/music_on_hold.php b/app/music_on_hold/music_on_hold.php index 95c4443a81..ae92335afb 100644 --- a/app/music_on_hold/music_on_hold.php +++ b/app/music_on_hold/music_on_hold.php @@ -308,7 +308,6 @@ $cache = new cache; $cache->delete("configuration:local_stream.conf"); - //require_once "app/music_on_hold/resources/classes/switch_music_on_hold.php"; $music = new switch_music_on_hold; $music->reload(); diff --git a/app/music_on_hold/resources/classes/switch_music_on_hold.php b/app/music_on_hold/resources/classes/switch_music_on_hold.php index 71d628eca2..55d90e86b1 100644 --- a/app/music_on_hold/resources/classes/switch_music_on_hold.php +++ b/app/music_on_hold/resources/classes/switch_music_on_hold.php @@ -27,7 +27,6 @@ */ //define the switch_music_on_hold class -if (!class_exists('switch_music_on_hold')) { class switch_music_on_hold { /** @@ -85,7 +84,6 @@ if (!class_exists('switch_music_on_hold')) { } //recordings if (is_dir($_SERVER["PROJECT_ROOT"].'/app/recordings')) { - require_once "app/recordings/resources/classes/switch_recordings.php"; $recordings_c = new switch_recordings; $recordings = $recordings_c->list_recordings(); if (is_array($recordings) && sizeof($recordings) > 0) { @@ -447,12 +445,9 @@ if (!class_exists('switch_music_on_hold')) { } //method } //class -} + //build and save the XML - //require_once "app/music_on_hold/resources/classes/switch_music_on_hold.php"; //$moh = new switch_music_on_hold; //$moh->xml(); //$moh->save(); - -?> \ No newline at end of file diff --git a/app/music_on_hold/waveform.php b/app/music_on_hold/waveform.php index 68087e5dde..47fafbd10c 100644 --- a/app/music_on_hold/waveform.php +++ b/app/music_on_hold/waveform.php @@ -27,7 +27,6 @@ //includes files require_once dirname(__DIR__, 2) . "/resources/require.php"; require_once "resources/check_auth.php"; - require_once "resources/classes/waveform.php"; use maximal\audio\Waveform; diff --git a/app/number_translations/resources/classes/number_translations.php b/app/number_translations/resources/classes/number_translations.php index 22a2836401..c0abf97057 100644 --- a/app/number_translations/resources/classes/number_translations.php +++ b/app/number_translations/resources/classes/number_translations.php @@ -25,7 +25,6 @@ */ //define the number translations class -if (!class_exists('number_translations')) { class number_translations { /** @@ -414,11 +413,8 @@ if (!class_exists('number_translations')) { } //method } //class -} /* $obj = new number_translations; $obj->delete(); */ - -?> \ No newline at end of file diff --git a/app/phrases/resources/classes/phrases.php b/app/phrases/resources/classes/phrases.php index 2ed6f0f893..8fa677fe8a 100644 --- a/app/phrases/resources/classes/phrases.php +++ b/app/phrases/resources/classes/phrases.php @@ -25,7 +25,6 @@ */ //define the phrases class -if (!class_exists('phrases')) { class phrases { /** @@ -431,6 +430,3 @@ if (!class_exists('phrases')) { } //method } //class -} - -?> \ No newline at end of file diff --git a/app/pin_numbers/resources/classes/pin_numbers.php b/app/pin_numbers/resources/classes/pin_numbers.php index c0be87493e..817f21caab 100644 --- a/app/pin_numbers/resources/classes/pin_numbers.php +++ b/app/pin_numbers/resources/classes/pin_numbers.php @@ -25,7 +25,6 @@ */ //define the pin numbers class -if (!class_exists('pin_numbers')) { class pin_numbers { /** @@ -245,6 +244,3 @@ if (!class_exists('pin_numbers')) { } } -} - -?> \ No newline at end of file diff --git a/app/recordings/resources/classes/switch_recordings.php b/app/recordings/resources/classes/switch_recordings.php index dc3988ef67..f50fa1e80e 100644 --- a/app/recordings/resources/classes/switch_recordings.php +++ b/app/recordings/resources/classes/switch_recordings.php @@ -26,7 +26,6 @@ */ //define the switch_recordings class -if (!class_exists('switch_recordings')) { class switch_recordings { /** @@ -158,6 +157,3 @@ if (!class_exists('switch_recordings')) { } //method } //class -} - -?> diff --git a/app/recordings/waveform.php b/app/recordings/waveform.php index f5136b2927..07a15a5555 100644 --- a/app/recordings/waveform.php +++ b/app/recordings/waveform.php @@ -27,7 +27,6 @@ //includes files require_once dirname(__DIR__, 2) . "/resources/require.php"; require_once "resources/check_auth.php"; - require_once "resources/classes/waveform.php"; use maximal\audio\Waveform; diff --git a/app/registrations/registrations.php b/app/registrations/registrations.php index 8840050198..18720eb38d 100644 --- a/app/registrations/registrations.php +++ b/app/registrations/registrations.php @@ -88,7 +88,6 @@ $registrations = $obj->get($profile ?? null); //order the array - require_once "resources/classes/array_order.php"; $order = new array_order(); $registrations = $order->sort($registrations, 'sip-auth-realm', 'user'); diff --git a/app/ring_groups/resources/classes/ring_groups.php b/app/ring_groups/resources/classes/ring_groups.php index ceab17b711..5a9786e256 100644 --- a/app/ring_groups/resources/classes/ring_groups.php +++ b/app/ring_groups/resources/classes/ring_groups.php @@ -25,7 +25,6 @@ */ //define the ring groups class -if (!class_exists('ring_groups')) { class ring_groups { /** @@ -512,6 +511,3 @@ if (!class_exists('ring_groups')) { } } -} - -?> diff --git a/app/ring_groups/waveform.php b/app/ring_groups/waveform.php index 0c93872262..8b760cd949 100644 --- a/app/ring_groups/waveform.php +++ b/app/ring_groups/waveform.php @@ -27,7 +27,6 @@ //includes files require_once dirname(__DIR__, 2) . "/resources/require.php"; require_once "resources/check_auth.php"; - require_once "resources/classes/waveform.php"; use maximal\audio\Waveform; diff --git a/app/sip_profiles/resources/classes/sip_profiles.php b/app/sip_profiles/resources/classes/sip_profiles.php index 5d90bb5de8..2ab414a2c3 100644 --- a/app/sip_profiles/resources/classes/sip_profiles.php +++ b/app/sip_profiles/resources/classes/sip_profiles.php @@ -25,7 +25,6 @@ */ //define the sip profiles class -if (!class_exists('sip_profiles')) { class sip_profiles { /** @@ -434,6 +433,3 @@ if (!class_exists('sip_profiles')) { } } -} - -?> \ No newline at end of file diff --git a/app/sofia_global_settings/resources/classes/sofia_global_settings.php b/app/sofia_global_settings/resources/classes/sofia_global_settings.php index 289efda183..f9a1c838b3 100644 --- a/app/sofia_global_settings/resources/classes/sofia_global_settings.php +++ b/app/sofia_global_settings/resources/classes/sofia_global_settings.php @@ -26,12 +26,7 @@ /** * sofia_global_settings class - * - * @method null delete - * @method null toggle - * @method null copy */ -if (!class_exists('sofia_global_settings')) { class sofia_global_settings { /** @@ -247,6 +242,3 @@ if (!class_exists('sofia_global_settings')) { } } -} - -?> \ No newline at end of file diff --git a/app/streams/resources/classes/streams.php b/app/streams/resources/classes/streams.php index 05340cdfee..2256892d8f 100644 --- a/app/streams/resources/classes/streams.php +++ b/app/streams/resources/classes/streams.php @@ -25,7 +25,6 @@ */ //define the streams class -if (!class_exists('streams')) { class streams { /** @@ -244,6 +243,3 @@ if (!class_exists('streams')) { } } -} - -?> \ No newline at end of file diff --git a/app/switch/resources/classes/presence.php b/app/switch/resources/classes/presence.php index b455c24a6d..c645f8eac4 100644 --- a/app/switch/resources/classes/presence.php +++ b/app/switch/resources/classes/presence.php @@ -23,12 +23,7 @@ /** * presence class - * - * @method boolean active - * @method array show */ - -if (!class_exists('presence')) { class presence { /** @@ -84,7 +79,6 @@ if (!class_exists('presence')) { return $array; } } -} //examples /* @@ -97,11 +91,9 @@ if (!class_exists('presence')) { echo "active: true\n"; } else { - echo "active: false\n"; + echo "active: false\n"; } //show active the presence $presence = new presence; $array = $presence->show(); */ - -?> diff --git a/app/switch/resources/classes/ringbacks.php b/app/switch/resources/classes/ringbacks.php index db05aeb98a..d206eac70b 100644 --- a/app/switch/resources/classes/ringbacks.php +++ b/app/switch/resources/classes/ringbacks.php @@ -25,7 +25,6 @@ Matthew Vale */ -if (!class_exists('ringbacks')) { class ringbacks { //define variables @@ -85,18 +84,15 @@ if (!class_exists('ringbacks')) { */ //get the tones - require_once "resources/classes/tones.php"; $tones = new tones; $this->tones_list = $tones->tones_list(); //get music on hold and recordings if (is_dir($_SERVER["PROJECT_ROOT"].'/app/music_on_hold')) { - require_once "app/music_on_hold/resources/classes/switch_music_on_hold.php"; $music = new switch_music_on_hold; $this->music_list = $music->get(); } if (is_dir($_SERVER["PROJECT_ROOT"].'/app/recordings')) { - require_once "app/recordings/resources/classes/switch_recordings.php"; $recordings = new switch_recordings; $this->recordings_list = $recordings->list_recordings(); } @@ -232,6 +228,3 @@ if (!class_exists('ringbacks')) { return $select; } } -} - -?> diff --git a/app/switch/resources/classes/switch_files.php b/app/switch/resources/classes/switch_files.php index 80b1b24436..c98091a624 100644 --- a/app/switch/resources/classes/switch_files.php +++ b/app/switch/resources/classes/switch_files.php @@ -26,12 +26,7 @@ /** * switch class provides methods for copying switch_files - * - * @method string correct_path - * @method string copy_scripts - * @method string copy_languages */ -if (!class_exists('switch_files')) { class switch_files { /** @@ -158,7 +153,6 @@ if (!class_exists('switch_files')) { } } -} /* //example use @@ -168,5 +162,3 @@ if (!class_exists('switch_files')) { $obj->copy_scripts(); $obj->copy_languages(); */ - -?> diff --git a/app/time_conditions/resources/classes/time_conditions.php b/app/time_conditions/resources/classes/time_conditions.php index 98a5e757df..c4be826b78 100644 --- a/app/time_conditions/resources/classes/time_conditions.php +++ b/app/time_conditions/resources/classes/time_conditions.php @@ -25,7 +25,6 @@ */ //define the time conditions class - if (!class_exists('time_conditions')) { class time_conditions { /** @@ -346,6 +345,3 @@ } //class - } - -?> diff --git a/app/vars/resources/classes/vars.php b/app/vars/resources/classes/vars.php index 3f137327d5..7018b3da36 100644 --- a/app/vars/resources/classes/vars.php +++ b/app/vars/resources/classes/vars.php @@ -25,7 +25,6 @@ */ //define the vars class -if (!class_exists('vars')) { class vars { /** @@ -258,6 +257,3 @@ if (!class_exists('vars')) { } } -} - -?> \ No newline at end of file diff --git a/app/voicemail_greetings/resources/classes/voicemail_greetings.php b/app/voicemail_greetings/resources/classes/voicemail_greetings.php index b8ae36fb28..74b50cd0d2 100644 --- a/app/voicemail_greetings/resources/classes/voicemail_greetings.php +++ b/app/voicemail_greetings/resources/classes/voicemail_greetings.php @@ -25,7 +25,6 @@ */ //define the voicemail greetings class -if (!class_exists('voicemail_greetings')) { class voicemail_greetings { /** @@ -166,6 +165,3 @@ if (!class_exists('voicemail_greetings')) { } //method } //class -} - -?> \ No newline at end of file diff --git a/app/voicemail_greetings/waveform.php b/app/voicemail_greetings/waveform.php index 59e8032d78..78325752ef 100644 --- a/app/voicemail_greetings/waveform.php +++ b/app/voicemail_greetings/waveform.php @@ -27,7 +27,6 @@ //includes files require_once dirname(__DIR__, 2) . "/resources/require.php"; require_once "resources/check_auth.php"; - require_once "resources/classes/waveform.php"; use maximal\audio\Waveform; diff --git a/app/voicemails/resources/classes/voicemail.php b/app/voicemails/resources/classes/voicemail.php index 771d07ed97..cfeca41e78 100644 --- a/app/voicemails/resources/classes/voicemail.php +++ b/app/voicemails/resources/classes/voicemail.php @@ -1581,7 +1581,6 @@ } //example voicemail messages - //require_once "app/voicemails/resources/classes/voicemail.php"; //$voicemail = new voicemail; //$voicemail->voicemail_uuid = $voicemail_uuid; //$voicemail->order_by = $order_by; diff --git a/app/voicemails/resources/dashboard/voicemails.php b/app/voicemails/resources/dashboard/voicemails.php index a8e88448c4..6f062a54ca 100644 --- a/app/voicemails/resources/dashboard/voicemails.php +++ b/app/voicemails/resources/dashboard/voicemails.php @@ -23,9 +23,6 @@ //voicemail echo "
\n"; -//required class - require_once "app/voicemails/resources/classes/voicemail.php"; - //get the voicemail $vm = new voicemail; $vm->domain_uuid = $_SESSION['domain_uuid']; diff --git a/app/voicemails/voicemail_message_toggle.php b/app/voicemails/voicemail_message_toggle.php index 46227bbd55..da1afc7c0c 100644 --- a/app/voicemails/voicemail_message_toggle.php +++ b/app/voicemails/voicemail_message_toggle.php @@ -47,7 +47,6 @@ //toggle the voicemail message $toggled = 0; if (is_array($voicemail_messages) && sizeof($voicemail_messages) > 0) { - require_once "resources/classes/voicemail.php"; foreach ($voicemail_messages as $voicemail_uuid => $voicemail_message_uuids) { foreach ($voicemail_message_uuids as $voicemail_message_uuid) { if (is_uuid($voicemail_uuid) && is_uuid($voicemail_message_uuid)) { diff --git a/app/voicemails/waveform.php b/app/voicemails/waveform.php index 645ef6c003..effb3842f5 100644 --- a/app/voicemails/waveform.php +++ b/app/voicemails/waveform.php @@ -27,7 +27,6 @@ //includes files require_once dirname(__DIR__, 2) . "/resources/require.php"; require_once "resources/check_auth.php"; - require_once "resources/classes/waveform.php"; use maximal\audio\Waveform; diff --git a/app/xml_cdr/resources/classes/xml_cdr.php b/app/xml_cdr/resources/classes/xml_cdr.php index 8996ca6e9d..432570f92d 100644 --- a/app/xml_cdr/resources/classes/xml_cdr.php +++ b/app/xml_cdr/resources/classes/xml_cdr.php @@ -26,10 +26,7 @@ /** * xml_cdr class provides methods for adding cdr records to the database - * - * @method boolean add */ -if (!class_exists('xml_cdr')) { class xml_cdr { /** @@ -2370,4 +2367,3 @@ if (!class_exists('xml_cdr')) { } } //class -} diff --git a/app/xml_cdr/waveform.php b/app/xml_cdr/waveform.php index b37c596109..885087ec78 100644 --- a/app/xml_cdr/waveform.php +++ b/app/xml_cdr/waveform.php @@ -27,7 +27,6 @@ //includes files require_once dirname(__DIR__, 2) . "/resources/require.php"; require_once "resources/check_auth.php"; - require_once "resources/classes/waveform.php"; use maximal\audio\Waveform; diff --git a/core/authentication/resources/classes/authentication.php b/core/authentication/resources/classes/authentication.php index 790f319709..9cdc02ebae 100644 --- a/core/authentication/resources/classes/authentication.php +++ b/core/authentication/resources/classes/authentication.php @@ -96,7 +96,6 @@ class authentication { //process the plugin if (file_exists($plugin)) { //run the plugin - include_once $plugin; $object = new $class_name(); $object->domain_name = $this->domain_name; $object->domain_uuid = $this->domain_uuid; diff --git a/core/authentication/resources/classes/plugins/email.php b/core/authentication/resources/classes/plugins/email.php index 900c467b36..aa0bfd4a38 100644 --- a/core/authentication/resources/classes/plugins/email.php +++ b/core/authentication/resources/classes/plugins/email.php @@ -26,8 +26,6 @@ /** * plugin_email - * - * @method email time based one time password authenticate the user */ class plugin_email { @@ -521,5 +519,3 @@ class plugin_email { } } - -?> diff --git a/core/authentication/resources/classes/plugins/ldap.php b/core/authentication/resources/classes/plugins/ldap.php index dfd499602f..de85f39089 100644 --- a/core/authentication/resources/classes/plugins/ldap.php +++ b/core/authentication/resources/classes/plugins/ldap.php @@ -209,5 +209,3 @@ class plugin_ldap { return $result; } } - -?> \ No newline at end of file diff --git a/core/authentication/resources/classes/plugins/totp.php b/core/authentication/resources/classes/plugins/totp.php index 0524335a63..ccf7b8b410 100644 --- a/core/authentication/resources/classes/plugins/totp.php +++ b/core/authentication/resources/classes/plugins/totp.php @@ -439,5 +439,3 @@ class plugin_totp { } } - -?> diff --git a/core/contacts/contacts_vcard.php b/core/contacts/contacts_vcard.php index 59dcb42b97..f9434275df 100644 --- a/core/contacts/contacts_vcard.php +++ b/core/contacts/contacts_vcard.php @@ -42,7 +42,6 @@ if (!empty($_GET)) { $text = $language->get(); //create the vcard object - require_once "resources/classes/vcard.php"; $vcard = new vcard(); //get the contact id diff --git a/core/contacts/resources/classes/contacts.php b/core/contacts/resources/classes/contacts.php index c29f0243a8..cd3de9d6d7 100644 --- a/core/contacts/resources/classes/contacts.php +++ b/core/contacts/resources/classes/contacts.php @@ -25,7 +25,6 @@ */ //define the contacts class -if (!class_exists('contacts')) { class contacts { const APP_NAME = "contacts"; @@ -277,6 +276,3 @@ if (!class_exists('contacts')) { } //method } //class -} - -?> \ No newline at end of file diff --git a/core/dashboard/resources/classes/dashboard.php b/core/dashboard/resources/classes/dashboard.php index 34f973bd95..6ecb1ba8fa 100644 --- a/core/dashboard/resources/classes/dashboard.php +++ b/core/dashboard/resources/classes/dashboard.php @@ -26,12 +26,7 @@ /** * dashboard class - * - * @method null delete - * @method null toggle - * @method null copy */ -if (!class_exists('dashboard')) { class dashboard { /** @@ -247,6 +242,3 @@ if (!class_exists('dashboard')) { } } -} - -?> diff --git a/core/databases/resources/classes/databases.php b/core/databases/resources/classes/databases.php index 8b9edee5e2..0b5a29d78c 100644 --- a/core/databases/resources/classes/databases.php +++ b/core/databases/resources/classes/databases.php @@ -25,7 +25,6 @@ */ //define the databases class -if (!class_exists('databases')) { class databases { /** @@ -169,6 +168,3 @@ if (!class_exists('databases')) { } } -} - -?> \ No newline at end of file diff --git a/core/default_settings/resources/classes/default_settings.php b/core/default_settings/resources/classes/default_settings.php index 499614b5b3..73deb9801d 100644 --- a/core/default_settings/resources/classes/default_settings.php +++ b/core/default_settings/resources/classes/default_settings.php @@ -26,12 +26,7 @@ /** * default_settings class - * - * @method null delete - * @method null toggle - * @method null copy */ -if (!class_exists('default_settings')) { class default_settings { /** @@ -327,6 +322,3 @@ if (!class_exists('default_settings')) { } //method } //class -} - -?> diff --git a/core/domain_settings/resources/classes/domain_settings.php b/core/domain_settings/resources/classes/domain_settings.php index 04a7c66626..b384ab062d 100644 --- a/core/domain_settings/resources/classes/domain_settings.php +++ b/core/domain_settings/resources/classes/domain_settings.php @@ -25,7 +25,6 @@ */ //define the domain settings class -if (!class_exists('domain_settings')) { class domain_settings { /** @@ -386,6 +385,3 @@ if (!class_exists('domain_settings')) { } //method } //class -} - -?> diff --git a/core/domains/domain_edit.php b/core/domains/domain_edit.php index bc40710efb..760b8f90ba 100644 --- a/core/domains/domain_edit.php +++ b/core/domains/domain_edit.php @@ -486,7 +486,6 @@ //recreate dialplan and extension xml files if (is_readable($_SESSION['switch']['extensions']['dir'])) { - require_once $_SERVER["DOCUMENT_ROOT"].PROJECT_PATH."/app/extensions/resources/classes/extension.php"; $extension = new extension; $extension->xml(); } diff --git a/core/email_templates/resources/classes/email_templates.php b/core/email_templates/resources/classes/email_templates.php index 027e76ee03..af7240421a 100644 --- a/core/email_templates/resources/classes/email_templates.php +++ b/core/email_templates/resources/classes/email_templates.php @@ -25,7 +25,6 @@ */ //define the email templates class -if (!class_exists('email_templates')) { class email_templates { /** @@ -244,6 +243,3 @@ if (!class_exists('email_templates')) { } } -} - -?> \ No newline at end of file diff --git a/core/events/resources/classes/events.php b/core/events/resources/classes/events.php index e3fbb373cb..dd72242c6d 100644 --- a/core/events/resources/classes/events.php +++ b/core/events/resources/classes/events.php @@ -2,9 +2,6 @@ /** * events class provides an event system - * - * @method void load_plugins - * @method dynamic __call */ class events { @@ -31,11 +28,7 @@ class events { //create the database connection //includes files - require_once dirname(__DIR__, 4) . "/resources/require.php"; - - //includes files - require_once "resources/classes/database.php"; - $database = new database; + $database = database::new(); $database->connect(); $this->db = $database->db; return $this->db = $database->db; diff --git a/core/groups/permissions_default.php b/core/groups/permissions_default.php index 30a17c6f7e..4b5b41f02e 100644 --- a/core/groups/permissions_default.php +++ b/core/groups/permissions_default.php @@ -43,7 +43,6 @@ $text = $language->get(); //permission restore default - require_once "core/groups/resources/classes/permission.php"; $permission = new permission; $permission->restore(); diff --git a/core/install/resources/classes/install.php b/core/install/resources/classes/install.php index cd9b089cb7..221d7b4c38 100644 --- a/core/install/resources/classes/install.php +++ b/core/install/resources/classes/install.php @@ -1,6 +1,5 @@ diff --git a/core/menu/menu_restore_default.php b/core/menu/menu_restore_default.php index ef46c1e998..df0c5f3c1a 100644 --- a/core/menu/menu_restore_default.php +++ b/core/menu/menu_restore_default.php @@ -51,7 +51,6 @@ } //menu restore default - //require_once "resources/classes/menu.php"; $menu = new menu; $menu->menu_uuid = $menu_uuid; $menu->menu_language = $menu_language; diff --git a/core/software/resources/classes/software.php b/core/software/resources/classes/software.php index 7a84332caf..16f8bac3d0 100644 --- a/core/software/resources/classes/software.php +++ b/core/software/resources/classes/software.php @@ -2,10 +2,7 @@ /** * software class - * - * @method string version */ -if (!class_exists('software')) { class software { /** @@ -25,6 +22,3 @@ if (!class_exists('software')) { } } -} - -?> diff --git a/core/upgrade/index.php b/core/upgrade/index.php index eb56ed9fce..5d7f1499eb 100644 --- a/core/upgrade/index.php +++ b/core/upgrade/index.php @@ -133,7 +133,6 @@ //load an array of the database schema and compare it with the active database if (!empty($action["upgrade_schema"]) && permission_exists("upgrade_schema")) { - require_once "resources/classes/schema.php"; $obj = new schema(); if (isset($action["data_types"]) && $action["data_types"] == 'true') { $obj->data_types = true; diff --git a/core/upgrade/upgrade.php b/core/upgrade/upgrade.php index 376c3b0a22..7fb56cc9d0 100644 --- a/core/upgrade/upgrade.php +++ b/core/upgrade/upgrade.php @@ -189,8 +189,6 @@ //run all app_defaults.php files if ($upgrade_type == 'domains') { - require_once "resources/classes/config.php"; - require_once "resources/classes/domains.php"; $domain = new domains; $domain->display_type = $display_type; $domain->upgrade(); @@ -199,7 +197,6 @@ //upgrade schema and/or data_types if ($upgrade_type == 'schema') { //get the database schema put it into an array then compare and update the database as needed. - require_once "resources/classes/schema.php"; $obj = new schema; if (isset($argv[2]) && $argv[2] == 'data_types') { $obj->data_types = true; diff --git a/core/upgrade/upgrade_domains.php b/core/upgrade/upgrade_domains.php index 99931b27a1..e2d1692b0a 100644 --- a/core/upgrade/upgrade_domains.php +++ b/core/upgrade/upgrade_domains.php @@ -46,8 +46,6 @@ } //run all app_defaults.php files - require_once "resources/classes/config.php"; - require_once "resources/classes/domains.php"; $domain = new domains; $domain->display_type = $display_type; $domain->upgrade(); diff --git a/core/upgrade/upgrade_menu.php b/core/upgrade/upgrade_menu.php index e2497f80f9..f44373c479 100644 --- a/core/upgrade/upgrade_menu.php +++ b/core/upgrade/upgrade_menu.php @@ -273,8 +273,6 @@ function do_upgrade_code_submodules() { * Execute all app_defaults.php files */ function do_upgrade_domains() { - require_once dirname(__DIR__, 2) . "/resources/classes/config.php"; - require_once dirname(__DIR__, 2) . "/resources/classes/domains.php"; $domain = new domains; $domain->display_type = 'text'; $domain->upgrade(); @@ -285,7 +283,6 @@ function do_upgrade_domains() { */ function do_upgrade_schema(bool $data_types = false) { //get the database schema put it into an array then compare and update the database as needed. - require_once dirname(__DIR__, 2) . "/resources/classes/schema.php"; $obj = new schema; $obj->data_types = $data_types; echo $obj->schema('text'); diff --git a/core/upgrade/upgrade_schema.php b/core/upgrade/upgrade_schema.php index aa60ffef8a..807631d935 100644 --- a/core/upgrade/upgrade_schema.php +++ b/core/upgrade/upgrade_schema.php @@ -59,7 +59,6 @@ $text = $language->get(); //get the database schema put it into an array then compare and update the database as needed. - require_once "resources/classes/schema.php"; $obj = new schema; if (isset($argv[1]) && $argv[1] == 'data_types') { $obj->data_types = true; diff --git a/core/user_logs/resources/classes/user_logs.php b/core/user_logs/resources/classes/user_logs.php index 041603f66f..659e3976f2 100644 --- a/core/user_logs/resources/classes/user_logs.php +++ b/core/user_logs/resources/classes/user_logs.php @@ -26,12 +26,7 @@ /** * user_logs class - * - * @method null delete - * @method null toggle - * @method null copy */ -if (!class_exists('user_logs')) { class user_logs { /** @@ -151,6 +146,3 @@ if (!class_exists('user_logs')) { } } -} - -?> diff --git a/core/user_settings/resources/classes/user_settings.php b/core/user_settings/resources/classes/user_settings.php index dea8b87ab3..8819ae58b0 100644 --- a/core/user_settings/resources/classes/user_settings.php +++ b/core/user_settings/resources/classes/user_settings.php @@ -25,7 +25,6 @@ */ //define the user settings class -if (!class_exists('user_settings')) { class user_settings { /** @@ -181,6 +180,3 @@ if (!class_exists('user_settings')) { } //method } //class -} - -?> \ No newline at end of file diff --git a/core/user_settings/user_setting_set.php b/core/user_settings/user_setting_set.php index 90dc47ed26..ef9dc20c86 100644 --- a/core/user_settings/user_setting_set.php +++ b/core/user_settings/user_setting_set.php @@ -107,7 +107,6 @@ Mark J Crane //revoke temporary permissions $p->delete('user_setting_delete', 'temp'); //reset session variables to default - require "resources/classes/domains.php"; $domain = new domains(); $domain->set(); } diff --git a/core/users/resources/classes/users.php b/core/users/resources/classes/users.php index 734ce273d9..f7424b734e 100644 --- a/core/users/resources/classes/users.php +++ b/core/users/resources/classes/users.php @@ -26,12 +26,7 @@ /** * users class - * - * @method null delete - * @method null toggle - * @method null copy */ -if (!class_exists('users')) { class users { /** @@ -315,6 +310,3 @@ if (!class_exists('users')) { } } } -} - -?> diff --git a/resources/classes/auto_loader.php b/resources/classes/auto_loader.php index 1b5ed65549..74aed053e7 100644 --- a/resources/classes/auto_loader.php +++ b/resources/classes/auto_loader.php @@ -1,29 +1,37 @@ - Portions created by the Initial Developer are Copyright (C) 2008-2024 - the Initial Developer. All Rights Reserved. + The Initial Developer of the Original Code is + Mark J Crane + Portions created by the Initial Developer are Copyright (C) 2008-2024 + the Initial Developer. All Rights Reserved. - Contributor(s): - Mark J Crane -*/ + Contributor(s): + Mark J Crane + */ +/** + * Auto Loader class + * Searches for project files when a class is required. Debugging mode can be set using: + * - export DEBUG=1 + * OR + * - debug=true is appended to the url + */ class auto_loader { const FILE = 'autoloader_cache.php'; @@ -37,11 +45,20 @@ class auto_loader { */ private $apcu_enabled; + /** + * Cache path and file name + * @var string + */ + private static $cache_file = null; + public function __construct($project_path = '') { //set if we can use RAM cache $this->apcu_enabled = function_exists('apcu_enabled') && apcu_enabled(); + //set cache location + self::$cache_file = sys_get_temp_dir() . DIRECTORY_SEPARATOR . self::FILE; + //classes must be loaded before this object is registered if (!$this->load_cache()) { //cache miss so load them @@ -61,12 +78,14 @@ class auto_loader { //update RAM cache when available if ($this->apcu_enabled) { - apcu_store(self::CACHE_KEY, $this->classes); + $success = apcu_store(self::CACHE_KEY, $this->classes); + //do not save to drive when we are using apcu + if ($success) return true; } //ensure we have somewhere to put the file if (empty($file)) { - $file = sys_get_temp_dir() . '/' . self::FILE; + $file = self::$cache_file; } //export the classes array using PHP engine @@ -77,13 +96,10 @@ class auto_loader { if ($result !== false) { return true; } + + //file failed to save - send error to syslog when debugging $error_array = error_get_last(); - //send to syslog when debugging - if (!empty($_REQUEST['debug']) && $_REQUEST['debug'] == 'true') { - openlog("PHP", LOG_PID | LOG_PERROR, LOG_LOCAL0); - syslog(LOG_WARNING, "[php][auto_loader] " . $error_array['message']); - closelog(); - } + self::log(LOG_WARNING, $error_array['message'] ?? ''); return false; } @@ -99,21 +115,21 @@ class auto_loader { //use a standard file if (empty($file)) { - $file = sys_get_temp_dir() . '/'. self::FILE; + $file = self::$cache_file; } + //use PHP engine to parse it if (file_exists($file)) { $this->classes = include $file; } - //assign to an array - if (!empty($this->classes)) { - //cache edge case of first time using apcu cache - if ($this->apcu_enabled) { - apcu_store(self::CACHE_KEY, $this->classes); - } - return true; + + //catch edge case of first time using apcu cache + if ($this->apcu_enabled) { + apcu_store(self::CACHE_KEY, $this->classes); } - return false; + + //return true when we have classes and false if the array is still empty + return !empty($this->classes); } public function reload_classes($project_path = '') { @@ -122,26 +138,87 @@ class auto_loader { $project_path = dirname(__DIR__, 2); } - //build the array of all classes - $search_path = []; - $search_path = array_merge($search_path, glob($project_path . '/resources/classes/*.php')); - $search_path = array_merge($search_path, glob($project_path . '/resources/interfaces/*.php')); - $search_path = array_merge($search_path, glob($project_path . '/resources/traits/*.php')); - $search_path = array_merge($search_path, glob($project_path . '/*/*/resources/classes/*.php')); - $search_path = array_merge($search_path, glob($project_path . '/*/*/resources/interfaces/*.php')); - $search_path = array_merge($search_path, glob($project_path . '/*/*/resources/traits/*.php')); + //build the array of all locations for classes in specific order + $search_path = [ + $project_path . '/resources/interfaces/*.php', + $project_path . '/resources/traits/*.php', + $project_path . '/resources/classes/*.php', + $project_path . '/*/*/resources/interfaces/*.php', + $project_path . '/*/*/resources/traits/*.php', + $project_path . '/*/*/resources/classes/*.php', + $project_path . '/core/authentication/resources/classes/plugins/*.php', + ]; + + //get all php files for each path + $files = []; + foreach ($search_path as $path) { + $files = array_merge($files, glob($path)); + } //reset the current array $this->classes = []; - //store the class name (key) and the path (value) - foreach ($search_path as $path) { - $this->classes[basename($path, '.php')] = $path; - } + //store PHP language declared classes, interfaces, and traits + $curr_classes = get_declared_classes(); + $curr_interfaces = get_declared_interfaces(); + $curr_traits = get_declared_traits(); + //store the class name (key) and the path (value) + foreach ($files as $file) { + + //include the new class + try { + include_once $file; + } catch (Exception $e) { + //report the error + self::log(LOG_ERR, "Exception while trying to include file '$file': " . $e->getMessage()); + continue; + } + + //get the new classes + $new_classes = get_declared_classes(); + $new_interfaces = get_declared_interfaces(); + $new_traits = get_declared_traits(); + + //check for a new class + $classes = array_diff($new_classes, $curr_classes); + if (!empty($classes)) { + foreach ($classes as $class) { + $this->classes[$class] = $file; + } + //overwrite previous array with new values + $curr_classes = $new_classes; + } + + //check for a new interface + $interfaces = array_diff($new_interfaces, $curr_interfaces); + if (!empty($interfaces)) { + foreach ($interfaces as $interface) { + $this->classes[$interface] = $file; + } + //overwrite previous array with new values + $curr_interfaces = $new_interfaces; + } + + //check for a new trait + $traits = array_diff($new_traits, $curr_traits); + if (!empty($traits)) { + foreach ($traits as $trait) { + $this->classes[$trait] = $file; + } + //overwrite previous array with new values + $curr_traits = $new_traits; + } + } } - private function loader($class_name) : bool { + /** + * The loader is set to private because only the PHP engine should be calling this method + * @param string $class_name The class name that needs to be loaded + * @return bool True if the class is loaded or false when the class is not found + * @access private + */ + private function loader($class_name): bool { //sanitize the class name $class_name = preg_replace('[^a-zA-Z0-9_]', '', $class_name); @@ -161,32 +238,29 @@ class auto_loader { } //cache miss - if (!empty($_REQUEST['debug']) && $_REQUEST['debug'] == 'true') { - openlog("PHP", LOG_PID | LOG_PERROR, LOG_LOCAL0); - syslog(LOG_WARNING, "[php][auto_loader] class not found in cache: ".$class_name); - closelog(); - } + self::log(LOG_WARNING, "class '$class_name' not found in cache"); //set project path using magic dir constant $project_path = dirname(__DIR__, 2); //build the search path array - $search_path[] = glob($project_path . "/resources/classes/".$class_name.".php"); - $search_path[] = glob($project_path . "/resources/interfaces/".$class_name.".php"); - $search_path[] = glob($project_path . "/resources/traits/".$class_name.".php"); - $search_path[] = glob($project_path . "/*/*/resources/classes/".$class_name.".php"); - $search_path[] = glob($project_path . "/*/*/resources/interfaces/".$class_name.".php"); - $search_path[] = glob($project_path . "/*/*/resources/traits/".$class_name.".php"); + $search_path[] = glob($project_path . "/resources/interfaces/" . $class_name . ".php"); + $search_path[] = glob($project_path . "/resources/traits/" . $class_name . ".php"); + $search_path[] = glob($project_path . "/resources/classes/" . $class_name . ".php"); + $search_path[] = glob($project_path . "/*/*/resources/interfaces/" . $class_name . ".php"); + $search_path[] = glob($project_path . "/*/*/resources/traits/" . $class_name . ".php"); + $search_path[] = glob($project_path . "/*/*/resources/classes/" . $class_name . ".php"); - //find the path - $path = self::autoload_search($search_path); - if (!empty($path)) { + //collapse all entries to only the matched entry + $matches = array_filter($search_path); + if (!empty($matches)) { + $path = array_pop($matches)[0]; - //include the class or interface - include $path; + //include the class, interface, or trait + include_once $path; - //make sure to reload the cache after we found a new class - $this->reload_classes(); + //inject the class in to the array + $this->classes[$class_name] = $path; //update the cache with new classes $this->update_cache(); @@ -196,35 +270,54 @@ class auto_loader { } //send to syslog when debugging - if (!empty($_REQUEST['debug']) && $_REQUEST['debug'] == 'true') { - openlog("PHP", LOG_PID | LOG_PERROR, LOG_LOCAL0); - syslog(LOG_WARNING, "[php][auto_loader] class not found name: ".$class_name); - closelog(); - } + self::log(LOG_ERR, "class '$class_name' not found name"); //return boolean return false; } - public static function autoload_search($array) : string { - foreach($array as $path) { - if (is_array($path) && count($path) != 0) { - foreach($path as $sub_path) { - if (!empty($sub_path) && file_exists($sub_path)) { - return $sub_path; - } - } - } - elseif (!empty($path) && file_exists($path)) { - return $path; - } + /** + * Returns a list of classes loaded by the auto_loader. If no classes have been loaded an empty array is returned. + * @return array List of classes loaded by the auto_loader or empty array + */ + public function get_class_list(): array { + if (!empty($this->classes)) { + return $this->classes; } - return ''; + return []; } - public static function clear_cache() { + public static function clear_cache(string $file = '') { + + //check for apcu cache if (function_exists('apcu_enabled') && apcu_enabled()) { apcu_delete(self::CACHE_KEY); } + + //set default file + if (empty(self::$cache_file)) { + self::$cache_file = sys_get_temp_dir() . DIRECTORY_SEPARATOR . self::FILE; + } + + //set file to clear + if (empty($file)) { + $file = self::$cache_file; + } + + //remove the file when it exists + if (file_exists($file)) { + @unlink($file); + $error_array = error_get_last(); + //send to syslog when debugging with either environment variable or debug in the url + self::log(LOG_WARNING, $error_array['message'] ?? ''); + } + } + + private static function log(int $level, string $message): void { + if (filter_var($_REQUEST['debug'] ?? false, FILTER_VALIDATE_BOOL) || filter_var(getenv('DEBUG') ?? false, FILTER_VALIDATE_BOOL)) { + openlog("PHP", LOG_PID | LOG_PERROR, LOG_LOCAL0); + syslog($level, "[auto_loader] " . $message); + closelog(); + } } } diff --git a/resources/classes/button.php b/resources/classes/button.php index c82b34551b..d7786d7418 100644 --- a/resources/classes/button.php +++ b/resources/classes/button.php @@ -25,7 +25,6 @@ Mark J Crane */ -if (!class_exists('button')) { class button { public static $collapse = 'hide-md-dn'; @@ -127,7 +126,6 @@ if (!class_exists('button')) { $button = $anchor.$button.""; } return $button; - unset($button); } private static function quote($value) { @@ -135,7 +133,6 @@ if (!class_exists('button')) { } } -} /* @@ -236,5 +233,3 @@ if (!class_exists('button')) { */ - -?> \ No newline at end of file diff --git a/resources/classes/database.php b/resources/classes/database.php index f745b8a489..28ceade452 100644 --- a/resources/classes/database.php +++ b/resources/classes/database.php @@ -3279,7 +3279,7 @@ * @see database::__construct() * @see database::connect() */ - public static function new(array $params = []) { + public static function new(array $params = []): static { if (self::$database === null) { self::$database = new database($params); if (!self::$database->is_connected()) { @@ -3326,7 +3326,6 @@ /* //example usage //find - require_once "resources/classes/database.php"; $database = new database; $database->domain_uuid = $_SESSION["domain_uuid"]; $database->type = $db_type; @@ -3343,7 +3342,6 @@ $database->find(); print_r($database->result); //insert - require_once "resources/classes/database.php"; $database = new database; $database->domain_uuid = $_SESSION["domain_uuid"]; $database->table = "v_ivr_menus"; diff --git a/resources/classes/domains.php b/resources/classes/domains.php index 2875616cdd..edb1932425 100644 --- a/resources/classes/domains.php +++ b/resources/classes/domains.php @@ -28,11 +28,7 @@ /** * domains class * - * @method null delete - * @method null toggle - * @method null copy */ -if (!class_exists('domains')) { class domains { /** @@ -786,6 +782,3 @@ if (!class_exists('domains')) { } } -} - -?> diff --git a/resources/classes/email.php b/resources/classes/email.php index dc419897b0..9b046505d6 100644 --- a/resources/classes/email.php +++ b/resources/classes/email.php @@ -27,9 +27,7 @@ /** * email class * - * @method boolean send */ -if (!class_exists('email')) { class email { /** @@ -625,7 +623,7 @@ if (!class_exists('email')) { } } -} + /* $email = new email; diff --git a/resources/classes/groups.php b/resources/classes/groups.php index 2bf85c4e63..138671f38b 100644 --- a/resources/classes/groups.php +++ b/resources/classes/groups.php @@ -27,11 +27,7 @@ /** * groups class provides methods for add, delete groups, and add default groups * - * @method null delete - * @method null toggle - * @method null copy */ -if (!class_exists('groups')) { class groups { /** @@ -534,6 +530,3 @@ if (!class_exists('groups')) { $_SESSION["user"]["group_level"] = $this->group_level; } } -} - -?> \ No newline at end of file diff --git a/resources/classes/menu.php b/resources/classes/menu.php index 9df1c94320..04489265a9 100644 --- a/resources/classes/menu.php +++ b/resources/classes/menu.php @@ -27,7 +27,6 @@ /** * menu class */ -if (!class_exists('menu')) { class menu { /** @@ -1339,4 +1338,3 @@ if (!class_exists('menu')) { } } -} diff --git a/resources/classes/message.php b/resources/classes/message.php index 936f4edd46..61e017753b 100644 --- a/resources/classes/message.php +++ b/resources/classes/message.php @@ -25,7 +25,6 @@ Matthew Vale */ -if (!class_exists('message')) { class message { static function add($message, $mood = null, $delay = null) { @@ -71,6 +70,3 @@ if (!class_exists('message')) { return $html; } } -} - -?> diff --git a/resources/classes/modal.php b/resources/classes/modal.php index e5d61a9f68..0629c4fa69 100644 --- a/resources/classes/modal.php +++ b/resources/classes/modal.php @@ -25,7 +25,6 @@ Mark J Crane */ -if (!class_exists('modal')) { class modal { static function create($array) { @@ -65,11 +64,7 @@ if (!class_exists('modal')) { $modal .= "
"; return $modal; - unset($modal); } } -} - -?> \ No newline at end of file diff --git a/resources/classes/schema.php b/resources/classes/schema.php index 3ec6c2c57f..1bd01703ff 100644 --- a/resources/classes/schema.php +++ b/resources/classes/schema.php @@ -26,8 +26,6 @@ */ //define the schema class -if (!class_exists('schema')) { - class schema { //define variables @@ -473,7 +471,6 @@ if (!class_exists('schema')) { } //get the db variables - //require_once "resources/classes/config.php"; //$config = new config; //$config_exists = $config->exists(); //$config_path = $config->find(); @@ -908,13 +905,10 @@ if (!class_exists('schema')) { } //end function } -} //example use -//require_once "resources/classes/schema.php"; //$obj = new schema; //$obj->db_type = $db_type; //$obj->schema(); //$result_array = $schema->obj['sql']; //print_r($result_array); -?> diff --git a/resources/classes/switch_settings.php b/resources/classes/switch_settings.php index 3457dba41e..e1822954cc 100644 --- a/resources/classes/switch_settings.php +++ b/resources/classes/switch_settings.php @@ -5,7 +5,6 @@ * * @method settings will add missing switch directories to default settings */ -if (!class_exists('switch_settings')) { class switch_settings { public $event_socket_ip_address; @@ -276,6 +275,3 @@ if (!class_exists('switch_settings')) { unset($array); } } -} - -?> diff --git a/resources/classes/template.php b/resources/classes/template.php index 0c932163e3..3b3d2c57f4 100644 --- a/resources/classes/template.php +++ b/resources/classes/template.php @@ -25,7 +25,6 @@ */ //define the template class - if (!class_exists('template')) { class template { public $engine; @@ -90,6 +89,3 @@ } } } - } - -?> \ No newline at end of file diff --git a/resources/classes/tones.php b/resources/classes/tones.php index 397348e660..90a8f9a08d 100644 --- a/resources/classes/tones.php +++ b/resources/classes/tones.php @@ -25,7 +25,6 @@ Matthew Vale */ -if (!class_exists('tones')) { class tones { //define variables @@ -33,7 +32,7 @@ if (!class_exists('tones')) { private $music_list; private $recordings_list; private $default_tone_label; - + //class constructor public function __construct() { //add multi-lingual support @@ -61,11 +60,8 @@ if (!class_exists('tones')) { $this->tones = $tone_list ?? ''; unset($sql, $tones, $tone, $tone_list); } - + public function tones_list() { return $this->tones; } } -} - -?> diff --git a/resources/classes/xml.php b/resources/classes/xml.php index 582595f15a..ac7d883297 100644 --- a/resources/classes/xml.php +++ b/resources/classes/xml.php @@ -1,6 +1,5 @@ diff --git a/resources/switch.php b/resources/switch.php index 906942b404..fa72e0ba13 100644 --- a/resources/switch.php +++ b/resources/switch.php @@ -948,7 +948,6 @@ if (!function_exists('save_switch_xml')) { function save_switch_xml() { if (is_readable($_SESSION['switch']['extensions']['dir'])) { if (file_exists($_SERVER["DOCUMENT_ROOT"].PROJECT_PATH."/app/extensions/resources/classes/extension.php")) { - require_once $_SERVER["DOCUMENT_ROOT"].PROJECT_PATH."app/extensions/resources/classes/extension.php"; $extension = new extension; $extension->xml(); } @@ -958,7 +957,6 @@ if (!function_exists('save_switch_xml')) { save_setting_xml(); } if (file_exists($_SERVER["PROJECT_ROOT"]."/app/modules/app_config.php")) { - require_once $_SERVER["DOCUMENT_ROOT"].PROJECT_PATH."/app/modules/resources/classes/modules.php"; $module = new modules; $module->xml(); //$msg = $module->msg; diff --git a/secure/fax_to_email.php b/secure/fax_to_email.php index a4a3525ddd..50e3f282ac 100644 --- a/secure/fax_to_email.php +++ b/secure/fax_to_email.php @@ -201,9 +201,8 @@ if (!function_exists('fax_split_dtmf')) { //includes files require_once dirname(__DIR__) . "/resources/require.php"; - include "resources/classes/event_socket.php"; - include "resources/phpmailer/class.phpmailer.php"; - include "resources/phpmailer/class.smtp.php"; // optional, gets called from within class.phpmailer.php if not already loaded + include_once "resources/phpmailer/class.phpmailer.php"; + include_once "resources/phpmailer/class.smtp.php"; // optional, gets called from within class.phpmailer.php if not already loaded //set php ini values ini_set('max_execution_time', 900); //15 minutes From 7897ff5b9e64c95459415b8592d66cfc2a570b99 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Wed, 12 Mar 2025 14:42:50 -0600 Subject: [PATCH 187/196] Clear the cache --- core/upgrade/upgrade.php | 1 + 1 file changed, 1 insertion(+) diff --git a/core/upgrade/upgrade.php b/core/upgrade/upgrade.php index 7fb56cc9d0..0d999aea99 100644 --- a/core/upgrade/upgrade.php +++ b/core/upgrade/upgrade.php @@ -181,6 +181,7 @@ $auto_loader = new auto_loader(); $auto_loader->reload_classes(); $auto_loader->update_cache(); + $auto_loader->clear_cache(); //get the version of the software if ($upgrade_type == 'version') { From 31a88e3a15d7399fcf198adee00cfa4891336003 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Wed, 12 Mar 2025 14:48:33 -0600 Subject: [PATCH 188/196] Update auto_loader.php --- resources/classes/auto_loader.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/resources/classes/auto_loader.php b/resources/classes/auto_loader.php index 74aed053e7..7befa402e8 100644 --- a/resources/classes/auto_loader.php +++ b/resources/classes/auto_loader.php @@ -159,9 +159,9 @@ class auto_loader { $this->classes = []; //store PHP language declared classes, interfaces, and traits - $curr_classes = get_declared_classes(); - $curr_interfaces = get_declared_interfaces(); - $curr_traits = get_declared_traits(); + $current_classes = get_declared_classes(); + $current_interfaces = get_declared_interfaces(); + $current_traits = get_declared_traits(); //store the class name (key) and the path (value) foreach ($files as $file) { @@ -181,33 +181,33 @@ class auto_loader { $new_traits = get_declared_traits(); //check for a new class - $classes = array_diff($new_classes, $curr_classes); + $classes = array_diff($new_classes, $current_classes); if (!empty($classes)) { foreach ($classes as $class) { $this->classes[$class] = $file; } //overwrite previous array with new values - $curr_classes = $new_classes; + $current_classes = $new_classes; } //check for a new interface - $interfaces = array_diff($new_interfaces, $curr_interfaces); + $interfaces = array_diff($new_interfaces, $current_interfaces); if (!empty($interfaces)) { foreach ($interfaces as $interface) { $this->classes[$interface] = $file; } //overwrite previous array with new values - $curr_interfaces = $new_interfaces; + $current_interfaces = $new_interfaces; } //check for a new trait - $traits = array_diff($new_traits, $curr_traits); + $traits = array_diff($new_traits, $current_traits); if (!empty($traits)) { foreach ($traits as $trait) { $this->classes[$trait] = $file; } //overwrite previous array with new values - $curr_traits = $new_traits; + $current_traits = $new_traits; } } } From 95761621a661b39eba26fcf8b7cb9fd62a33d815 Mon Sep 17 00:00:00 2001 From: chansizzle <14916599+chansizzle@users.noreply.github.com> Date: Wed, 12 Mar 2025 17:39:05 -0600 Subject: [PATCH 189/196] improve emergency emailing (#7309) * improve emergency emailing 1. set emergency CID name & number to the outbound CID name & number if emergency CID name & number are not set 2. remove duplicate item in email body 3. change the hardcoded email subject '911 Emergency Call' to be dynamically provided from the event. I do not like seeing the subject '911 Emergency Call' when it is an TEST call. * improve emergency emailing 1. change the hardcoded email subject '911 Emergency Call' to be dynamically provided from the event. I do not like seeing the subject '911 Emergency Call' when it is an TEST call. 2. fix email template misspelling 3. improved email template with bold fonts --- .../resources/scripts/app/emergency/index.lua | 13 +++++++--- core/email_templates/app_defaults.php | 24 +++++++++---------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/app/switch/resources/scripts/app/emergency/index.lua b/app/switch/resources/scripts/app/emergency/index.lua index d33c5eb2a2..53c945a435 100644 --- a/app/switch/resources/scripts/app/emergency/index.lua +++ b/app/switch/resources/scripts/app/emergency/index.lua @@ -118,13 +118,18 @@ if (session and session:ready()) then sip_from_user = session:getVariable("sip_from_user"); emergency_caller_id_name = session:getVariable("emergency_caller_id_name"); emergency_caller_id_number = session:getVariable("emergency_caller_id_number"); + outbound_caller_id_name = session:getVariable("outbound_caller_id_name"); outbound_caller_id_number = session:getVariable("outbound_caller_id_number"); destination_number = session:getVariable("destination_number"); end --set the defaults -if (not emergency_caller_id_name) then emergency_caller_id_name = ''; end -if (not emergency_caller_id_number) then emergency_caller_id_number = '' end +if (not emergency_caller_id_name or emergency_caller_id_name == '') then + emergency_caller_id_name = outbound_caller_id_name +end +if (not emergency_caller_id_number or emergency_caller_id_number == '') then + emergency_caller_id_number = outbound_caller_id_number +end --no emergency emails found under domain, using default local sql = "SELECT default_setting_value "; @@ -181,6 +186,9 @@ end local t = dbh:first_row(sql); call_date = t.call_date; +-- replace the hardcoded template subject with the event +subject = event; + --send the email if (#to > 0) then --prepare the body @@ -190,7 +198,6 @@ if (#to > 0) then body = body:gsub("${emergency_caller_id_name}", emergency_caller_id_name); body = body:gsub("${emergency_caller_id_number}", emergency_caller_id_number); body = body:gsub("${sip_from_user}", sip_from_user); - body = body:gsub("${caller_id_number}", caller_id_number); body = body:gsub("${message_date}", call_date); body = body:gsub("${event}", event); body = trim(body); diff --git a/core/email_templates/app_defaults.php b/core/email_templates/app_defaults.php index de95aa70ab..f3280dd25d 100644 --- a/core/email_templates/app_defaults.php +++ b/core/email_templates/app_defaults.php @@ -510,15 +510,15 @@ $array['email_templates'][$x]['template_language'] = 'en-gb'; $array['email_templates'][$x]['template_category'] = 'plugin'; $array['email_templates'][$x]['template_subcategory'] = 'emergency'; - $array['email_templates'][$x]['template_subject'] = '911 Emergency Call'; + $array['email_templates'][$x]['template_subject'] = '\${event}'; $array['email_templates'][$x]['template_body'] = "\n"; $array['email_templates'][$x]['template_body'] .= "\n"; - $array['email_templates'][$x]['template_body'] .= "From \${caller_id_name} \${caller_id_number}
\n"; + $array['email_templates'][$x]['template_body'] .= "From: \${caller_id_name} \${caller_id_number}
\n"; $array['email_templates'][$x]['template_body'] .= "
\n"; - $array['email_templates'][$x]['template_body'] .= "Emergency Name \${emergency_caller_id_name}
\n"; - $array['email_templates'][$x]['template_body'] .= "Emergency Name \${emergency_caller_id_number}
\n"; - $array['email_templates'][$x]['template_body'] .= "Received \${message_date}
\n"; - $array['email_templates'][$x]['template_body'] .= "Event \${event}
\n"; + $array['email_templates'][$x]['template_body'] .= "Emergency Name: \${emergency_caller_id_name}
\n"; + $array['email_templates'][$x]['template_body'] .= "Emergency Number: \${emergency_caller_id_number}
\n"; + $array['email_templates'][$x]['template_body'] .= "Received: \${message_date}
\n"; + $array['email_templates'][$x]['template_body'] .= "Event: \${event}
\n"; $array['email_templates'][$x]['template_body'] .= "\n"; $array['email_templates'][$x]['template_body'] .= "\n"; $array['email_templates'][$x]['template_type'] = 'html'; @@ -530,15 +530,15 @@ $array['email_templates'][$x]['template_language'] = 'en-us'; $array['email_templates'][$x]['template_category'] = 'plugin'; $array['email_templates'][$x]['template_subcategory'] = 'emergency'; - $array['email_templates'][$x]['template_subject'] = '911 Emergency Call'; + $array['email_templates'][$x]['template_subject'] = '\${event}'; $array['email_templates'][$x]['template_body'] = "\n"; $array['email_templates'][$x]['template_body'] .= "\n"; - $array['email_templates'][$x]['template_body'] .= "From \${caller_id_name} \${caller_id_number}
\n"; + $array['email_templates'][$x]['template_body'] .= "From: \${caller_id_name} \${caller_id_number}
\n"; $array['email_templates'][$x]['template_body'] .= "
\n"; - $array['email_templates'][$x]['template_body'] .= "Emergency Name \${emergency_caller_id_name}
\n"; - $array['email_templates'][$x]['template_body'] .= "Emergency Name \${emergency_caller_id_number}
\n"; - $array['email_templates'][$x]['template_body'] .= "Received \${message_date}
\n"; - $array['email_templates'][$x]['template_body'] .= "Event \${event}
\n"; + $array['email_templates'][$x]['template_body'] .= "Emergency Name: \${emergency_caller_id_name}
\n"; + $array['email_templates'][$x]['template_body'] .= "Emergency Number: \${emergency_caller_id_number}
\n"; + $array['email_templates'][$x]['template_body'] .= "Received: \${message_date}
\n"; + $array['email_templates'][$x]['template_body'] .= "Event: \${event}
\n"; $array['email_templates'][$x]['template_body'] .= "\n"; $array['email_templates'][$x]['template_body'] .= "\n"; $array['email_templates'][$x]['template_type'] = 'html'; From bed7c8827f663bbcaa216c0d0fa02817e0826f9c Mon Sep 17 00:00:00 2001 From: frytimo Date: Wed, 12 Mar 2025 23:50:14 -0300 Subject: [PATCH 190/196] fix missing quotes on parameter default value (#7310) --- resources/functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/functions.php b/resources/functions.php index cc791db9df..43b4219938 100644 --- a/resources/functions.php +++ b/resources/functions.php @@ -2118,7 +2118,7 @@ //define email button (src: https://buttons.cm) if (!function_exists('email_button')) { - function email_button($text = 'Click Here!', $link = URL, $bg_color = '#dddddd', $fg_color = '#000000', $radius = '') { + function email_button($text = 'Click Here!', $link = 'URL', $bg_color = '#dddddd', $fg_color = '#000000', $radius = '') { // default button radius $radius = !empty($radius) ? $radius : '3px'; From 6c6814b29e22b3c93b7d8e73342fcf0f22c78c5c Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Wed, 12 Mar 2025 23:39:24 -0600 Subject: [PATCH 191/196] Remove syntax that breaks older PHP Removed :static to support PHP 7.4 --- resources/classes/database.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/classes/database.php b/resources/classes/database.php index 28ceade452..692dcb56cd 100644 --- a/resources/classes/database.php +++ b/resources/classes/database.php @@ -3279,7 +3279,7 @@ * @see database::__construct() * @see database::connect() */ - public static function new(array $params = []): static { + public static function new(array $params = []) { if (self::$database === null) { self::$database = new database($params); if (!self::$database->is_connected()) { From ee28c6d2039c4079eabed70b972330adecda3882 Mon Sep 17 00:00:00 2001 From: FusionPBX Date: Thu, 13 Mar 2025 10:06:36 -0600 Subject: [PATCH 192/196] Fix Call Detail Records with invalid xml --- app/xml_cdr/resources/classes/xml_cdr.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/xml_cdr/resources/classes/xml_cdr.php b/app/xml_cdr/resources/classes/xml_cdr.php index 432570f92d..58047adfd4 100644 --- a/app/xml_cdr/resources/classes/xml_cdr.php +++ b/app/xml_cdr/resources/classes/xml_cdr.php @@ -339,6 +339,12 @@ //replace xml tag name with $xml_string = preg_replace('/(<\/?)(set )([^>]*>)/', '$1$3', $xml_string); + //replace xml tag name <^^,default_language> with + $xml_string = preg_replace('/(<\/?)(\^\^,)([^>]*>)/', '$1$3', $xml_string); + + //replace xml tag name with + $xml_string = preg_replace('/(<\/?)(nolocal:)([^>]*>)/', '$1$3', $xml_string); + //disable xml entities if (PHP_VERSION_ID < 80000) { libxml_disable_entity_loader(true); } From b5592e84c79d7255e6a2842771525d8cf29ff593 Mon Sep 17 00:00:00 2001 From: Alex <40072887+alexdcrane@users.noreply.github.com> Date: Thu, 13 Mar 2025 10:04:40 -0700 Subject: [PATCH 193/196] Fix fatal error on fax send (#7313) --- app/fax/fax_send.php | 83 +++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 44 deletions(-) diff --git a/app/fax/fax_send.php b/app/fax/fax_send.php index 9c6b59e9f7..a3918a49d5 100644 --- a/app/fax/fax_send.php +++ b/app/fax/fax_send.php @@ -17,7 +17,7 @@ The Initial Developer of the Original Code is Mark J Crane - Portions created by the Initial Developer are Copyright (C) 2008-2024 + Portions created by the Initial Developer are Copyright (C) 2008-2025 the Initial Developer. All Rights Reserved. Contributor(s): @@ -36,7 +36,7 @@ if (defined('STDIN')) { //add multi-lingual support $language = new text; - $text = $language->get($setting->get('domain','language','en-us'), 'app/fax'); + $text = $language->get($settings->get('domain','language','en-us'), 'app/fax'); } //executed via browser @@ -51,11 +51,6 @@ else { $domain_name = $_SESSION['domain_name']; $user_uuid = $_SESSION['user_uuid']; - //initialize the settings object - if (empty($settings)) { - $setting = new settings(["domain_uuid" => $domain_uuid]); - } - //check permissions if (permission_exists('fax_send')) { //access granted @@ -121,12 +116,12 @@ else { } //set the fax directory - if (!empty($setting->get('switch','storage'))) { - $fax_dir = $setting->get('switch','storage').'/fax/'.$domain_name; + if (!empty($settings->get('switch','storage'))) { + $fax_dir = $settings->get('switch','storage').'/fax/'.$domain_name; } //set fax cover font to generate pdf - $fax_cover_font = $setting->get('fax','cover_font') ?? null; + $fax_cover_font = $settings->get('fax','cover_font') ?? null; } //define function correct_path @@ -171,14 +166,14 @@ if (!function_exists('fax_split_dtmf')) { $dir_fax_temp = $fax_dir.'/'.$fax_extension.'/temp'; //make sure the directories exist - if (!empty($setting->get('switch','storage')) && !is_dir($setting->get('switch','storage'))) { - mkdir($setting->get('switch','storage'), 0770); + if (!empty($settings->get('switch','storage')) && !is_dir($settings->get('switch','storage'))) { + mkdir($settings->get('switch','storage'), 0770); } - if (!empty($setting->get('switch','storage')) && !is_dir($setting->get('switch','storage').'/fax')) { - mkdir($setting->get('switch','storage').'/fax', 0770); + if (!empty($settings->get('switch','storage')) && !is_dir($settings->get('switch','storage').'/fax')) { + mkdir($settings->get('switch','storage').'/fax', 0770); } - if (!empty($setting->get('switch','storage')) && !is_dir($setting->get('switch','storage').'/fax/'.$domain_name)) { - mkdir($setting->get('switch','storage').'/fax/'.$domain_name, 0770); + if (!empty($settings->get('switch','storage')) && !is_dir($settings->get('switch','storage').'/fax/'.$domain_name)) { + mkdir($settings->get('switch','storage').'/fax/'.$domain_name, 0770); } if (!is_dir($fax_dir.'/'.$fax_extension)) { mkdir($fax_dir.'/'.$fax_extension, 0770); @@ -301,7 +296,7 @@ if (!function_exists('fax_split_dtmf')) { } //un/authorized file extensions - $allowed_file_extensions = $setting->get('fax','allowed_extension'); + $allowed_file_extensions = $settings->get('fax','allowed_extension'); $disallowed_file_extensions = explode(',','sh,ssh,so,dll,exe,bat,vbs,zip,rar,z,tar,tbz,tgz,gz'); //process uploaded or emailed files (if any) @@ -410,19 +405,19 @@ if (!function_exists('fax_split_dtmf')) { //logo $display_logo = false; - if (empty($setting->get('fax','cover_logo'))) { + if (empty($settings->get('fax','cover_logo'))) { $logo = ''; //explicitly empty } - else if ($setting->get('fax','cover_logo') != '') { - if (substr($setting->get('fax','cover_logo'), 0, 4) == 'http') { - $logo = $setting->get('fax','cover_logo'); + else if ($settings->get('fax','cover_logo') != '') { + if (substr($settings->get('fax','cover_logo'), 0, 4) == 'http') { + $logo = $settings->get('fax','cover_logo'); } - else if (substr($setting->get('fax','cover_logo'), 0, 1) == '/') { - if (substr($setting->get('fax','cover_logo'), 0, strlen($_SERVER['DOCUMENT_ROOT'])) != $_SERVER['DOCUMENT_ROOT']) { - $logo = $_SERVER['DOCUMENT_ROOT'].$setting->get('fax','cover_logo'); + else if (substr($settings->get('fax','cover_logo'), 0, 1) == '/') { + if (substr($settings->get('fax','cover_logo'), 0, strlen($_SERVER['DOCUMENT_ROOT'])) != $_SERVER['DOCUMENT_ROOT']) { + $logo = $_SERVER['DOCUMENT_ROOT'].$settings->get('fax','cover_logo'); } else { - $logo = $setting->get('fax','cover_logo'); + $logo = $settings->get('fax','cover_logo'); } } } @@ -497,7 +492,7 @@ if (!function_exists('fax_split_dtmf')) { $pdf->SetFont($pdf_font, "", 12); $pdf->SetXY($x + 2.0, $y + 1.65); if (defined('STDIN') || ($_REQUEST['submit'] != '' && $_REQUEST['submit'] != 'preview')) { - $date = new DateTime('now', new DateTimeZone( $setting->get('domain','time_zone', date_default_timezone_get() ) )); + $date = new DateTime('now', new DateTimeZone( $settings->get('domain','time_zone', date_default_timezone_get() ) )); $pdf->Write(0.3, $date->format('d M Y @ h:i:s A')); } $pdf->SetXY($x + 2.0, $y + 1.95); @@ -569,7 +564,7 @@ if (!function_exists('fax_split_dtmf')) { } else { //determine cover message box height, and difference, to adjust footer position accordingly - $cover_message_height = $setting->get('fax','cover_message_height'); + $cover_message_height = $settings->get('fax','cover_message_height'); $cover_message_height = (float) ($cover_message_height ?? 6.15); $height_difference = 6.15 - $cover_message_height; @@ -677,7 +672,7 @@ if (!function_exists('fax_split_dtmf')) { } //prepare variables send the fax - $mail_from_address = (!empty($setting->get('fax','smtp_from'))) ? $setting->get('fax','smtp_from') : $setting->get('email','smtp_from'); + $mail_from_address = (!empty($settings->get('fax','smtp_from'))) ? $settings->get('fax','smtp_from') : $settings->get('email','smtp_from'); //get the fax mail to address and fax prefix $sql = "select * from v_fax where fax_uuid = :fax_uuid "; @@ -805,7 +800,7 @@ if (!function_exists('fax_split_dtmf')) { //send the external call $fax_variables = ''; - foreach($setting->get('fax','variable') as $variable) { + foreach($settings->get('fax','variable') as $variable) { $fax_variables .= $variable.","; } } @@ -897,7 +892,7 @@ if (!defined('STDIN')) { $sql .= "and cp.phone_type_fax = 1 "; $sql .= "and cp.phone_number is not null "; $sql .= "and cp.phone_number <> '' "; - if ($setting->get('contact','permissions', false)) { + if ($settings->get('contact','permissions', false)) { if (is_array($user_group_uuids) && @sizeof($user_group_uuids) != 0) { //only show contacts assigned to current user's group(s) and those not assigned to any group $sql .= "and ("; @@ -1013,7 +1008,7 @@ if (!defined('STDIN')) { echo "
\n"; echo "
".$text['header-new_fax']."
\n"; echo "
\n"; - echo button::create(['type'=>'button','label'=>$text['button-back'],'icon'=>$setting->get('theme','button_icon_back'),'id'=>'btn_back','style'=>'margin-right: 15px;','link'=>'fax.php']); + echo button::create(['type'=>'button','label'=>$text['button-back'],'icon'=>$settings->get('theme','button_icon_back'),'id'=>'btn_back','style'=>'margin-right: 15px;','link'=>'fax.php']); if ($domain_enabled == true) { echo button::create(['type'=>'submit','label'=>$text['button-preview'],'icon'=>'eye','name'=>'submit','value'=>'preview']); echo button::create(['type'=>'submit','label'=>$text['button-send'],'icon'=>'paper-plane','id'=>'btn_save','name'=>'submit','value'=>'send','style'=>'margin-left: 15px;']); @@ -1036,7 +1031,7 @@ if (!defined('STDIN')) { echo " ".$text['label-fax-header']."\n"; echo "
\n"; - echo " \n"; + echo " \n"; echo "
\n"; echo " ".$text['description-fax-header']."\n"; echo "
\n"; echo " \n"; echo "
\n"; echo " ".$text['description-fax-resolution']."\n"; @@ -1134,9 +1129,9 @@ if (!defined('STDIN')) { echo "
\n"; echo " \n"; echo "
\n"; echo " ".$text['description-fax-page-size']."\n"; @@ -1144,7 +1139,7 @@ if (!defined('STDIN')) { echo "
\n"; - echo " \n"; + echo " \n"; echo "
\n"; echo " ".$text['description-fax-message']."\n"; echo "
\n"; - echo " \n"; + echo " \n"; echo "
\n"; echo " ".$text['description-fax-footer']."\n"; echo "
".$text['label-caller_destination']."".$text['label-caller_destination']."".$row['extension']." ".escape($row['extension_name'])."".$row['extension']." ".escape($row['extension_name'])."