diff --git a/app/dialplan_outbound/dialplan_outbound_add.php b/app/dialplan_outbound/dialplan_outbound_add.php index 12ff896054..98022a5702 100644 --- a/app/dialplan_outbound/dialplan_outbound_add.php +++ b/app/dialplan_outbound/dialplan_outbound_add.php @@ -613,6 +613,7 @@ $array['dialplans'][$x]['dialplan_details'][$y]['dialplan_detail_type'] = 'set'; if ($dialplan_expression == '(^911$|^933$)') { $array['dialplans'][$x]['dialplan_details'][$y]['dialplan_detail_data'] = 'effective_caller_id_number=${emergency_caller_id_number}'; + $array['dialplans'][$x]['dialplan_details'][$y]['dialplan_detail_data'] = 'call_date=${strftime(%d-%b-%Y %r)}'; } else { $array['dialplans'][$x]['dialplan_details'][$y]['dialplan_detail_data'] = 'effective_caller_id_number=${outbound_caller_id_number}'; @@ -628,7 +629,7 @@ $array['dialplans'][$x]['dialplan_details'][$y]['dialplan_uuid'] = $dialplan_uuid; $array['dialplans'][$x]['dialplan_details'][$y]['dialplan_detail_tag'] = 'action'; $array['dialplans'][$x]['dialplan_details'][$y]['dialplan_detail_type'] = 'lua'; - $array['dialplans'][$x]['dialplan_details'][$y]['dialplan_detail_data'] = "email.lua \${email_to} \${email_from} '' 'Emergency Call' '\${sip_from_user}@\${domain_name} has called 911 emergency'"; + $array['dialplans'][$x]['dialplan_details'][$y]['dialplan_detail_data'] = "app.lua emergency 1"; $array['dialplans'][$x]['dialplan_details'][$y]['dialplan_detail_order'] = $y * 10; $array['dialplans'][$x]['dialplan_details'][$y]['dialplan_detail_group'] = '0'; $array['dialplans'][$x]['dialplan_details'][$y]['dialplan_detail_enabled'] = 'false'; diff --git a/app/email_templates/app_defaults.php b/app/email_templates/app_defaults.php index 93682c51c5..9008dff2af 100644 --- a/app/email_templates/app_defaults.php +++ b/app/email_templates/app_defaults.php @@ -504,6 +504,46 @@ $array['email_templates'][$x]['template_type'] = 'html'; $array['email_templates'][$x]['template_enabled'] = 'true'; $array['email_templates'][$x]['template_description'] = ''; + $x++; + + $array['email_templates'][$x]['email_template_uuid'] = '814c08da-78ff-11ee-b73f-005056a27559'; + $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_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'] .= "
\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'] .= "\n"; + $array['email_templates'][$x]['template_body'] .= "\n"; + $array['email_templates'][$x]['template_type'] = 'html'; + $array['email_templates'][$x]['template_enabled'] = 'true'; + $array['email_templates'][$x]['template_description'] = ''; + $x++; + + $array['email_templates'][$x]['email_template_uuid'] = '8928e8d4-78ff-11ee-ac06-005056a27559'; + $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_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'] .= "
\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'] .= "\n"; + $array['email_templates'][$x]['template_body'] .= "\n"; + $array['email_templates'][$x]['template_type'] = 'html'; + $array['email_templates'][$x]['template_enabled'] = 'true'; + $array['email_templates'][$x]['template_description'] = ''; //build array of email template uuids diff --git a/app/emergency/app_config.php b/app/emergency/app_config.php new file mode 100644 index 0000000000..53f7f09e0a --- /dev/null +++ b/app/emergency/app_config.php @@ -0,0 +1,96 @@ + diff --git a/app/emergency/app_menu.php b/app/emergency/app_menu.php new file mode 100644 index 0000000000..08e0e253e2 --- /dev/null +++ b/app/emergency/app_menu.php @@ -0,0 +1,35 @@ + diff --git a/app/emergency/emergency.php b/app/emergency/emergency.php new file mode 100644 index 0000000000..03dbaaa698 --- /dev/null +++ b/app/emergency/emergency.php @@ -0,0 +1,213 @@ +get(); + +//get the http post data +if (!empty($_POST['emergency_logs']) && is_array($_POST['emergency_logs'])) { + $action = $_POST['action']; + $search = $_POST['search']; + $emergency_logs = $_POST['emergency_logs']; +} + +//process the http post data by action +if (!empty($action) && !empty($emergency_logs) && is_array($emergency_logs) && @sizeof($emergency_logs) != 0) { + + //validate the token + $token = new token; + if (!$token->validate($_SERVER['PHP_SELF'])) { + message::add($text['message-invalid_token'],'negative'); + header('Location: emergency.php'); + exit; + } + + //prepare the array + if (!empty($emergency_logs)) { + foreach ($emergency_logs as $row) { + $array['emergency_logs'][$x]['checked'] = $row['checked']; + $array['emergency_logs'][$x]['emergency_log_uuid'] = $row['emergency_log_uuid']; + $x++; + } + } + + //prepare the database object + $database = new database; + $database->app_name = 'emergency_logs'; + $database->app_uuid = 'de63b1ae-7750-11ee-b3a5-005056a27559'; + + //send the array to the database class + if (!empty($action) && $action == 'delete') { + $database->delete($array); + } + + //redirect the user + header('Location: emergency.php'.($search != '' ? '?search='.urlencode($search) : null)); + exit; +} + +//get order and order by +$order_by = $_GET["order_by"] ?? null; +$order = $_GET["order"] ?? null; + +//define the variables +$search = ''; +$show = ''; + +//add the search variable +if (!empty($_GET["search"])) { + $search = strtolower($_GET["search"]); +} + +//add the show variable +if (!empty($_GET["show"])) { + $show = $_GET["show"]; +} + + +//get the count +$sql = "select count(log_uuid) "; +$sql .= "from v_emergency_logs "; +if ($show == 'all') { + $sql .= "where true "; +} +else { + $sql .= "where domain_uuid = :domain_uuid "; + $parameters['domain_uuid'] = $_SESSION['domain_uuid']; +} +if (!empty($search)) { + $sql .= "and ( "; + $sql .= " lower(event) like :search "; + $sql .= ") "; + $parameters['search'] = '%'.$search.'%'; +} +$database = new database; +$num_rows = $database->select($sql, $parameters ?? null, 'column'); +unset($sql, $parameters); + +//prepare to page the results +$rows_per_page = ($_SESSION['domain']['paging']['numeric'] != '') ? $_SESSION['domain']['paging']['numeric'] : 50; +$param = !empty($search) ? "&search=".$search : null; +$param .= (!empty($_GET['page']) && $show == 'all' && permission_exists('user_log_all')) ? "&show=all" : null; +$page = !empty($_GET['page']) && is_numeric($_GET['page']) ? $_GET['page'] : 0; +list($paging_controls, $rows_per_page) = paging($num_rows, $param, $rows_per_page); +list($paging_controls_mini, $rows_per_page) = paging($num_rows, $param, $rows_per_page, true); +$offset = $rows_per_page * $page; + +//set the time zone +if (isset($_SESSION['domain']['time_zone']['name'])) { + $time_zone = $_SESSION['domain']['time_zone']['name']; +} +else { + $time_zone = date_default_timezone_get(); +} + +//get the list +$sql = "select * "; +$sql .= "from v_emergency_logs "; +if ($show == 'all') { + $sql .= "where true "; +} +else { + $sql .= "where domain_uuid = :domain_uuid "; + $parameters['domain_uuid'] = $_SESSION['domain_uuid']; +} +if (!empty($search)) { + $sql .= "and ( "; + $sql .= " lower(event) like :search "; + $sql .= ") "; + $parameters['search'] = '%'.$search.'%'; +} +$sql .= limit_offset($rows_per_page, $offset); + +$database = new database; +$emergency_logs = $database->select($sql, $parameters ?? null, 'all'); +unset($sql, $parameters); + +//create token +$object = new token; +$token = $object->create($_SERVER['PHP_SELF']); + +//additional includes +$document['title'] = 'Emergency Logs'; +require_once "resources/header.php"; + +//show the content +echo "
\n"; +echo "
Emergency Logs (".$num_rows.")
\n"; +echo "
\n"; +if ($emergency_logs) { + 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 "\n"; +echo "
\n"; +echo "
\n"; +echo "
\n"; + +if ($emergency_logs) { + echo modal::create(['id'=>'modal-delete','type'=>'delete','actions'=>button::create(['type'=>'button','label'=>$text['button-continue'],'icon'=>'check','id'=>'btn_delete','style'=>'float: right; margin-left: 15px;','collapse'=>'never','onclick'=>"modal_close(); list_action_set('delete'); list_form_submit('form_list');"])]); +} + +echo $text['title_description-emergency_logs']."\n"; +echo "

\n"; + +echo "\n"; +echo "\n"; +echo "\n"; +echo "\n"; +echo "\n"; +echo "\n"; +echo "\n"; + +if (!empty($emergency_logs) && is_array($emergency_logs) && @sizeof($emergency_logs) != 0) { + $x = 0; + foreach ($emergency_logs as $row) { + echo "\n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo "\n"; + $x++; + } + unset($emergency_logs); +} + +echo "
TimeDateExtensionEvent
".escape($row['time'])."".escape($row['date'])."".escape($row['extension'])."".escape($row['event'])."
\n"; +echo "
\n"; +echo "
".$paging_controls."
\n"; +echo "\n"; +echo "\n"; + +//include the footer +require_once "resources/footer.php"; + +?> diff --git a/app/switch/resources/scripts/app/emergency/index.lua b/app/switch/resources/scripts/app/emergency/index.lua new file mode 100644 index 0000000000..fd1a694ede --- /dev/null +++ b/app/switch/resources/scripts/app/emergency/index.lua @@ -0,0 +1,278 @@ +-- emergency.lua +-- Part of FusionPBX +-- Copyright (C) 2010 - 2022 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. + +--Description: + --purpose: send an email queue or email for 911 calls + --freeswitch.email(to, from, headers, body, file, convert_cmd, convert_ext) + --to (mandatory) a valid email address + --from (mandatory) a valid email address + --headers (mandatory) for example "subject: you've got mail!\n" + --body (optional) your regular mail body + --file (optional) a file to attach to your mail + --convert_cmd (optional) convert file to a different format before sending + --convert_ext (optional) to replace the file's extension + +--Example + --luarun emergency.lua to@domain.com from@domain.com 'headers' 'subject' 'body' + +--load libraries + local send_mail = require 'resources.functions.send_mail' + local Database = require "resources.functions.database" + local Settings = require "resources.functions.lazy_settings" + local Utils = require "resources.functions.channel_utils"; + +--define a function to send email + local db = dbh or Database.new('system') + local settings = Settings.new(db, domain_name, domain_uuid) + local email_queue_enabled = settings:get('email_queue', 'enabled', 'boolean') or "false"; + +--get the argv values + script_name = argv[0]; + delete = argv[1]; + +--prepare the api object + api = freeswitch.API(); + +--get sessions info +if (session and session:ready()) then + domain_uuid = session:getVariable("domain_uuid"); + domain_name = session:getVariable("domain_name"); + call_uuid = session:getVariable("uuid"); + headers = { + ["X-FusionPBX-Domain-UUID"] = domain_uuid; + ["X-FusionPBX-Domain-Name"] = domain_name; + ["X-FusionPBX-Email-Type"] = 'app'; + ["X-FusionPBX-Call-UUID"] = call_uuid; + } +else + headers = {} +end + +function escapeCSV(s) + if string.find(s, '[,"]') then + s = '"' .. string.gsub(s, '"', '""') .. '"' + end + return s +end + +function toCSV(tt) + local s = "" + for _,p in ipairs(tt) do + s = s .. "," .. escapeCSV(p) + end + return string.sub(s, 2) +end + +--connect to the database +local dbh = Database.new('system'); + +--get the templates +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'} + dbh:query(sql, params, function(row) + subject = row.template_subject; + body = row.template_body; + language = row.template_language; + end); + if (debug["sql"]) then + freeswitch.consoleLog("info", "[emergency] SQL: " .. sql .. "\n"); + end + --freeswitch.consoleLog("info", "[template] SQL: " .. sql .. "body: " .. body .. "\n"); + +--get email from +local sql = "SELECT * FROM v_default_settings "; + sql = sql .. "WHERE default_setting_category = 'email' "; + sql = sql .. "AND (default_setting_subcategory = 'smtp_from' "; + sql = sql .. "OR default_setting_subcategory = 'smtp_from_name') "; + + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[emergency] SQL: " .. sql .. "\n"); + end + + dbh:query(sql, function(row) + if (row.default_setting_subcategory == "smtp_from") then + from = row.default_setting_value; + end + if (row.default_setting_subcategory == "smtp_from_name") then + from_name = row.default_setting_value; + end + end); + + + +-- get vars +domain_uuid = session:getVariable("domain_uuid"); +call_date = session:getVariable("call_date"); +caller_id_name = session:getVariable("caller_id_name"); +caller_id_number = session:getVariable("caller_id_number"); +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"); +call_duration = session:getVariable("call_duration"); + +--domain level check + result = {} +local sql = "SELECT count(domain_setting_value) "; + sql = sql .. "AS total "; + sql = sql .. "FROM v_domain_settings "; + sql = sql .. "WHERE domain_uuid = :domain_uuid "; + sql = sql .. "AND domain_setting_subcategory = :emergency_email_address "; + sql = sql .. "AND domain_setting_enabled = :status "; + + local params = {domain_uuid = domain_uuid, emergency_email_address = 'emergency_email_address', status = 't'} + + dbh:query(sql, params, function(result) + total = result.total; + --no emergency emails found under domain, using default + if (total == 0 or total == nil) then + to = {} + local sql = "SELECT default_setting_value "; + sql = sql .. "FROM v_default_settings "; + sql = sql .. "WHERE default_setting_category = :category "; + sql = sql .. "AND default_setting_subcategory = :emergency_email_address "; + sql = sql .. "AND default_setting_enabled = :status "; + sql = sql .. "LIMIT 5 "; + local params = {category = 'dialplan', emergency_email_address = 'emergency_email_address', status = 't'} + dbh:query(sql, params, function(result) + for key,row in pairs(result) do + table.insert(to, row); + freeswitch.consoleLog("info", "[emergency] Inserted into table from default settings " .. row .. "\n"); + end + --add some details + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[emergency] SQL: " .. sql .. " result " .. result .. "\n"); + end + end); + --domain level emails max 5 + else if (tonumber(total) <= 5) then + to = {} + local sql = "SELECT domain_setting_value "; + sql = sql .. "FROM v_domain_settings "; + sql = sql .. "WHERE domain_uuid = :domain_uuid "; + sql = sql .. "AND domain_setting_subcategory = :emergency_email_address "; + sql = sql .. "AND domain_setting_enabled = :status "; + local params = {domain_uuid = domain_uuid, emergency_email_address = 'emergency_email_address', status = 't'} + dbh:query(sql, params, function(result) + for key,row in pairs(result) do + table.insert(to, row); + freeswitch.consoleLog("info", "[template] Inserted into table " .. row .. "\n"); + end + end); + end + end + + end); + +dbh:release() + +if (#to > 0) then + --set event + destination_number = session:getVariable("destination_number"); + if (tonumber(destination_number) == 933) then + event = '933 Emergency Address Validation Service'; + else if (tonumber(destination_number) == 911) then + event = '911 Emergency Call'; + end + end + + --prepare the body + if (body ~= nil) then + body = body:gsub("${caller_id_name}", caller_id_name); + body = body:gsub("${caller_id_number}", caller_id_number); + 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); + end + + for key,row in ipairs(to) do + freeswitch.consoleLog("info", "[emergency] Sending to row " .. row .. " key " .. key .. "\n"); + --send the email + send_mail(headers, + from, + row, + {subject, body} + ); + end +end + +-- Insert into Emergency Logs +emergency_logs_uuid = api:executeString("create_uuid"); +domain_uuid = session:getVariable("domain_uuid"); + +-- Set time and date +local delimiter = " "; +local y = 0; +local tab = {} + +while true do + local endindex = call_date:find(delimiter,y); + if not endindex then + break + end + table.insert(tab,call_date:sub(y,endindex-1)) + y = endindex + 1; +end + +table.insert(tab,call_date:sub(y)); +local time = tab[2] .. " " .. tab[3]; + +freeswitch.consoleLog("info", "[emergency] Getting Date " .. tab[1] .. " Time " .. tab[2] .. " Format " .. tab[3] .. "\n"); + +--connect to the database +local dbh = Database.new('system'); + +local sql = "INSERT INTO v_emergency_logs ( "; + sql = sql .. " log_uuid, "; + sql = sql .. " domain_uuid, "; + sql = sql .. " date, "; + sql = sql .. " time, "; + sql = sql .. " extension, "; + sql = sql .. " event "; + sql = sql .. ") "; + sql = sql .. "VALUES ( "; + sql = sql .. " :emergency_logs_uuid, "; + sql = sql .. " :domain_uuid, "; + sql = sql .. " :date, "; + sql = sql .. " :time, "; + sql = sql .. " :extension, "; + sql = sql .. " :event "; + sql = sql .. ") "; + + local params = {emergency_logs_uuid = emergency_logs_uuid,domain_uuid = domain_uuid, date = tab[1], time = time, extension = caller_id_number, event = event} + + if (debug["sql"]) then + freeswitch.consoleLog("info", "[emergency] SQL: " .. sql .. "\n"); + end + + dbh:query(sql, params); + dbh:release();