From 6fa4da361212eb72bd506d6724427884d8b1cb3f Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Fri, 4 Dec 2015 21:09:25 +0300 Subject: [PATCH 01/17] Fix. send fax by user listed in fax server list --- app/fax/fax_send.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/app/fax/fax_send.php b/app/fax/fax_send.php index b5491287a0..6307d28f68 100644 --- a/app/fax/fax_send.php +++ b/app/fax/fax_send.php @@ -58,13 +58,17 @@ if (!$included) { $fax_uuid = check_str($_REQUEST["id"]); if (if_group("superadmin") || if_group("admin")) { //show all fax extensions - $sql = "select * from v_fax "; + $sql = "select fax_uuid, fax_extension, fax_caller_id_name, fax_caller_id_number, "; + $sql .= "accountcode, fax_send_greeting "; + $sql .= "from v_fax "; $sql .= "where domain_uuid = '".$_SESSION['domain_uuid']."' "; $sql .= "and fax_uuid = '$fax_uuid' "; } else { //show only assigned fax extensions - $sql = "select * from v_fax as f, v_fax_users as u "; + $sql = "select f.fax_uuid, f.fax_extension, f.fax_caller_id_name, f.fax_caller_id_number, "; + $sql .= "f.accountcode, f.fax_send_greeting "; + $sql .= "from v_fax as f, v_fax_users as u "; $sql .= "where f.fax_uuid = u.fax_uuid "; $sql .= "and f.domain_uuid = '".$_SESSION['domain_uuid']."' "; $sql .= "and f.fax_uuid = '$fax_uuid' "; @@ -101,7 +105,7 @@ if (!$included) { } //set the fax directory - $fax_dir = $_SESSION['switch']['storage']['dir'].'/fax'.((count($_SESSION["domains"]) > 1) ? '/'.$_SESSION['domain_name'] : null); + $fax_dir = $_SESSION['switch']['storage']['dir'].'/fax/'.$_SESSION['domain_name']; // set fax cover font to generate pdf $fax_cover_font = $_SESSION['fax']['cover_font']['text']; @@ -703,6 +707,7 @@ function fax_split_dtmf(&$fax_number, &$fax_dtmf){ foreach ($fax_numbers as $fax_number) { $dial_string = $common_dial_string; + fax_split_dtmf($fax_number, $fax_dtmf); //prepare the fax command From c76edde6d30886ac86bb75292cea8fd03298661c Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Tue, 8 Dec 2015 16:16:54 +0300 Subject: [PATCH 02/17] Add. Web UI to monitor for fax queue. --- app/fax/app_config.php | 7 ++ app/fax/app_languages.php | 21 ++++ app/fax/fax.php | 3 + app/fax/fax_active.php | 136 +++++++++++++++++++++++ app/fax/fax_active_inc.php | 222 +++++++++++++++++++++++++++++++++++++ 5 files changed, 389 insertions(+) create mode 100644 app/fax/fax_active.php create mode 100644 app/fax/fax_active_inc.php diff --git a/app/fax/app_config.php b/app/fax/app_config.php index 83fe88019d..838ecf936f 100644 --- a/app/fax/app_config.php +++ b/app/fax/app_config.php @@ -146,6 +146,13 @@ $apps[$x]['permissions'][$y]['name'] = 'fax_file_delete'; $apps[$x]['permissions'][$y]['groups'][] = 'superadmin'; $apps[$x]['permissions'][$y]['groups'][] = 'admin'; + $y++; + $apps[$x]['permissions'][$y]['name'] = 'fax_active_view'; + $apps[$x]['permissions'][$y]['groups'][] = 'superadmin'; + $apps[$x]['permissions'][$y]['groups'][] = 'admin'; + $y++; + $apps[$x]['permissions'][$y]['name'] = 'fax_active_all'; + $apps[$x]['permissions'][$y]['groups'][] = 'superadmin'; //schema details $y = 0; //table array index diff --git a/app/fax/app_languages.php b/app/fax/app_languages.php index 5ab3463d98..2cb1bbd38d 100644 --- a/app/fax/app_languages.php +++ b/app/fax/app_languages.php @@ -330,6 +330,17 @@ $text['label-log']['de-at'] = "Log"; $text['label-log']['ro'] = "Log"; $text['label-log']['he'] = ""; +$text['label-active']['en-us'] = "Active"; +$text['label-active']['es-cl'] = ""; +$text['label-active']['pt-pt'] = ""; +$text['label-active']['fr-fr'] = ""; +$text['label-active']['pt-br'] = ""; +$text['label-active']['pl'] = ""; +$text['label-active']['sv-se'] = ""; +$text['label-active']['de-at'] = ""; +$text['label-active']['ro'] = ""; +$text['label-active']['he'] = ""; + $text['label-location']['en-us'] = "Location"; $text['label-location']['es-cl'] = "Localización"; $text['label-location']['pt-pt'] = "Localização"; @@ -2068,4 +2079,14 @@ $text['button-add']['de-at'] = "Hinzufügen"; $text['button-add']['ro'] = "Adaugă"; $text['button-add']['he'] = "הוספה"; +$text['button-show_all']['en-us'] = "Show All"; +$text['button-show_all']['es-cl'] = "Mostrar Todos"; +$text['button-show_all']['pt-pt'] = "Mostrar Todos"; +$text['button-show_all']['fr-fr'] = "Montrer Tout"; +$text['button-show_all']['pt-br'] = "Mostrar Todos"; +$text['button-show_all']['pl'] = "Pokaż Wszystkie"; +$text['button-show_all']['uk'] = "Показати всі"; +$text['button-show_all']['de-at'] = "Alle anzeigen"; +$text['button-show_all']['he'] = ""; + ?> \ No newline at end of file diff --git a/app/fax/fax.php b/app/fax/fax.php index 81af0c8441..5fb50ed436 100644 --- a/app/fax/fax.php +++ b/app/fax/fax.php @@ -170,6 +170,9 @@ else { if (permission_exists('fax_log_view')) { echo " ".$text['label-log'].""; } + if (permission_exists('fax_active_view')) { + echo " ".$text['label-active'].""; + } echo " \n"; echo " ".$row['fax_description']." \n"; echo " "; diff --git a/app/fax/fax_active.php b/app/fax/fax_active.php new file mode 100644 index 0000000000..a70bcc8eb6 --- /dev/null +++ b/app/fax/fax_active.php @@ -0,0 +1,136 @@ + + Portions created by the Initial Developer are Copyright (C) 2008-2012 + the Initial Developer. All Rights Reserved. + + Contributor(s): + Mark J Crane +*/ +include "root.php"; +require_once "resources/require.php"; +require_once "resources/check_auth.php"; +if (permission_exists('fax_active_view')) { + //access granted +} +else { + echo "access denied"; + exit; +} + +//add multi-lingual support + $language = new text; + $text = $language->get(); + +//get the HTTP values and set as variables + $show = trim($_REQUEST["show"]); + if ($show != "all") { $show = ''; } + +// + $fax_uuid = false; + if(isset($_REQUEST['id'])) { + $fax_uuid = check_str($_REQUEST["id"]); + } + +//show the header + $document['title'] = $text['title']; + require_once "resources/header.php"; + +//ajax for refresh + ?> + +\n"; +echo "\n"; +echo "


"; + +require_once "resources/footer.php"; + +/* +// deprecated functions for this page + + function get_park_cmd(uuid, context) { + cmd = \"uuid_transfer \"+uuid+\" -bleg *6000 xml \"+context; + return escape(cmd); + } + + function get_record_cmd(uuid, prefix, name) { + cmd = \"uuid_record \"+uuid+\" start ".$_SESSION['switch']['recordings']['dir']."/".$_SESSION['domain_name']."/archive/".date("Y")."/".date("M")."/".date("d")."/\"+uuid+\".wav\"; + return escape(cmd); + } +*/ +?> \ No newline at end of file diff --git a/app/fax/fax_active_inc.php b/app/fax/fax_active_inc.php new file mode 100644 index 0000000000..17bac8604b --- /dev/null +++ b/app/fax/fax_active_inc.php @@ -0,0 +1,222 @@ + + Portions created by the Initial Developer are Copyright (C) 2008-2012 + the Initial Developer. All Rights Reserved. + + Contributor(s): + Mark J Crane +*/ +include "root.php"; +require_once "resources/require.php"; +require_once "resources/check_auth.php"; +if (permission_exists('fax_active_view')) { + //access granted +} +else { + echo "access denied"; + exit; +} + +if ((!permission_exists('fax_active_all')) && ($show == 'all')) { + echo "access denied"; + exit; +} + +$fax_uuid = false; +if(isset($_REQUEST['id'])) { + $fax_uuid = check_str($_REQUEST["id"]); +} + +//add multi-lingual support + $language = new text; + $text = $language->get(); + +//get the HTTP values and set as variables + $show = trim($_REQUEST["show"]); + if ($show != "all") { $show = ''; } + +//include theme config for button images + include_once("themes/".$_SESSION['domain']['template']['name']."/config.php"); + +$where = 'where (1 = 1)'; + +if($show !== 'all'){ + $where .= 'and (t3.domain_name = \'' . check_str($_SESSION['domain_name']) . '\')'; +} +else if($fax_uuid){ + if(!permission_exists('fax_active_all')){ + $where .= 'and (t3.domain_name = \'' . check_str($_SESSION['domain_name']) . '\')'; + } + $where .= 'and (t1.fax_uuid =\'' . check_str($fax_uuid) . '\')'; +} + + $sql = <<prepare(check_sql($sql)); + if ($prep_statement) { + if($prep_statement->execute()) { + $result = $prep_statement->fetchAll(PDO::FETCH_ASSOC); + } + } + unset($prep_statement, $sql, $where); + +//if the connnection is available then run it and return the results + if ($result === false) { + var_dump($db->errorInfo()); + $msg = "
".$text['confirm-socket']."
"; + echo "
\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "
".$text['label-message']."
$msg
\n"; + echo "
\n"; + } + else { + //define js function call var + $onhover_pause_refresh = " onmouseover='refresh_stop();' onmouseout='refresh_start();'"; + + //show buttons + echo ""; + echo " "; + echo " "; + echo " "; + echo " "; + echo "
"; + echo " \"".$text['label-refresh_pause']."\""; + echo " "; + if (permission_exists('fax_active_all')) { + if ($show == "all") { + echo " \n"; + } + else { + echo " \n"; + } + } + echo "
"; + + // show title + echo "".'Fax queue'.""; + echo "

\n"; + echo 'Current status of fax queue' . "\n"; + echo "

\n"; + + //set the alternating color for each row + $c = 0; + $row_style["0"] = "row_style0"; + $row_style["1"] = "row_style1"; + + //show the results + echo "
\n"; + + //show headers + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + + echo "\n"; + echo "\n"; + + foreach ($result as &$row) { + $fax_uri = $row['uri']; + $domain_name = $row['domain_name']; + $task_enabled = ($row['interrupted'] == 'true') ? 'Disable': 'Enable'; + $task_status = 'Wait'; + $task_next_time = $row['next_time']; + + if($row['status'] > 0){ + if($row['status'] <= 3){ + $task_status = 'Execute'; + } + else if($row['status'] == 10){ + $task_status = 'Success'; + } + else{ + $task_status = 'Fail'; + } + } + + $fax_server = $row['fax_server_name']; + if ($show == 'all') { + $fax_server .= '@' . $domain_name; + } + + $task_files = ''; + if(!empty($row['fax_file'])){ + $task_files .= ' ' . basename($row['fax_file']); + } + if(!empty($row['wav_file'])){ + $task_files .= '
 ' . basename($row['wav_file']); + } else if(!empty($row['greeting'])){ + $task_files .= '
 ' . basename($row['greeting']); + } + + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + + echo "\n"; + echo "\n"; + $c = ($c) ? 0 : 1; + } + + echo "\n"; + echo "\n"; + echo "
". 'Fax' . "". 'Enabled' . "". 'Status' . "". 'Next time' . "". 'Files' . "". 'URI' . "
" . $fax_server . " " . $task_enabled . " " . $task_status . " " . $task_next_time . " " . $task_files . " " . $fax_uri . " ".$v_link_label_delete."
\n"; + } +?> \ No newline at end of file From 279a745e4f3505cd11ce784acb7129d3fb34b185 Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Tue, 8 Dec 2015 16:42:13 +0300 Subject: [PATCH 03/17] Add. Ability to delete fax queue element --- app/fax/fax_active.php | 2 +- app/fax/fax_active_exec.php | 74 +++++++++++++++++++++++++++++++++++++ app/fax/fax_active_inc.php | 2 +- 3 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 app/fax/fax_active_exec.php diff --git a/app/fax/fax_active.php b/app/fax/fax_active.php index a70bcc8eb6..4729e91ab8 100644 --- a/app/fax/fax_active.php +++ b/app/fax/fax_active.php @@ -95,7 +95,7 @@ else { //call controls function hangup(uuid) { if (confirm("")) { - send_cmd('fax_active_exec.php?cmd=uuid_kill%20'+uuid); + send_cmd('fax_active_exec.php?cmd=delete&id='+uuid); } } diff --git a/app/fax/fax_active_exec.php b/app/fax/fax_active_exec.php new file mode 100644 index 0000000000..24b38ac2d0 --- /dev/null +++ b/app/fax/fax_active_exec.php @@ -0,0 +1,74 @@ +0) { + $cmd = trim(check_str($_GET['cmd'])); + $fax_uuid = trim(check_str($_GET['id'])); + } + +//authorized commands + if ($cmd == 'delete') { + //authorized; + } else { + //not found. this command is not authorized + echo "access denied"; + exit; + } + +//Command + if ($cmd == 'delete') { + if($fax_uuid){ + $sql = <<exec($sql); + // if($result === false){ + // var_dump($db->errorInfo()); + // } + } + } +?> \ No newline at end of file diff --git a/app/fax/fax_active_inc.php b/app/fax/fax_active_inc.php index 17bac8604b..b8b791c5eb 100644 --- a/app/fax/fax_active_inc.php +++ b/app/fax/fax_active_inc.php @@ -210,7 +210,7 @@ HERE; echo "" . $task_files . " \n"; echo "" . $fax_uri . " \n"; - echo "".$v_link_label_delete."\n"; + echo "".$v_link_label_delete."\n"; echo "\n"; $c = ($c) ? 0 : 1; } From c5e24411619610a91a6778276ecdeb4e04e38c98 Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Wed, 9 Dec 2015 12:43:40 +0300 Subject: [PATCH 04/17] Add. mail templates for fax server responses. --- .../install/scripts/app/fax/app_languages.lua | 9 +++ .../app/fax/resources/scripts/queue/next.lua | 31 +++++--- .../app/fax/resources/scripts/queue/retry.lua | 73 ++++++++++++++----- .../app/fax/resources/scripts/queue/tasks.lua | 61 +++++++++++++++- .../templates/en/us/outbound/fail/body.tpl | 51 +++++++++++++ .../templates/en/us/outbound/fail/subject.tpl | 1 + .../templates/en/us/outbound/success/body.tpl | 51 +++++++++++++ .../en/us/outbound/success/subject.tpl | 1 + .../resources/functions/file_exists.lua | 6 +- 9 files changed, 249 insertions(+), 35 deletions(-) create mode 100644 resources/install/scripts/app/fax/app_languages.lua create mode 100644 resources/install/scripts/app/fax/resources/templates/en/us/outbound/fail/body.tpl create mode 100644 resources/install/scripts/app/fax/resources/templates/en/us/outbound/fail/subject.tpl create mode 100644 resources/install/scripts/app/fax/resources/templates/en/us/outbound/success/body.tpl create mode 100644 resources/install/scripts/app/fax/resources/templates/en/us/outbound/success/subject.tpl diff --git a/resources/install/scripts/app/fax/app_languages.lua b/resources/install/scripts/app/fax/app_languages.lua new file mode 100644 index 0000000000..7983512b77 --- /dev/null +++ b/resources/install/scripts/app/fax/app_languages.lua @@ -0,0 +1,9 @@ +text = text or {}; + +text['message-send_success'] = {} +text['message-send_success']['en-us'] = "We are happy to report the fax was sent successfully. It has been attached for your records." + +text['message-send_fail'] = {} +text['message-send_fail']['en-us'] = "We are sorry the fax failed to go through. It has been attached. Please check the number, and if it was correct you might consider emailing it instead." + +return text \ No newline at end of file diff --git a/resources/install/scripts/app/fax/resources/scripts/queue/next.lua b/resources/install/scripts/app/fax/resources/scripts/queue/next.lua index 4780867a1d..874171cca7 100644 --- a/resources/install/scripts/app/fax/resources/scripts/queue/next.lua +++ b/resources/install/scripts/app/fax/resources/scripts/queue/next.lua @@ -1,6 +1,7 @@ require "resources.functions.config" require "resources.functions.sleep" +require "resources.functions.file_exists" local log = require "resources.functions.log".next_fax_task local Tasks = require "app.fax.resources.scripts.queue.tasks" local Esl = require "resources.functions.esl" @@ -13,17 +14,27 @@ local FAX_OPTIONS = { "fax_use_ecm=false,fax_enable_t38=false,fax_enable_t38_request=false,fax_disable_v17=false"; } -local function task_send_mail(task) +local function task_send_mail(task, err) local number_dialed = task.uri:match("/([^/]-)%s*$") - Tasks.send_mail_task(task, { - "Fax to: " .. number_dialed .. " FAILED", - table.concat{ - "We are sorry the fax failed to go through. ", - "It has been attached. Please check the number " .. number_dialed .. ", ", - "and if it was correct you might consider emailing it instead.", - }} - ) + local Text = require "resources.functions.text" + local text = Text.new("app.fax.app_languages") + + local env = { + destination_number = number_dialed:match("^([^@]*)"); + hangup_cause = err; + message = text['message-send_fail']; + } + + local body = Tasks.build_template(task, 'outbound/fail/body', env) + local subject = Tasks.build_template(task, 'outbound/fail/subject', env) + + if not subject then + log.warning("Can not find template for email") + subject = "Fax to: " .. number_dialed .. " FAILED" + end + + Tasks.send_mail_task(task, {subject, body}, nil, file_exists(task.fax_file)) end local function next_task() @@ -56,7 +67,7 @@ local function next_task() Tasks.wait_task(task, false, info) if task.status ~= 0 then Tasks.remove_task(task) - task_send_mail(task) + task_send_mail(task, tostring(info)) end log.noticef('Can not originate to `%s` cause: %s: %s ', task.uri, tostring(status), tostring(info)) else diff --git a/resources/install/scripts/app/fax/resources/scripts/queue/retry.lua b/resources/install/scripts/app/fax/resources/scripts/queue/retry.lua index 1d634ea725..3cc20dbf43 100644 --- a/resources/install/scripts/app/fax/resources/scripts/queue/retry.lua +++ b/resources/install/scripts/app/fax/resources/scripts/queue/retry.lua @@ -1,8 +1,7 @@ -- include libraries require "resources.functions.config"; - require "resources.functions.explode"; require "resources.functions.split"; - require "resources.functions.count"; + require "resources.functions.file_exists"; local log = require "resources.functions.log".fax_retry local Database = require "resources.functions.database" @@ -28,6 +27,10 @@ local dbh = Database.new('system') +-- Global environment + default_language = env:getHeader("default_language") + default_dialect = env:getHeader("default_dialect") + -- Channel/FusionPBX variables local uuid = env:getHeader("uuid") local fax_queue_task_session = env:getHeader('fax_queue_task_session') @@ -312,18 +315,32 @@ --Success log.infof("RETRY STATS SUCCESS: GATEWAY[%s]", fax_options); + Tasks.remove_task(task) + + local Text = require "resources.functions.text" + local text = Text.new("app.fax.app_languages") + + local env = { + fax_options = fax_options; + destination_number = number_dialed:match("^([^@]*)"); + document_transferred_pages = fax_document_transferred_pages; + document_total_pages = fax_document_total_pages; + message = text['message-send_success']; + } + + local body = Tasks.build_template(task, 'outbound/success/body', env) + local subject = Tasks.build_template(task, 'outbound/success/subject', env) + + if not subject then + log.warning("Can not find template for email") + subject = "Fax to: " .. number_dialed .. " SENT" + end + + Tasks.send_mail_task(task, {subject, body}, uuid, file_exists(fax_file)) + if keep_local == "false" then os.remove(fax_file); end - - Tasks.remove_task(task) - Tasks.send_mail_task(task, { - "Fax to: " .. number_dialed .. " SENT", - table.concat{ - "We are happy to report the fax was sent successfully.", - "It has been attached for your records.", - }}, uuid - ) end if fax_success ~= "1" then @@ -345,14 +362,32 @@ Tasks.wait_task(task, answered, hangup_cause_q850) if task.status ~= 0 then Tasks.remove_task(task) - Tasks.send_mail_task(task, { - "Fax to: " .. number_dialed .. " FAILED", - table.concat{ - "We are sorry the fax failed to go through. ", - "It has been attached. Please check the number "..number_dialed..", ", - "and if it was correct you might consider emailing it instead.", - }}, uuid - ) + + local Text = require "resources.functions.text" + local text = Text.new("app.fax.app_languages") + + local env = { + fax_options = fax_options; + destination_number = number_dialed:match("^([^@]*)"); + document_transferred_pages = fax_document_transferred_pages; + document_total_pages = fax_document_total_pages; + hangup_cause = hangup_cause; + hangup_cause_q850 = hangup_cause_q850; + fax_result_code = fax_result_code; + fax_result_text = fax_result_text; + message = text['message-send_fail']; + } + + local body = Tasks.build_template(task, 'outbound/fail/body', env) + local subject = Tasks.build_template(task, 'outbound/fail/subject', env) + + if not subject then + log.warning("Can not find template for email") + subject = "Fax to: " .. number_dialed .. " FAILED" + end + + Tasks.send_mail_task(task, {subject, body}, uuid, file_exists(fax_file)) + end end end diff --git a/resources/install/scripts/app/fax/resources/scripts/queue/tasks.lua b/resources/install/scripts/app/fax/resources/scripts/queue/tasks.lua index e6ba83835f..33cd5c0f89 100644 --- a/resources/install/scripts/app/fax/resources/scripts/queue/tasks.lua +++ b/resources/install/scripts/app/fax/resources/scripts/queue/tasks.lua @@ -203,8 +203,6 @@ local function wait_task(task, answered, q850) task.uuid ) - print(sql) - local ok, err = db:query( sql ) if not ok then return nil, err end @@ -245,7 +243,7 @@ local function cleanup_tasks() db:query(remove_finished_tasks_sql) end -local function send_mail_task(task, message, call_uuid) +local function send_mail_task(task, message, call_uuid, file) if not task.reply_address or #task.reply_address == 0 then return end @@ -257,7 +255,61 @@ local function send_mail_task(task, message, call_uuid) ["X-FusionPBX-Email-Type"] = 'email2fax'; } - return send_mail(mail_x_headers, task.reply_address, message) + return send_mail(mail_x_headers, task.reply_address, message, file) +end + +local function read_file(name, mode) + local f, err, code = io.open(name, mode or 'rb') + if not f then return nil, err, code end + local data = f:read("*all") + f:close() + return data +end + +local function read_template(app, name, lang) + local default_language_path = 'en/us' + + local full_path_tpl = scripts_dir .. '/app/' .. app .. '/resources/templates/{lang}/' .. name .. '.tpl' + + local path + + if lang then + path = file_exists((full_path_tpl:gsub('{lang}', lang))) + end + + if (not path) and (lang ~= default_language_path) then + path = file_exists((full_path_tpl:gsub('{lang}', default_language_path))) + end + + if path then + return read_file(path) + end +end + +local function build_template(task, templ, env) + local lang + + if default_language and default_dialect then + lang = (default_language .. '/' .. default_dialect):lower() + else + local settings = Settings.new(dbh or 'system', task.domain_name, task.domain_uuid) + lang = settings:get('domain', 'language', 'code') + if lang then lang = lang:gsub('%-', '/'):lower() end + end + + local body = read_template('fax', templ, lang) + + body = body:gsub("[^\\](${.-})", function(name) + name = name:sub(3, -2) + if type(env) == 'table' then + return env[name] or '' + end + if type(env) == 'function' then + return env(name) or '' + end + end) + + return body end return { @@ -274,4 +326,5 @@ return { release_task = release_task; cleanup_tasks = cleanup_tasks; send_mail_task = send_mail_task; + build_template = build_template; } diff --git a/resources/install/scripts/app/fax/resources/templates/en/us/outbound/fail/body.tpl b/resources/install/scripts/app/fax/resources/templates/en/us/outbound/fail/body.tpl new file mode 100644 index 0000000000..0a74af6208 --- /dev/null +++ b/resources/install/scripts/app/fax/resources/templates/en/us/outbound/fail/body.tpl @@ -0,0 +1,51 @@ + + + + + + + + +
+ Send fax fail +
+ + + + + + + + + + + + + + + + + +
+ To + + ${destination_number} +
+ Pages + + ${document_transferred_pages}/${document_total_pages} +
+ Message + + ${message} +
+ Error + + ${hangup_cause}/${fax_result_code}/${fax_result_text} +
+
+ \ No newline at end of file diff --git a/resources/install/scripts/app/fax/resources/templates/en/us/outbound/fail/subject.tpl b/resources/install/scripts/app/fax/resources/templates/en/us/outbound/fail/subject.tpl new file mode 100644 index 0000000000..0b4efa53ac --- /dev/null +++ b/resources/install/scripts/app/fax/resources/templates/en/us/outbound/fail/subject.tpl @@ -0,0 +1 @@ +Fax to: ${destination_number} FAILED \ No newline at end of file diff --git a/resources/install/scripts/app/fax/resources/templates/en/us/outbound/success/body.tpl b/resources/install/scripts/app/fax/resources/templates/en/us/outbound/success/body.tpl new file mode 100644 index 0000000000..073e4c6db6 --- /dev/null +++ b/resources/install/scripts/app/fax/resources/templates/en/us/outbound/success/body.tpl @@ -0,0 +1,51 @@ + + + + + + + + +
+ Send fax successfully +
+ + + + + + + + + + + + + + + + + +
+ To + + ${destination_number} +
+ Pages + + ${document_transferred_pages} +
+ Message + + ${message} +
+ Options + + ${fax_options} +
+
+ \ No newline at end of file diff --git a/resources/install/scripts/app/fax/resources/templates/en/us/outbound/success/subject.tpl b/resources/install/scripts/app/fax/resources/templates/en/us/outbound/success/subject.tpl new file mode 100644 index 0000000000..a1e835ddd1 --- /dev/null +++ b/resources/install/scripts/app/fax/resources/templates/en/us/outbound/success/subject.tpl @@ -0,0 +1 @@ +Fax to: ${destination_number} sent \ No newline at end of file diff --git a/resources/install/scripts/resources/functions/file_exists.lua b/resources/install/scripts/resources/functions/file_exists.lua index 76a31c5126..aece58bd5f 100644 --- a/resources/install/scripts/resources/functions/file_exists.lua +++ b/resources/install/scripts/resources/functions/file_exists.lua @@ -1,6 +1,8 @@ --check if a file exists function file_exists(name) - local f=io.open(name,"r") - if f~=nil then io.close(f) return true else return false end + local f = io.open(name, "r") + if not f then return end + f:close() + return name end \ No newline at end of file From 5cb8aa1d2afa59dbe82c4317eea624a41c91d8db Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Wed, 9 Dec 2015 13:00:42 +0300 Subject: [PATCH 05/17] Change. `Send` button redirect to `Active` page. --- app/fax/fax_send.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/fax/fax_send.php b/app/fax/fax_send.php index 1d016b4171..35b17e5a2b 100644 --- a/app/fax/fax_send.php +++ b/app/fax/fax_send.php @@ -768,7 +768,12 @@ function fax_split_dtmf(&$fax_number, &$fax_dtmf){ if (!$included) { //redirect the browser $_SESSION["message"] = $response; - header("Location: fax_files.php?id=".$fax_uuid."&box=sent"); + if (permission_exists('fax_active_view')) { + header("Location: fax_active.php?id=".$fax_uuid); + } + else { + header("Location: fax_files.php?id=".$fax_uuid."&box=sent"); + } exit; } From 199b7e0def54a4eaeb7f39a00a53b14819b22084 Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Wed, 9 Dec 2015 13:21:37 +0300 Subject: [PATCH 06/17] Add. Allows select greeting. --- app/fax/fax_edit.php | 103 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/app/fax/fax_edit.php b/app/fax/fax_edit.php index 8a23a3cf4c..83fabbae3d 100644 --- a/app/fax/fax_edit.php +++ b/app/fax/fax_edit.php @@ -686,7 +686,108 @@ if (count($_POST)>0 && strlen($_POST["persistformvar"]) == 0) { echo " ".$text['label-fax_send_greeting']."\n"; echo "\n"; echo "\n"; - echo " \n"; + if (permission_exists('fax_extension_add') || permission_exists('fax_extension_edit')) { + echo "\n"; + echo "\n"; + } + echo " \n"; echo "
\n"; echo " ".$text['description-fax_send_greeting']."\n"; echo "\n"; From 742a782183093caf361a54295cd0b7bdcedc5370 Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Wed, 9 Dec 2015 13:37:32 +0300 Subject: [PATCH 07/17] Fix. Use `Test` interface to translate UI. --- app/fax/app_languages.php | 24 ++++++++++++++++++++++++ app/fax/fax_active_inc.php | 26 +++++++++++++------------- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/app/fax/app_languages.php b/app/fax/app_languages.php index 2cb1bbd38d..3531c78fec 100644 --- a/app/fax/app_languages.php +++ b/app/fax/app_languages.php @@ -2089,4 +2089,28 @@ $text['button-show_all']['uk'] = "Показати всі"; $text['button-show_all']['de-at'] = "Alle anzeigen"; $text['button-show_all']['he'] = ""; +$text['fax-active_title']['en-us'] = "Fax queue"; + +$text['fax-active_description']['en-us'] = "Current status of fax queue"; + +$text['fax-active_title_fax_server']['en-us'] = "Fax"; + +$text['fax-active_title_enabled']['en-us'] = "Enabled"; + +$text['fax-active_title_status']['en-us'] = "Status"; + +$text['fax-active_title_next_time']['en-us'] = "Next time"; + +$text['fax-active_title_files']['en-us'] = "Files"; + +$text['fax-active_title_uri']['en-us'] = "URI"; + +$text['fax-active_status_wait']['en-us'] = "Wait"; + +$text['fax-active_status_execute']['en-us'] = "Execute"; + +$text['fax-active_status_success']['en-us'] = "Success"; + +$text['fax-active_status_fail']['en-us'] = "Fail"; + ?> \ No newline at end of file diff --git a/app/fax/fax_active_inc.php b/app/fax/fax_active_inc.php index b8b791c5eb..9e13e1cc6a 100644 --- a/app/fax/fax_active_inc.php +++ b/app/fax/fax_active_inc.php @@ -106,7 +106,7 @@ HERE; //if the connnection is available then run it and return the results if ($result === false) { var_dump($db->errorInfo()); - $msg = "
".$text['confirm-socket']."
"; + $msg = "
".$text['message-fail']."
"; echo "
\n"; echo "\n"; echo "\n"; @@ -142,9 +142,9 @@ HERE; echo "
"; // show title - echo "".'Fax queue'.""; + echo "".$text['fax-active_title'].""; echo "

\n"; - echo 'Current status of fax queue' . "\n"; + echo $text['fax-active_description']."\n"; echo "

\n"; //set the alternating color for each row @@ -158,12 +158,12 @@ HERE; //show headers echo "\n"; echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; echo "\n"; echo "\n"; @@ -172,18 +172,18 @@ HERE; $fax_uri = $row['uri']; $domain_name = $row['domain_name']; $task_enabled = ($row['interrupted'] == 'true') ? 'Disable': 'Enable'; - $task_status = 'Wait'; + $task_status = $text['fax-active_status_wait']; $task_next_time = $row['next_time']; if($row['status'] > 0){ if($row['status'] <= 3){ - $task_status = 'Execute'; + $task_status = $text['fax-active_status_execute']; } else if($row['status'] == 10){ - $task_status = 'Success'; + $task_status = $text['fax-active_status_success']; } else{ - $task_status = 'Fail'; + $task_status = $text['fax-active_status_fail']; } } From c0ec50e46c9bae1a5a9fff2a8515d4ecd147d615 Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Wed, 9 Dec 2015 13:51:25 +0300 Subject: [PATCH 08/17] Fix. forgotten images. --- app/fax/resources/images/refresh_active.gif | Bin 0 -> 1079 bytes app/fax/resources/images/refresh_paused.png | Bin 0 -> 501 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/fax/resources/images/refresh_active.gif create mode 100644 app/fax/resources/images/refresh_paused.png diff --git a/app/fax/resources/images/refresh_active.gif b/app/fax/resources/images/refresh_active.gif new file mode 100644 index 0000000000000000000000000000000000000000..305457831c3f47939d634650660e859f50f18224 GIT binary patch literal 1079 zcmZ?wbhEHb6krfw_{_lY|NsA0U~uKimGkG%KYaM`#fum3-o5+$`SYz?x4wP*cIM0( z1|*>PpWDwhB-q(8z|~04fSC~}rT9$q3n zO>tew&yZDRa$!Y@S0^yIF#{CID4C^TqZC^&!;E6k-dQ&1{8}lV<;)-2jBdSFW47#` z1vIJ`t5L{)gBT?kmRz|^`|7L}S{*99_jCT;vIy5ToB7wlqaU~5kYZS7nL_(UfrqBk z(zDj8X?3K$2`jK(z145C(S#4nG^P4aV2xolq_Ej0;4GAuT$!{|vttSOYJI8o;oR@$ zJ^Oz^L6r$xSRh*s)EXo~qSeR&uoa}AU5JbTK#mcJDN5wV2$E5AwtyYvL~c4k^4lFJ R9?wLX4uT2S8kB9p001&weI)<@ literal 0 HcmV?d00001 diff --git a/app/fax/resources/images/refresh_paused.png b/app/fax/resources/images/refresh_paused.png new file mode 100644 index 0000000000000000000000000000000000000000..38937ec1f222094efb05cd3d3c634f752f84deb2 GIT binary patch literal 501 zcmVwBx2>F4R;%NMVn_aJxg_miiOUzd`-l3gn!7VkA&I7c*+DB!%r3QpAguz80Ve)s0dLW`~5+e4hT7Q6`Q>6PhY?hE(21}udC6bM0N(*gquPL7X19qhk(2T)25%jM!% r*LBxEygxiz%}l?3`LprpRloCJ0R6KCvd?rv00000NkvXXu0mjfpda3S literal 0 HcmV?d00001 From 9e001af711c355dc58f649a52464f83b9b7d464e Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Wed, 9 Dec 2015 14:56:02 +0300 Subject: [PATCH 09/17] Fix. Use task db connection to build template. --- .../install/scripts/app/fax/resources/scripts/queue/tasks.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/install/scripts/app/fax/resources/scripts/queue/tasks.lua b/resources/install/scripts/app/fax/resources/scripts/queue/tasks.lua index 33cd5c0f89..6e78bffccb 100644 --- a/resources/install/scripts/app/fax/resources/scripts/queue/tasks.lua +++ b/resources/install/scripts/app/fax/resources/scripts/queue/tasks.lua @@ -292,7 +292,7 @@ local function build_template(task, templ, env) if default_language and default_dialect then lang = (default_language .. '/' .. default_dialect):lower() else - local settings = Settings.new(dbh or 'system', task.domain_name, task.domain_uuid) + local settings = Settings.new(get_db(), task.domain_name, task.domain_uuid) lang = settings:get('domain', 'language', 'code') if lang then lang = lang:gsub('%-', '/'):lower() end end From de1ab1509558cc0e91ac91000718ae740ab6ee2a Mon Sep 17 00:00:00 2001 From: blackc2004 Date: Wed, 9 Dec 2015 14:44:22 -0800 Subject: [PATCH 10/17] test --- app/xml_cdr/app_languages.php | 11 +++++++++ app/xml_cdr/xml_cdr_inc.php | 33 ++++++++++++++++++++++++++ app/xml_cdr/xml_cdr_search.php | 16 ++++++++++++- app/xml_cdr/xml_cdr_statistics.php | 25 +++++++++++++++++++ app/xml_cdr/xml_cdr_statistics_inc.php | 12 +++++++--- 5 files changed, 93 insertions(+), 4 deletions(-) diff --git a/app/xml_cdr/app_languages.php b/app/xml_cdr/app_languages.php index 6e7dad1774..1e57575810 100644 --- a/app/xml_cdr/app_languages.php +++ b/app/xml_cdr/app_languages.php @@ -615,6 +615,17 @@ $text['label-network_addr']['uk'] = ""; $text['label-network_addr']['de-at'] = "Netzwerk Adresse"; $text['label-network_addr']['he'] = "כתובת רשת"; +$text['label-mos_score']['en-us'] = "MOS Score"; +$text['label-mos_score']['es-cl'] = ""; +$text['label-mos_score']['pt-pt'] = ""; +$text['label-mos_score']['fr-fr'] = ""; +$text['label-mos_score']['pt-br'] = ""; +$text['label-mos_score']['pl'] = ""; +$text['label-mos_score']['sv-se'] = ""; +$text['label-mos_score']['uk'] = ""; +$text['label-mos_score']['de-at'] = ""; +$text['label-mos_score']['he'] = ""; + $text['label-name']['en-us'] = "Name"; $text['label-name']['es-cl'] = "Nombre"; $text['label-name']['pt-pt'] = "Nome"; diff --git a/app/xml_cdr/xml_cdr_inc.php b/app/xml_cdr/xml_cdr_inc.php index 911c94f92c..2fc5daf1f8 100644 --- a/app/xml_cdr/xml_cdr_inc.php +++ b/app/xml_cdr/xml_cdr_inc.php @@ -74,8 +74,36 @@ else { $bridge_uuid = check_str($_REQUEST["network_addr"]); $order_by = check_str($_REQUEST["order_by"]); $order = check_str($_REQUEST["order"]); + if (strlen(check_str($_REQUEST["mos_comparison"])) > 0) { + switch(check_str($_REQUEST["mos_comparison"])) { + case 'less': + $mos_comparison = "<"; + break; + case 'greater': + $mos_comparison = ">"; + break; + case 'lessorequal': + $mos_comparison = "<="; + break; + case 'greaterorequal': + $mos_comparison = ">="; + break; + case 'equal': + $mos_comparison = "<"; + break; + case 'notequal': + $mos_comparison = "<>"; + break; + } + } else { + $mos_comparison = ''; + } + //$mos_comparison = check_str($_REQUEST["mos_comparison"]); + $mos_score = check_str($_REQUEST["mos_score"]); } + + //build the sql where string if ($missed == true) { $sql_where_ands[] = "billsec = '0'"; @@ -126,6 +154,7 @@ else { if (strlen($write_codec) > 0) { $sql_where_ands[] = "write_codec like '%".$write_codec."%'"; } if (strlen($remote_media_ip) > 0) { $sql_where_ands[] = "remote_media_ip like '%".$remote_media_ip."%'"; } if (strlen($network_addr) > 0) { $sql_where_ands[] = "network_addr like '%".$network_addr."%'"; } + if (strlen($mos_comparison) > 0 && strlen($mos_score) > 0 ) { $sql_where_ands[] = "rtp_audio_in_mos " . $mos_comparison . " ".$mos_score.""; } //if not admin or superadmin, only show own calls if (!permission_exists('xml_cdr_domain')) { @@ -201,6 +230,9 @@ else { $param .= "&remote_media_ip=".$remote_media_ip; $param .= "&network_addr=".$network_addr; $param .= "&bridge_uuid=".$bridge_uuid; + $param .= "&mos_comparison=".$mos_comparison; + $param .= "&mos_score=".$mos_score; + if ($_GET['showall'] && permission_exists('xml_cdr_all')) { $param .= "&showall=" . $_GET['showall']; } @@ -297,6 +329,7 @@ else { else { $sql .= " limit ".$rows_per_page." offset ".$offset." "; } + $prep_statement = $db->prepare(check_sql($sql)); $prep_statement->execute(); $result = $prep_statement->fetchAll(PDO::FETCH_ASSOC); diff --git a/app/xml_cdr/xml_cdr_search.php b/app/xml_cdr/xml_cdr_search.php index e61e247ed8..50c6e809f8 100644 --- a/app/xml_cdr/xml_cdr_search.php +++ b/app/xml_cdr/xml_cdr_search.php @@ -53,7 +53,7 @@ echo " if ($('#caller_id_number').is(':visible')) { $('#caller_id_number').foc echo " }"; echo " }"; echo ""; - + echo "
\n"; echo "
". 'Fax' . "". 'Enabled' . "". 'Status' . "". 'Next time' . "". 'Files' . "". 'URI' . "" . $text['fax-active_title_fax_server'] . "" . $text['fax-active_title_enabled'] . "" . $text['fax-active_title_status'] . "" . $text['fax-active_title_next_time'] . "" . $text['fax-active_title_files'] . "" . $text['fax-active_title_uri'] . "
\n"; @@ -203,6 +203,20 @@ echo " "; echo " "; echo " "; echo " "; +echo " "; +echo " "; +echo " "; +echo " "; echo " "; echo " "; echo "
".$text['label-network_addr']."
".$text['label-mos_score'].""; +echo " \n"; +echo "

"; diff --git a/app/xml_cdr/xml_cdr_statistics.php b/app/xml_cdr/xml_cdr_statistics.php index c274f921ab..a68fab51af 100644 --- a/app/xml_cdr/xml_cdr_statistics.php +++ b/app/xml_cdr/xml_cdr_statistics.php @@ -43,6 +43,11 @@ else { require_once "resources/header.php"; //page title and description + + echo ""; + echo " "; + echo " "; + echo " "; echo "\n"; echo "\n"; echo " \n"; @@ -65,6 +70,26 @@ else { echo " \n"; echo "\n"; echo "
".$text['label-call-statistics']."
\n"; +#CJB +/* echo "\n"; + echo "\n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo ""; + echo " \n"; + echo "
\n"; + echo " ".$text['label-start_range']."\n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo " "; + echo "\n"; + echo "\n"; + echo "
\n"; + echo ""; +*/ +#CJB //set the style $c = 0; diff --git a/app/xml_cdr/xml_cdr_statistics_inc.php b/app/xml_cdr/xml_cdr_statistics_inc.php index 7dfc6fc2b2..dab016fe17 100644 --- a/app/xml_cdr/xml_cdr_statistics_inc.php +++ b/app/xml_cdr/xml_cdr_statistics_inc.php @@ -141,9 +141,15 @@ else { //$call_seconds_1st_hour = get_call_seconds_between(3600, 0); //if (strlen($call_seconds_1st_hour) == 0) { $call_seconds_1st_hour = 0; } -//round down to the nearest hour - $time = time() - time() % 3600; - +// if (strlen(check_str($_GET['start_stamp_begin'])) > 0 && strlen(check_str($_GET['start_stamp_end'])) > 0 ) { +// $start_date = new DateTime(check_str($_GET['start_stamp_begin'])); +// $end_date = new DateTime(check_str($_GET['start_stamp_end'])); +// $time = $start_date->getTimestamp(); +// } else { + //round down to the nearest hour + $time = time() - time() % 3600; +// } + //call info hour by hour for ($i = 0; $i <= 23; $i++) { $start_epoch = $time - 3600*$i; From cb440de264983f4f9698cb0fb346c079756dc0be Mon Sep 17 00:00:00 2001 From: Matthew Vale Date: Thu, 10 Dec 2015 10:51:38 +0000 Subject: [PATCH 11/17] updated switch version detection will now work with both git and packaged version numbers added bits to detect_switch --- app/system/system.php | 2 +- core/install/resources/classes/detect_switch.php | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/system/system.php b/app/system/system.php index 9129f39707..60cea81bb0 100644 --- a/app/system/system.php +++ b/app/system/system.php @@ -108,7 +108,7 @@ $document['title'] = $text['title-sys-status']; $fp = event_socket_create($_SESSION['event_socket_ip_address'], $_SESSION['event_socket_port'], $_SESSION['event_socket_password']); if ($fp) { $switch_version = event_socket_request($fp, 'api version'); - preg_match("/FreeSWITCH Version (\d+\.\d+\.\d+(?:\.\d+)?).*\(\s*(\d+\w+)\s*\)/", $switch_version, $matches); + preg_match("/FreeSWITCH Version (\d+\.\d+\.\d+(?:\.\d+)?).*\(.*?(\d+\w+)\s*\)/", $switch_version, $matches); $switch_version = $matches[1]; $switch_bits = $matches[2]; echo "\n"; diff --git a/core/install/resources/classes/detect_switch.php b/core/install/resources/classes/detect_switch.php index 4245d5bc61..92ab726465 100644 --- a/core/install/resources/classes/detect_switch.php +++ b/core/install/resources/classes/detect_switch.php @@ -40,10 +40,12 @@ require_once "resources/classes/EventSocket.php"; protected $_major; protected $_minor; protected $_build; + protected $_bits; public function major() { return $this->_major; } public function minor() { return $this->_minor; } public function build() { return $this->_build; } - public function version() { return $this->_major.".".$this->_minor.".".$this->_build; } + public function bits() { return $this->_bits; } + public function version() { return $this->_major.".".$this->_minor.".".$this->_build." (".$this->_bits.")"; } // dirs - detected by from the switch protected $_base_dir = ''; @@ -126,7 +128,7 @@ require_once "resources/classes/EventSocket.php"; throw new Exception('Failed to use event socket'); } $FS_Version = $this->event_socket_request('api version'); - preg_match("/FreeSWITCH Version (\d+)\.(\d+)\.(\d+(?:\.\d+)?)/", $FS_Version, $matches); + preg_match("/FreeSWITCH Version (\d+\.\d+\.\d+(?:\.\d+)?).*\(.*?(\d+\w+)\s*\)/", $FS_Version, $matches); $this->_major = $matches[1]; $this->_minor = $matches[2]; $this->_build = $matches[3]; From 4776ceb0303021db63eb236bcf214034530537c3 Mon Sep 17 00:00:00 2001 From: Matthew Vale Date: Thu, 10 Dec 2015 11:58:09 +0000 Subject: [PATCH 12/17] added switch git_info where available --- app/system/app_languages.php | 18 +++++++++--------- app/system/system.php | 12 +++++++++++- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/app/system/app_languages.php b/app/system/app_languages.php index e576287a32..08271e3487 100644 --- a/app/system/app_languages.php +++ b/app/system/app_languages.php @@ -100,15 +100,15 @@ $text['label-git_info']['sv-se'] = ""; $text['label-git_info']['uk'] = ""; $text['label-git_info']['de-at'] = ""; -$text['label-switch_version']['en-us'] = "Switch Version"; -$text['label-switch_version']['es-cl'] = ""; -$text['label-switch_version']['pt-pt'] = ""; -$text['label-switch_version']['fr-fr'] = ""; -$text['label-switch_version']['pt-br'] = ""; -$text['label-switch_version']['pl'] = ""; -$text['label-switch_version']['sv-se'] = ""; -$text['label-switch_version']['uk'] = ""; -$text['label-switch_version']['de-at'] = ""; +$text['label-switch']['en-us'] = "Switch"; +$text['label-switch']['es-cl'] = ""; +$text['label-switch']['pt-pt'] = ""; +$text['label-switch']['fr-fr'] = ""; +$text['label-switch']['pt-br'] = ""; +$text['label-switch']['pl'] = ""; +$text['label-switch']['sv-se'] = ""; +$text['label-switch']['uk'] = ""; +$text['label-switch']['de-at'] = ""; $text['label-git_branch']['en-us'] = "Branch:"; $text['label-git_branch']['es-cl'] = ""; diff --git a/app/system/system.php b/app/system/system.php index 60cea81bb0..f9e63ce403 100644 --- a/app/system/system.php +++ b/app/system/system.php @@ -113,10 +113,20 @@ $document['title'] = $text['title-sys-status']; $switch_bits = $matches[2]; echo "\n"; echo " \n"; - echo " ".$text['label-switch_version']."\n"; + echo " ".$text['label-switch']." ".$text['label-version']."\n"; echo " \n"; echo " $switch_version ($switch_bits)\n"; echo "\n"; + preg_match("/\(git\s*(.*?)\s*\d+\w+\s*\)/", $switch_version, $matches); + $switch_git_info = $matches[1]; + if(strlen($switch_git_info) > 0){ + echo "\n"; + echo " \n"; + echo " ".$text['label-switch']." ".$text['label-git_info']."\n"; + echo " \n"; + echo " $switch_git_info\n"; + echo "\n"; + } } echo ""; - echo " "; - echo " "; - echo " "; echo "\n"; echo "\n"; echo " \n"; echo " \n"; echo "\n"; echo "
".$text['label-call-statistics']."\n"; + if (permission_exists('xml_cdr_search_advanced')) { + echo " \n"; + } if (permission_exists('xml_cdr_all')) { if ($_GET['showall'] != 'true') { echo "\n"; @@ -70,26 +69,6 @@ else { echo "
\n"; -#CJB -/* echo "
\n"; - echo "\n"; - echo " \n"; - echo " \n"; - echo " \n"; - echo ""; - echo " \n"; - echo "
\n"; - echo " ".$text['label-start_range']."\n"; - echo " \n"; - echo " \n"; - echo " \n"; - echo " "; - echo "\n"; - echo "\n"; - echo "
\n"; - echo "
"; -*/ -#CJB //set the style $c = 0; @@ -100,6 +79,7 @@ else { +
@@ -172,7 +152,17 @@ else { if (data.length > 0) $.plot($("#placeholder"), data, { yaxis: { min: 0 }, - xaxis: { tickDecimals: 0 } + 48 && $hours < 168) { + echo "xaxis: {mode: \"time\",timeformat: \"%m:%d\",minTickSize: [1, \"day\"]}"; + } else { + echo "xaxis: {mode: \"time\",timeformat: \"%m:%d\",minTickSize: [1, \"month\"]}"; + } + + ?> + }); } @@ -198,10 +188,10 @@ else { $i = 0; foreach ($stats as $row) { echo "\n"; - if ($i < 24) { + if ($i <= $hours) { echo " \n"; } - elseif ($i == 24) { + elseif ($i == $hours+1) { echo "

\n"; echo "\n"; echo "\n"; @@ -223,14 +213,14 @@ else { echo "\n"; echo " \n"; } - elseif ($i == 25) { + elseif ($i == $hours+2) { echo "\n"; echo " \n"; } - elseif ($i == 26) { + elseif ($i == $hours+3) { echo " \n"; } - if ($i < 24) { + if ($i <= $hours) { echo " \n"; echo " \n"; } diff --git a/app/xml_cdr/xml_cdr_statistics_inc.php b/app/xml_cdr/xml_cdr_statistics_inc.php index dab016fe17..5d52505901 100644 --- a/app/xml_cdr/xml_cdr_statistics_inc.php +++ b/app/xml_cdr/xml_cdr_statistics_inc.php @@ -34,7 +34,7 @@ else { exit; } -//show all call detail records to admin and superadmin. for everyone else show only the call details for extensions assigned to them +/*//show all call detail records to admin and superadmin. for everyone else show only the call details for extensions assigned to them if (!if_group("admin") && !if_group("superadmin")) { // select caller_id_number, destination_number from v_xml_cdr where domain_uuid = '' // and (caller_id_number = '1001' or destination_number = '1001' or destination_number = '*991001') @@ -68,6 +68,166 @@ else { //create the sql query to get the xml cdr records if (strlen($order_by) == 0) { $order_by = "start_epoch"; } if (strlen($order) == 0) { $order = "desc"; } +*/ + +//get post or get variables from http + if (count($_REQUEST) > 0) { + $cdr_id = check_str($_REQUEST["cdr_id"]); + $missed = check_str($_REQUEST["missed"]); + $direction = check_str($_REQUEST["direction"]); + $caller_id_name = check_str($_REQUEST["caller_id_name"]); + $caller_id_number = check_str($_REQUEST["caller_id_number"]); + $caller_extension_uuid = check_str($_REQUEST["caller_extension_uuid"]); + $destination_number = check_str($_REQUEST["destination_number"]); + $context = check_str($_REQUEST["context"]); + $start_stamp_begin = check_str($_REQUEST["start_stamp_begin"]); + $start_stamp_end = check_str($_REQUEST["start_stamp_end"]); + $answer_stamp_begin = check_str($_REQUEST["answer_stamp_begin"]); + $answer_stamp_end = check_str($_REQUEST["answer_stamp_end"]); + $end_stamp_begin = check_str($_REQUEST["end_stamp_begin"]); + $end_stamp_end = check_str($_REQUEST["end_stamp_end"]); + $start_epoch = check_str($_REQUEST["start_epoch"]); + $stop_epoch = check_str($_REQUEST["stop_epoch"]); + $duration = check_str($_REQUEST["duration"]); + $billsec = check_str($_REQUEST["billsec"]); + $hangup_cause = check_str($_REQUEST["hangup_cause"]); + $uuid = check_str($_REQUEST["uuid"]); + $bleg_uuid = check_str($_REQUEST["bleg_uuid"]); + $accountcode = check_str($_REQUEST["accountcode"]); + $read_codec = check_str($_REQUEST["read_codec"]); + $write_codec = check_str($_REQUEST["write_codec"]); + $remote_media_ip = check_str($_REQUEST["remote_media_ip"]); + $network_addr = check_str($_REQUEST["network_addr"]); + $bridge_uuid = check_str($_REQUEST["network_addr"]); + $order_by = check_str($_REQUEST["order_by"]); + $order = check_str($_REQUEST["order"]); + if (strlen(check_str($_REQUEST["mos_comparison"])) > 0) { + switch(check_str($_REQUEST["mos_comparison"])) { + case 'less': + $mos_comparison = "<"; + break; + case 'greater': + $mos_comparison = ">"; + break; + case 'lessorequal': + $mos_comparison = "<="; + break; + case 'greaterorequal': + $mos_comparison = ">="; + break; + case 'equal': + $mos_comparison = "<"; + break; + case 'notequal': + $mos_comparison = "<>"; + break; + } + } else { + $mos_comparison = ''; + } + //$mos_comparison = check_str($_REQUEST["mos_comparison"]); + $mos_score = check_str($_REQUEST["mos_score"]); + } + + + +//build the sql where string + if ($missed == true) { + $sql_where_ands[] = "billsec = '0'"; + } + if (strlen($start_epoch) > 0 && strlen($stop_epoch) > 0) { + $sql_where_ands[] = "start_epoch BETWEEN ".$start_epoch." AND ".$stop_epoch." "; + } + if (strlen($cdr_id) > 0) { $sql_where_ands[] = "cdr_id like '%".$cdr_id."%'"; } + if (strlen($direction) > 0) { $sql_where_ands[] = "direction = '".$direction."'"; } + if (strlen($caller_id_name) > 0) { + $mod_caller_id_name = str_replace("*", "%", $caller_id_name); + $sql_where_ands[] = "caller_id_name like '".$mod_caller_id_name."'"; + } + if (strlen($caller_extension_uuid) > 0) { + $sql_where_ands[] = "extension_uuid = '".$caller_extension_uuid."'"; + } + if (strlen($caller_id_number) > 0) { + $mod_caller_id_number = str_replace("*", "%", $caller_id_number); + $sql_where_ands[] = "caller_id_number like '".$mod_caller_id_number."'"; + } + if (strlen($destination_number) > 0) { + $mod_destination_number = str_replace("*", "%", $destination_number); + $sql_where_ands[] = "destination_number like '".$mod_destination_number."'"; + } + if (strlen($context) > 0) { $sql_where_ands[] = "context like '%".$context."%'"; } +/* if (strlen($start_stamp_begin) > 0 && strlen($start_stamp_end) > 0) { $sql_where_ands[] = "start_stamp BETWEEN '".$start_stamp_begin.":00.000' AND '".$start_stamp_end.":59.999'"; } + else { + if (strlen($start_stamp_begin) > 0) { $sql_where_ands[] = "start_stamp >= '".$start_stamp_begin.":00.000'"; } + if (strlen($start_stamp_end) > 0) { $sql_where_ands[] = "start_stamp <= '".$start_stamp_end.":59.999'"; } + } +*/ if (strlen($answer_stamp_begin) > 0 && strlen($answer_stamp_end) > 0) { $sql_where_ands[] = "answer_stamp BETWEEN '".$answer_stamp_begin.":00.000' AND '".$answer_stamp_end.":59.999'"; } + else { + if (strlen($answer_stamp_begin) > 0) { $sql_where_ands[] = "answer_stamp >= '".$answer_stamp_begin.":00.000'"; } + if (strlen($answer_stamp_end) > 0) { $sql_where_ands[] = "answer_stamp <= '".$answer_stamp_end.":59.999'"; } + } + if (strlen($end_stamp_begin) > 0 && strlen($end_stamp_end) > 0) { $sql_where_ands[] = "end_stamp BETWEEN '".$end_stamp_begin.":00.000' AND '".$end_stamp_end.":59.999'"; } + else { + if (strlen($end_stamp_begin) > 0) { $sql_where_ands[] = "end_stamp >= '".$end_stamp_begin.":00.000'"; } + if (strlen($end_stamp_end) > 0) { $sql_where_ands[] = "end_stamp <= '".$end_stamp_end.":59.999'"; } + } + if (strlen($duration) > 0) { $sql_where_ands[] = "duration like '%".$duration."%'"; } + if (strlen($billsec) > 0) { $sql_where_ands[] = "billsec like '%".$billsec."%'"; } + if (strlen($hangup_cause) > 0) { $sql_where_ands[] = "hangup_cause like '%".$hangup_cause."%'"; } + if (strlen($uuid) > 0) { $sql_where_ands[] = "uuid = '".$uuid."'"; } + if (strlen($bleg_uuid) > 0) { $sql_where_ands[] = "bleg_uuid = '".$bleg_uuid."'"; } + if (strlen($accountcode) > 0) { $sql_where_ands[] = "accountcode = '".$accountcode."'"; } + if (strlen($read_codec) > 0) { $sql_where_ands[] = "read_codec like '%".$read_codec."%'"; } + if (strlen($write_codec) > 0) { $sql_where_ands[] = "write_codec like '%".$write_codec."%'"; } + if (strlen($remote_media_ip) > 0) { $sql_where_ands[] = "remote_media_ip like '%".$remote_media_ip."%'"; } + if (strlen($network_addr) > 0) { $sql_where_ands[] = "network_addr like '%".$network_addr."%'"; } + if (strlen($mos_comparison) > 0 && strlen($mos_score) > 0 ) { $sql_where_ands[] = "rtp_audio_in_mos " . $mos_comparison . " ".$mos_score.""; } + + //if not admin or superadmin, only show own calls + if (!permission_exists('xml_cdr_domain')) { + if (count($_SESSION['user']['extension']) > 0) { // extensions are assigned to this user + // create simple user extension array + foreach ($_SESSION['user']['extension'] as $row) { $user_extensions[] = $row['user']; } + // if both a source and destination are submitted, but neither are an assigned extension, restrict results + if ( + $caller_id_number != '' && + $destination_number != '' && + array_search($caller_id_number, $user_extensions) === false && + array_search($destination_number, $user_extensions) === false + ) { + $sql_where_ors[] = "caller_id_number like '".$user_extension."'"; + $sql_where_ors[] = "destination_number like '".$user_extension."'"; + $sql_where_ors[] = "destination_number like '*99".$user_extension."'"; + } + // if source submitted is blank, implement restriction for assigned extension(s) + if ($caller_id_number == '') { // if source criteria is blank, then restrict to assigned ext + foreach ($user_extensions as $user_extension) { + if (strlen($user_extension) > 0) { $sql_where_ors[] = "caller_id_number like '".$user_extension."'"; } + } + } + // if destination submitted is blank, implement restriction for assigned extension(s) + if ($destination_number == '') { + foreach ($user_extensions as $user_extension) { + if (strlen($user_extension) > 0) { + $sql_where_ors[] = "destination_number like '".$user_extension."'"; + $sql_where_ors[] = "destination_number like '*99".$user_extension."'"; + } + } + } + // concatenate the 'or's array, then add to the 'and's array + if (sizeof($sql_where_ors) > 0) { + $sql_where_ands[] = "( ".implode(" or ", $sql_where_ors)." )"; + } + } + else { + $sql_where_ands[] = "1 <> 1"; //disable viewing of cdr records by users with no assigned extensions + } + } + + // concatenate the 'ands's array, add to where clause + if (sizeof($sql_where_ands) > 0) { + $sql_where = " where ".implode(" and ", $sql_where_ands)." and "; + } //calculate the seconds in different time frames $seconds_hour = 3600; @@ -89,6 +249,9 @@ else { $sql = "select count(*) as count from v_xml_cdr "; $sql .= $where; $sql .= " start_epoch BETWEEN ".$start." AND ".$end." "; +echo '
'; 
+print_r($sql);
+echo '
'; $prep_statement = $db->prepare(check_sql($sql)); $prep_statement->execute(); $result = $prep_statement->fetchAll(PDO::FETCH_ASSOC); @@ -141,17 +304,20 @@ else { //$call_seconds_1st_hour = get_call_seconds_between(3600, 0); //if (strlen($call_seconds_1st_hour) == 0) { $call_seconds_1st_hour = 0; } -// if (strlen(check_str($_GET['start_stamp_begin'])) > 0 && strlen(check_str($_GET['start_stamp_end'])) > 0 ) { -// $start_date = new DateTime(check_str($_GET['start_stamp_begin'])); -// $end_date = new DateTime(check_str($_GET['start_stamp_end'])); -// $time = $start_date->getTimestamp(); -// } else { + if (strlen(check_str($_GET['start_stamp_begin'])) > 0 && strlen(check_str($_GET['start_stamp_end'])) > 0 ) { + $start_date = new DateTime(check_str($_GET['start_stamp_begin'])); + $end_date = new DateTime(check_str($_GET['start_stamp_end'])); + $time = $end_date->getTimestamp(); + $time = $time - $time % 3600; + $hours = ($end_date->getTimestamp() - $start_date->getTimestamp()) / 3600; + } else { //round down to the nearest hour $time = time() - time() % 3600; -// } - + $hours = 23; + } + //call info hour by hour - for ($i = 0; $i <= 23; $i++) { + for ($i = 0; $i <= $hours; $i++) { $start_epoch = $time - 3600*$i; $stop_epoch = $start_epoch + 3600; $stats[$i]['hours'] = $i + 1; @@ -159,7 +325,7 @@ else { $stats[$i]['stop_stamp'] = date('Y-m-d h:n:s', $stop_epoch); $stats[$i]['start_epoch'] = $start_epoch; $stats[$i]['stop_epoch'] = $stop_epoch; - $stats[$i]['volume'] = get_call_volume_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], ''); + $stats[$i]['volume'] = get_call_volume_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], $sql_where); $stats[$i]['seconds'] = get_call_seconds_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], ''); $stats[$i]['minutes'] = $stats[$i]['seconds'] / 60; $stats[$i]['avg_sec'] = $stats[$i]['seconds'] / $stats[$i]['volume']; @@ -181,7 +347,7 @@ else { } //call info for a day - $i = 24; + $i = $hours+1; $start_epoch = time() - $seconds_day; $stop_epoch = time(); $stats[$i]['hours'] = 24; @@ -189,7 +355,7 @@ else { $stats[$i]['stop_stamp'] = date('Y-m-d h:n:s', $stop_epoch); $stats[$i]['start_epoch'] = $start_epoch; $stats[$i]['stop_epoch'] = $stop_epoch; - $stats[$i]['volume'] = get_call_volume_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], ''); + $stats[$i]['volume'] = get_call_volume_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], $sql_where); $stats[$i]['seconds'] = get_call_seconds_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], ''); $stats[$i]['minutes'] = $stats[$i]['seconds'] / 60; $stats[$i]['avg_sec'] = $stats[$i]['seconds'] / $stats[$i]['volume']; @@ -214,7 +380,7 @@ else { $stats[$i]['stop_stamp'] = date('Y-m-d h:n:s', $stop_epoch); $stats[$i]['start_epoch'] = $start_epoch; $stats[$i]['stop_epoch'] = $stop_epoch; - $stats[$i]['volume'] = get_call_volume_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], ''); + $stats[$i]['volume'] = get_call_volume_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], $sql_where); $stats[$i]['seconds'] = get_call_seconds_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], ''); $stats[$i]['minutes'] = $stats[$i]['seconds'] / 60; $stats[$i]['avg_sec'] = $stats[$i]['seconds'] / $stats[$i]['volume']; @@ -239,7 +405,7 @@ else { $stats[$i]['stop_stamp'] = date('Y-m-d h:n:s', $stop_epoch); $stats[$i]['start_epoch'] = $start_epoch; $stats[$i]['stop_epoch'] = $stop_epoch; - $stats[$i]['volume'] = get_call_volume_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], ''); + $stats[$i]['volume'] = get_call_volume_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], $sql_where); $stats[$i]['seconds'] = get_call_seconds_between($stats[$i]['start_epoch'], $stats[$i]['stop_epoch'], ''); $stats[$i]['minutes'] = $stats[$i]['seconds'] / 60; $stats[$i]['avg_sec'] = $stats[$i]['seconds'] / $stats[$i]['volume']; @@ -257,47 +423,47 @@ else { $i++; //show the graph - $x = 0; - foreach ($stats as $row) { - $graph['volume'][$x][] = date('H', $row['start_epoch']); - $graph['volume'][$x][] = $row['volume']/1; - if ($x == 23) { break; } - $x++; - } - $x = 0; - foreach ($stats as $row) { - $graph['minutes'][$x][] = date('H', $row['start_epoch']); - $graph['minutes'][$x][] = round($row['minutes'],2); - if ($x == 23) { break; } - $x++; - } - $x = 0; - foreach ($stats as $row) { - $graph['call_per_min'][$x][] = date('H', $row['start_epoch']); - $graph['call_per_min'][$x][] = round($row['avg_min'],2); - if ($x == 23) { break; } - $x++; - } - $x = 0; - foreach ($stats as $row) { - $graph['missed'][$x][] = date('H', $row['start_epoch']); - $graph['missed'][$x][] = $row['missed']/1; - if ($x == 23) { break; } - $x++; - } - $x = 0; - foreach ($stats as $row) { - $graph['asr'][$x][] = date('H', $row['start_epoch']); - $graph['asr'][$x][] = round($row['asr'],2)/100; - if ($x == 23) { break; } - $x++; - } - $x = 0; - foreach ($stats as $row) { - $graph['aloc'][$x][] = date('H', $row['start_epoch']); - $graph['aloc'][$x][] = round($row['aloc'],2); - if ($x == 23) { break; } - $x++; - } + $x = 0; + foreach ($stats as $row) { + $graph['volume'][$x][] = $row['start_epoch'] * 1000; + $graph['volume'][$x][] = $row['volume']/1; + if ($x == $hours) { break; } + $x++; + } + $x = 0; + foreach ($stats as $row) { + $graph['minutes'][$x][] = $row['start_epoch'] * 1000; + $graph['minutes'][$x][] = round($row['minutes'],2); + if ($x == $hours) { break; } + $x++; + } + $x = 0; + foreach ($stats as $row) { + $graph['call_per_min'][$x][] = $row['start_epoch'] * 1000; + $graph['call_per_min'][$x][] = round($row['avg_min'],2); + if ($x == $hours) { break; } + $x++; + } + $x = 0; + foreach ($stats as $row) { + $graph['missed'][$x][] = $row['start_epoch'] * 1000; + $graph['missed'][$x][] = $row['missed']/1; + if ($x == $hours) { break; } + $x++; + } + $x = 0; + foreach ($stats as $row) { + $graph['asr'][$x][] = $row['start_epoch'] * 1000; + $graph['asr'][$x][] = round($row['asr'],2)/100; + if ($x == $hours) { break; } + $x++; + } + $x = 0; + foreach ($stats as $row) { + $graph['aloc'][$x][] = $row['start_epoch'] * 1000; + $graph['aloc'][$x][] = round($row['aloc'],2); + if ($x == $hours) { break; } + $x++; + } ?> \ No newline at end of file diff --git a/resources/jquery/flot/jquery.flot.time.js b/resources/jquery/flot/jquery.flot.time.js new file mode 100644 index 0000000000..b06cca72f0 --- /dev/null +++ b/resources/jquery/flot/jquery.flot.time.js @@ -0,0 +1,432 @@ +/* Pretty handling of time axes. + +Copyright (c) 2007-2014 IOLA and Ole Laursen. +Licensed under the MIT license. + +Set axis.mode to "time" to enable. See the section "Time series data" in +API.txt for details. + +*/ + +(function($) { + + var options = { + xaxis: { + timezone: null, // "browser" for local to the client or timezone for timezone-js + timeformat: null, // format string to use + twelveHourClock: false, // 12 or 24 time in time mode + monthNames: null // list of names of months + } + }; + + // round to nearby lower multiple of base + + function floorInBase(n, base) { + return base * Math.floor(n / base); + } + + // Returns a string with the date d formatted according to fmt. + // A subset of the Open Group's strftime format is supported. + + function formatDate(d, fmt, monthNames, dayNames) { + + if (typeof d.strftime == "function") { + return d.strftime(fmt); + } + + var leftPad = function(n, pad) { + n = "" + n; + pad = "" + (pad == null ? "0" : pad); + return n.length == 1 ? pad + n : n; + }; + + var r = []; + var escape = false; + var hours = d.getHours(); + var isAM = hours < 12; + + if (monthNames == null) { + monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; + } + + if (dayNames == null) { + dayNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; + } + + var hours12; + + if (hours > 12) { + hours12 = hours - 12; + } else if (hours == 0) { + hours12 = 12; + } else { + hours12 = hours; + } + + for (var i = 0; i < fmt.length; ++i) { + + var c = fmt.charAt(i); + + if (escape) { + switch (c) { + case 'a': c = "" + dayNames[d.getDay()]; break; + case 'b': c = "" + monthNames[d.getMonth()]; break; + case 'd': c = leftPad(d.getDate()); break; + case 'e': c = leftPad(d.getDate(), " "); break; + case 'h': // For back-compat with 0.7; remove in 1.0 + case 'H': c = leftPad(hours); break; + case 'I': c = leftPad(hours12); break; + case 'l': c = leftPad(hours12, " "); break; + case 'm': c = leftPad(d.getMonth() + 1); break; + case 'M': c = leftPad(d.getMinutes()); break; + // quarters not in Open Group's strftime specification + case 'q': + c = "" + (Math.floor(d.getMonth() / 3) + 1); break; + case 'S': c = leftPad(d.getSeconds()); break; + case 'y': c = leftPad(d.getFullYear() % 100); break; + case 'Y': c = "" + d.getFullYear(); break; + case 'p': c = (isAM) ? ("" + "am") : ("" + "pm"); break; + case 'P': c = (isAM) ? ("" + "AM") : ("" + "PM"); break; + case 'w': c = "" + d.getDay(); break; + } + r.push(c); + escape = false; + } else { + if (c == "%") { + escape = true; + } else { + r.push(c); + } + } + } + + return r.join(""); + } + + // To have a consistent view of time-based data independent of which time + // zone the client happens to be in we need a date-like object independent + // of time zones. This is done through a wrapper that only calls the UTC + // versions of the accessor methods. + + function makeUtcWrapper(d) { + + function addProxyMethod(sourceObj, sourceMethod, targetObj, targetMethod) { + sourceObj[sourceMethod] = function() { + return targetObj[targetMethod].apply(targetObj, arguments); + }; + }; + + var utc = { + date: d + }; + + // support strftime, if found + + if (d.strftime != undefined) { + addProxyMethod(utc, "strftime", d, "strftime"); + } + + addProxyMethod(utc, "getTime", d, "getTime"); + addProxyMethod(utc, "setTime", d, "setTime"); + + var props = ["Date", "Day", "FullYear", "Hours", "Milliseconds", "Minutes", "Month", "Seconds"]; + + for (var p = 0; p < props.length; p++) { + addProxyMethod(utc, "get" + props[p], d, "getUTC" + props[p]); + addProxyMethod(utc, "set" + props[p], d, "setUTC" + props[p]); + } + + return utc; + }; + + // select time zone strategy. This returns a date-like object tied to the + // desired timezone + + function dateGenerator(ts, opts) { + if (opts.timezone == "browser") { + return new Date(ts); + } else if (!opts.timezone || opts.timezone == "utc") { + return makeUtcWrapper(new Date(ts)); + } else if (typeof timezoneJS != "undefined" && typeof timezoneJS.Date != "undefined") { + var d = new timezoneJS.Date(); + // timezone-js is fickle, so be sure to set the time zone before + // setting the time. + d.setTimezone(opts.timezone); + d.setTime(ts); + return d; + } else { + return makeUtcWrapper(new Date(ts)); + } + } + + // map of app. size of time units in milliseconds + + var timeUnitSize = { + "second": 1000, + "minute": 60 * 1000, + "hour": 60 * 60 * 1000, + "day": 24 * 60 * 60 * 1000, + "month": 30 * 24 * 60 * 60 * 1000, + "quarter": 3 * 30 * 24 * 60 * 60 * 1000, + "year": 365.2425 * 24 * 60 * 60 * 1000 + }; + + // the allowed tick sizes, after 1 year we use + // an integer algorithm + + var baseSpec = [ + [1, "second"], [2, "second"], [5, "second"], [10, "second"], + [30, "second"], + [1, "minute"], [2, "minute"], [5, "minute"], [10, "minute"], + [30, "minute"], + [1, "hour"], [2, "hour"], [4, "hour"], + [8, "hour"], [12, "hour"], + [1, "day"], [2, "day"], [3, "day"], + [0.25, "month"], [0.5, "month"], [1, "month"], + [2, "month"] + ]; + + // we don't know which variant(s) we'll need yet, but generating both is + // cheap + + var specMonths = baseSpec.concat([[3, "month"], [6, "month"], + [1, "year"]]); + var specQuarters = baseSpec.concat([[1, "quarter"], [2, "quarter"], + [1, "year"]]); + + function init(plot) { + plot.hooks.processOptions.push(function (plot, options) { + $.each(plot.getAxes(), function(axisName, axis) { + + var opts = axis.options; + + if (opts.mode == "time") { + axis.tickGenerator = function(axis) { + + var ticks = []; + var d = dateGenerator(axis.min, opts); + var minSize = 0; + + // make quarter use a possibility if quarters are + // mentioned in either of these options + + var spec = (opts.tickSize && opts.tickSize[1] === + "quarter") || + (opts.minTickSize && opts.minTickSize[1] === + "quarter") ? specQuarters : specMonths; + + if (opts.minTickSize != null) { + if (typeof opts.tickSize == "number") { + minSize = opts.tickSize; + } else { + minSize = opts.minTickSize[0] * timeUnitSize[opts.minTickSize[1]]; + } + } + + for (var i = 0; i < spec.length - 1; ++i) { + if (axis.delta < (spec[i][0] * timeUnitSize[spec[i][1]] + + spec[i + 1][0] * timeUnitSize[spec[i + 1][1]]) / 2 + && spec[i][0] * timeUnitSize[spec[i][1]] >= minSize) { + break; + } + } + + var size = spec[i][0]; + var unit = spec[i][1]; + + // special-case the possibility of several years + + if (unit == "year") { + + // if given a minTickSize in years, just use it, + // ensuring that it's an integer + + if (opts.minTickSize != null && opts.minTickSize[1] == "year") { + size = Math.floor(opts.minTickSize[0]); + } else { + + var magn = Math.pow(10, Math.floor(Math.log(axis.delta / timeUnitSize.year) / Math.LN10)); + var norm = (axis.delta / timeUnitSize.year) / magn; + + if (norm < 1.5) { + size = 1; + } else if (norm < 3) { + size = 2; + } else if (norm < 7.5) { + size = 5; + } else { + size = 10; + } + + size *= magn; + } + + // minimum size for years is 1 + + if (size < 1) { + size = 1; + } + } + + axis.tickSize = opts.tickSize || [size, unit]; + var tickSize = axis.tickSize[0]; + unit = axis.tickSize[1]; + + var step = tickSize * timeUnitSize[unit]; + + if (unit == "second") { + d.setSeconds(floorInBase(d.getSeconds(), tickSize)); + } else if (unit == "minute") { + d.setMinutes(floorInBase(d.getMinutes(), tickSize)); + } else if (unit == "hour") { + d.setHours(floorInBase(d.getHours(), tickSize)); + } else if (unit == "month") { + d.setMonth(floorInBase(d.getMonth(), tickSize)); + } else if (unit == "quarter") { + d.setMonth(3 * floorInBase(d.getMonth() / 3, + tickSize)); + } else if (unit == "year") { + d.setFullYear(floorInBase(d.getFullYear(), tickSize)); + } + + // reset smaller components + + d.setMilliseconds(0); + + if (step >= timeUnitSize.minute) { + d.setSeconds(0); + } + if (step >= timeUnitSize.hour) { + d.setMinutes(0); + } + if (step >= timeUnitSize.day) { + d.setHours(0); + } + if (step >= timeUnitSize.day * 4) { + d.setDate(1); + } + if (step >= timeUnitSize.month * 2) { + d.setMonth(floorInBase(d.getMonth(), 3)); + } + if (step >= timeUnitSize.quarter * 2) { + d.setMonth(floorInBase(d.getMonth(), 6)); + } + if (step >= timeUnitSize.year) { + d.setMonth(0); + } + + var carry = 0; + var v = Number.NaN; + var prev; + + do { + + prev = v; + v = d.getTime(); + ticks.push(v); + + if (unit == "month" || unit == "quarter") { + if (tickSize < 1) { + + // a bit complicated - we'll divide the + // month/quarter up but we need to take + // care of fractions so we don't end up in + // the middle of a day + + d.setDate(1); + var start = d.getTime(); + d.setMonth(d.getMonth() + + (unit == "quarter" ? 3 : 1)); + var end = d.getTime(); + d.setTime(v + carry * timeUnitSize.hour + (end - start) * tickSize); + carry = d.getHours(); + d.setHours(0); + } else { + d.setMonth(d.getMonth() + + tickSize * (unit == "quarter" ? 3 : 1)); + } + } else if (unit == "year") { + d.setFullYear(d.getFullYear() + tickSize); + } else { + d.setTime(v + step); + } + } while (v < axis.max && v != prev); + + return ticks; + }; + + axis.tickFormatter = function (v, axis) { + + var d = dateGenerator(v, axis.options); + + // first check global format + + if (opts.timeformat != null) { + return formatDate(d, opts.timeformat, opts.monthNames, opts.dayNames); + } + + // possibly use quarters if quarters are mentioned in + // any of these places + + var useQuarters = (axis.options.tickSize && + axis.options.tickSize[1] == "quarter") || + (axis.options.minTickSize && + axis.options.minTickSize[1] == "quarter"); + + var t = axis.tickSize[0] * timeUnitSize[axis.tickSize[1]]; + var span = axis.max - axis.min; + var suffix = (opts.twelveHourClock) ? " %p" : ""; + var hourCode = (opts.twelveHourClock) ? "%I" : "%H"; + var fmt; + + if (t < timeUnitSize.minute) { + fmt = hourCode + ":%M:%S" + suffix; + } else if (t < timeUnitSize.day) { + if (span < 2 * timeUnitSize.day) { + fmt = hourCode + ":%M" + suffix; + } else { + fmt = "%b %d " + hourCode + ":%M" + suffix; + } + } else if (t < timeUnitSize.month) { + fmt = "%b %d"; + } else if ((useQuarters && t < timeUnitSize.quarter) || + (!useQuarters && t < timeUnitSize.year)) { + if (span < timeUnitSize.year) { + fmt = "%b"; + } else { + fmt = "%b %Y"; + } + } else if (useQuarters && t < timeUnitSize.year) { + if (span < timeUnitSize.year) { + fmt = "Q%q"; + } else { + fmt = "Q%q %Y"; + } + } else { + fmt = "%Y"; + } + + var rt = formatDate(d, fmt, opts.monthNames, opts.dayNames); + + return rt; + }; + } + }); + }); + } + + $.plot.plugins.push({ + init: init, + options: options, + name: 'time', + version: '1.0' + }); + + // Time-axis support used to be in Flot core, which exposed the + // formatDate function on the plot object. Various plugins depend + // on the function, so we need to re-expose it here. + + $.plot.formatDate = formatDate; + $.plot.dateGenerator = dateGenerator; + +})(jQuery); \ No newline at end of file From 904de0b2671c69f604463e9a11a97f9f4cb0335b Mon Sep 17 00:00:00 2001 From: blackc2004 Date: Thu, 10 Dec 2015 11:10:32 -0800 Subject: [PATCH 14/17] remove print --- app/xml_cdr/xml_cdr_statistics_inc.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/xml_cdr/xml_cdr_statistics_inc.php b/app/xml_cdr/xml_cdr_statistics_inc.php index 5d52505901..c6d48c64a2 100644 --- a/app/xml_cdr/xml_cdr_statistics_inc.php +++ b/app/xml_cdr/xml_cdr_statistics_inc.php @@ -249,9 +249,7 @@ else { $sql = "select count(*) as count from v_xml_cdr "; $sql .= $where; $sql .= " start_epoch BETWEEN ".$start." AND ".$end." "; -echo '
'; 
-print_r($sql);
-echo '
'; + $prep_statement = $db->prepare(check_sql($sql)); $prep_statement->execute(); $result = $prep_statement->fetchAll(PDO::FETCH_ASSOC); From e69bc4da6be6a51cdfc1557bb2a0fb598695d5cf Mon Sep 17 00:00:00 2001 From: blackc2004 Date: Thu, 10 Dec 2015 15:07:46 -0800 Subject: [PATCH 15/17] extension download --- app/extensions/app_languages.php | 11 ++ app/extensions/extension_download.php | 187 ++++++++++++++++++++++++++ app/extensions/extensions.php | 3 + themes/enhanced/template.php | 4 + 4 files changed, 205 insertions(+) create mode 100644 app/extensions/extension_download.php diff --git a/app/extensions/app_languages.php b/app/extensions/app_languages.php index d70072975a..1a15d94a98 100644 --- a/app/extensions/app_languages.php +++ b/app/extensions/app_languages.php @@ -1729,6 +1729,17 @@ $text['button-save']['ro'] = "Salvează"; $text['button-save']['ar-eg'] = "حفظ"; $text['button-save']['he'] = "שמור"; +$text['button-export']['en-us'] = "Export"; +$text['button-export']['es-cl'] = "Exportación"; +$text['button-export']['pt-pt'] = "Exportação"; +$text['button-export']['fr-fr'] = "Exportation"; +$text['button-export']['pt-br'] = "Exportação "; +$text['button-export']['pl'] = "Eksportuj"; +$text['button-export']['sv-se'] = "Export"; +$text['button-export']['uk'] = ""; +$text['button-export']['de-at'] = "Export"; +$text['button-export']['he'] = "יצוא"; + $text['button-edit']['en-us'] = "Edit"; $text['button-edit']['es-cl'] = "Editar"; $text['button-edit']['pt-pt'] = "Editar"; diff --git a/app/extensions/extension_download.php b/app/extensions/extension_download.php new file mode 100644 index 0000000000..3fa035b416 --- /dev/null +++ b/app/extensions/extension_download.php @@ -0,0 +1,187 @@ + + Portions created by the Initial Developer are Copyright (C) 2008-2012 + the Initial Developer. All Rights Reserved. + + Contributor(s): + Mark J Crane +*/ +include "root.php"; +require_once "resources/require.php"; +require_once "resources/check_auth.php"; +require_once "resources/paging.php"; +if (if_group("superadmin")) { + //access granted +} +else { + echo "access denied"; + exit; +} + +//add multi-lingual support +$language = new text; +$text = $language->get(); + +function array2csv(array &$array) +{ + if (count($array) == 0) { + return null; + } + ob_start(); + $df = fopen("php://output", 'w'); + fputcsv($df, array_keys(reset($array))); + foreach ($array as $row) { + fputcsv($df, $row); + } + fclose($df); + return ob_get_clean(); +} + +function download_send_headers($filename) { + // disable caching + $now = gmdate("D, d M Y H:i:s"); + header("Expires: Tue, 03 Jul 2001 06:00:00 GMT"); + header("Cache-Control: max-age=0, no-cache, must-revalidate, proxy-revalidate"); + header("Last-Modified: {$now} GMT"); + + // force download + header("Content-Type: application/force-download"); + header("Content-Type: application/octet-stream"); + header("Content-Type: application/download"); + + // disposition / encoding on response body + header("Content-Disposition: attachment;filename={$filename}"); + header("Content-Transfer-Encoding: binary"); +} + +if (isset($_REQUEST["column_group"])) { + + $columns = implode(",",$_REQUEST["column_group"]); + $sql = "select " . $columns . " from v_extensions "; + $sql .= " where domain_uuid = '".$domain_uuid."' "; + $prep_statement = $db->prepare(check_sql($sql)); + $prep_statement->execute(); + $extensions = $prep_statement->fetchAll(PDO::FETCH_ASSOC); + unset ($sql, $prep_statement); +// print_r($extensions); + + download_send_headers("data_export_" . date("Y-m-d") . ".csv"); + echo array2csv($extensions); + die(); + +} + +$columns[] = 'extension_uuid'; +$columns[] = 'domain_uuid'; +$columns[] = 'extension'; +$columns[] = 'number_alias'; +$columns[] = 'password'; +$columns[] = 'accountcode'; +$columns[] = 'effective_caller_id_name'; +$columns[] = 'effective_caller_id_number'; +$columns[] = 'outbound_caller_id_name'; +$columns[] = 'outbound_caller_id_number'; +$columns[] = 'emergency_caller_id_name'; +$columns[] = 'emergency_caller_id_number'; +$columns[] = 'directory_full_name'; +$columns[] = 'directory_visible'; +$columns[] = 'directory_exten_visible'; +$columns[] = 'limit_max'; +$columns[] = 'limit_destination'; +$columns[] = 'missed_call_app'; +$columns[] = 'missed_call_data'; +$columns[] = 'user_context'; +$columns[] = 'toll_allow'; +$columns[] = 'call_timeout'; +$columns[] = 'call_group'; +$columns[] = 'call_screen_enabled'; +$columns[] = 'user_record'; +$columns[] = 'hold_music'; +$columns[] = 'auth_acl'; +$columns[] = 'cidr'; +$columns[] = 'sip_force_contact'; +$columns[] = 'nibble_account'; +$columns[] = 'sip_force_expires'; +$columns[] = 'mwi_account'; +$columns[] = 'sip_bypass_media'; +$columns[] = 'unique_id'; +$columns[] = 'dial_string'; +$columns[] = 'dial_user'; +$columns[] = 'dial_domain'; +$columns[] = 'do_not_disturb'; +$columns[] = 'forward_all_destination'; +$columns[] = 'forward_all_enabled'; +$columns[] = 'forward_busy_destination'; +$columns[] = 'forward_busy_enabled'; +$columns[] = 'forward_no_answer_destination'; +$columns[] = 'forward_no_answer_enabled'; +$columns[] = 'follow_me_uuid'; +$columns[] = 'enabled'; +$columns[] = 'description'; +$columns[] = 'forward_caller_id_uuid'; +$columns[] = 'absolute_codec_string'; +$columns[] = 'forward_user_not_registered_destination'; +$columns[] = 'forward_user_not_registered_enabled'; + +$c = 0; +$row_style["0"] = "row_style0"; +$row_style["1"] = "row_style1"; + +//begin the page content + require_once "resources/header.php"; + + echo "
\n"; + echo "
".($i+1)."
1
730".date('j M', $row['start_epoch'])."".date('H:i', $row['start_epoch'])." - ".date('H:i', $row['stop_epoch'])." 
\n"; + echo "\n"; + echo "\n"; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + foreach ($columns as $value) { + echo "\n"; + echo " "; + echo " "; + echo " "; + echo ""; + if ($c==0) { $c=1; } else { $c=0; } + } + + echo " \n"; + echo " \n"; + echo " "; + + echo "
"; + echo " Column Name"; + echo " Description"; + echo "
"; + echo " $value"; + echo ""; + echo "
\n"; + echo "
"; + echo " \n"; + echo "
"; + echo "

"; + echo ""; + +//include the footer + require_once "resources/footer.php"; +?> \ No newline at end of file diff --git a/app/extensions/extensions.php b/app/extensions/extensions.php index a2d7b28597..15619513ae 100644 --- a/app/extensions/extensions.php +++ b/app/extensions/extensions.php @@ -123,6 +123,9 @@ require_once "resources/paging.php"; echo " \n"; echo "
\n"; echo " \n"; + if (if_group("superadmin")) { + echo " \n"; + } echo " "; echo " "; echo " \n"; diff --git a/themes/enhanced/template.php b/themes/enhanced/template.php index 23aadd820a..1ff8bd9091 100644 --- a/themes/enhanced/template.php +++ b/themes/enhanced/template.php @@ -1254,6 +1254,10 @@ SPAN.playback_progress_bar { } }); + $("#selecctall").change(function(){ + $(".checkbox1").prop('checked', $(this).prop("checked")); + }); + // linkify rows (except the last - the list_control_icons cell) // on a table with a class of 'tr_hover', according to the href // attribute of the tag From 1706a13234714d7d1d203b4b3a5554a807d0b787 Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Fri, 11 Dec 2015 16:40:49 +0300 Subject: [PATCH 16/17] Fix. Play voicemail. Copy from recordings.php --- app/voicemails/resources/classes/voicemail.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/voicemails/resources/classes/voicemail.php b/app/voicemails/resources/classes/voicemail.php index 27f7e304af..f16d187b1c 100644 --- a/app/voicemails/resources/classes/voicemail.php +++ b/app/voicemails/resources/classes/voicemail.php @@ -354,6 +354,7 @@ header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1 header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // date in the past header("Content-Length: " . filesize($file_path)); + ob_end_clean(); fpassthru($fd); } From 358ae7d312be5f9456e19a7a444073f9925889ed Mon Sep 17 00:00:00 2001 From: Matthew Vale Date: Fri, 11 Dec 2015 14:57:14 +0000 Subject: [PATCH 17/17] patch for SunOS corrected collection of switch version during detect_switch --- app/system/system.php | 8 +++++--- core/install/resources/classes/detect_switch.php | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/system/system.php b/app/system/system.php index f9e63ce403..49887f1d11 100644 --- a/app/system/system.php +++ b/app/system/system.php @@ -87,11 +87,13 @@ $document['title'] = $text['title-sys-status']; $git_path = normalize_path_to_os($_SERVER["DOCUMENT_ROOT"]."/.git"); if(file_exists($git_path)){ - $git_branch = shell_exec('git --git-dir='.$git_path.' name-rev --name-only HEAD'); + $git_exe = 'git'; + if (strtoupper(substr(PHP_OS, 0, 3)) === 'SUN') { $git_exe = shell_exec('which git')); } + $git_branch = shell_exec($git_exe.' --git-dir='.$git_path.' name-rev --name-only HEAD'); rtrim($git_branch); - $git_commit = shell_exec('git --git-dir='.$git_path.' rev-parse HEAD'); + $git_commit = shell_exec($git_exe.' --git-dir='.$git_path.' rev-parse HEAD'); rtrim($git_commit); - $git_origin = shell_exec('git --git-dir='.$git_path.' config --get remote.origin.url'); + $git_origin = shell_exec($git_exe.' --git-dir='.$git_path.' config --get remote.origin.url'); rtrim($git_commit); echo "\n"; echo " \n"; diff --git a/core/install/resources/classes/detect_switch.php b/core/install/resources/classes/detect_switch.php index 92ab726465..b23910fab1 100644 --- a/core/install/resources/classes/detect_switch.php +++ b/core/install/resources/classes/detect_switch.php @@ -128,10 +128,11 @@ require_once "resources/classes/EventSocket.php"; throw new Exception('Failed to use event socket'); } $FS_Version = $this->event_socket_request('api version'); - preg_match("/FreeSWITCH Version (\d+\.\d+\.\d+(?:\.\d+)?).*\(.*?(\d+\w+)\s*\)/", $FS_Version, $matches); + preg_match("/FreeSWITCH Version (\d+)\.(\d+)\.(\d+(?:\.\d+)?).*\(.*?(\d+\w+)\s*\)/", $FS_Version, $matches); $this->_major = $matches[1]; $this->_minor = $matches[2]; $this->_build = $matches[3]; + $this->_bits = $matches[4]; $FS_Vars = $this->event_socket_request('api global_getvar'); foreach (explode("\n",$FS_Vars) as $FS_Var){ preg_match("/(\w+_dir)=(.*)/", $FS_Var, $matches);