diff --git a/app/contacts/app_config.php b/app/contacts/app_config.php index 074d198837..a7da3f7cfd 100644 --- a/app/contacts/app_config.php +++ b/app/contacts/app_config.php @@ -445,6 +445,10 @@ $apps[$x]['db'][$y]['fields'][$z]['type'] = "text"; $apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "Enter the extension."; $z++; + $apps[$x]['db'][$y]['fields'][$z]['name'] = "phone_speed_dial"; + $apps[$x]['db'][$y]['fields'][$z]['type'] = "text"; + $apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "Enter the speed dial."; + $z++; $apps[$x]['db'][$y]['fields'][$z]['name'] = "phone_description"; $apps[$x]['db'][$y]['fields'][$z]['type'] = "text"; $apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "Enter the description."; diff --git a/app/contacts/app_languages.php b/app/contacts/app_languages.php index a17b05f209..6186b51bf8 100644 --- a/app/contacts/app_languages.php +++ b/app/contacts/app_languages.php @@ -879,6 +879,17 @@ $text['label-phone_tools']['sv-se'] = "Verktyg"; $text['label-phone_tools']['de-at'] = "Funktionen"; $text['label-phone_tools']['he'] = "כלים"; +$text['label-phone_speed_dial']['en-us'] = "Speed Dial"; +$text['label-phone_speed_dial']['es-cl'] = ""; +$text['label-phone_speed_dial']['pt-pt'] = ""; +$text['label-phone_speed_dial']['fr-fr'] = ""; +$text['label-phone_speed_dial']['pt-br'] = ""; +$text['label-phone_speed_dial']['pl'] = ""; +$text['label-phone_speed_dial']['uk'] = ""; +$text['label-phone_speed_dial']['sv-se'] = ""; +$text['label-phone_speed_dial']['de-at'] = ""; +$text['label-phone_speed_dial']['he'] = ""; + $text['label-phone_numbers']['en-us'] = "Numbers"; $text['label-phone_numbers']['es-cl'] = "Números"; $text['label-phone_numbers']['pt-pt'] = "Números"; @@ -2019,6 +2030,17 @@ $text['description-phone_primary']['sv-se'] = "Sätt som primärt Nummer för de $text['description-phone_primary']['de-at'] = "Als primäre Nummer für diesen Kontakt setzen."; $text['description-phone_primary']['he'] = ""; +$text['description-phone_speed_dial']['en-us'] = "Enter the speed dial number."; +$text['description-phone_speed_dial']['es-cl'] = ""; +$text['description-phone_speed_dial']['pt-pt'] = ""; +$text['description-phone_speed_dial']['fr-fr'] = ""; +$text['description-phone_speed_dial']['pt-br'] = ""; +$text['description-phone_speed_dial']['pl'] = ""; +$text['description-phone_speed_dial']['uk'] = ""; +$text['description-phone_speed_dial']['sv-se'] = ""; +$text['description-phone_speed_dial']['de-at'] = ""; +$text['description-phone_speed_dial']['he'] = ""; + $text['description-phone_number']['en-us'] = "Enter the phone number."; $text['description-phone_number']['es-cl'] = "Ingrese el número de teléfono."; $text['description-phone_number']['pt-pt'] = "Introduza o número de telefone"; diff --git a/app/contacts/contact_phone_edit.php b/app/contacts/contact_phone_edit.php index 8e6c7d12ff..0677b5deaf 100644 --- a/app/contacts/contact_phone_edit.php +++ b/app/contacts/contact_phone_edit.php @@ -17,23 +17,27 @@ The Initial Developer of the Original Code is Mark J Crane - Portions created by the Initial Developer are Copyright (C) 2008-2012 + Portions created by the Initial Developer are Copyright (C) 2008-2016 the Initial Developer. All Rights Reserved. Contributor(s): Mark J Crane Luis Daniel Lucio Quiroz */ -require_once "root.php"; -require_once "resources/require.php"; -require_once "resources/check_auth.php"; -if (permission_exists('contact_phone_edit') || permission_exists('contact_phone_add')) { - //access granted -} -else { - echo "access denied"; - exit; -} + +//includes + require_once "root.php"; + require_once "resources/require.php"; + require_once "resources/check_auth.php"; + +//check permissions + if (permission_exists('contact_phone_edit') || permission_exists('contact_phone_add')) { + //access granted + } + else { + echo "access denied"; + exit; + } //add multi-lingual support $language = new text; @@ -48,9 +52,10 @@ else { $action = "add"; } -if (strlen($_GET["contact_uuid"]) > 0) { - $contact_uuid = check_str($_GET["contact_uuid"]); -} +//get the uuid + if (strlen($_GET["contact_uuid"]) > 0) { + $contact_uuid = check_str($_GET["contact_uuid"]); + } //get http post variables and set them to php variables if (count($_POST)>0) { @@ -60,6 +65,7 @@ if (strlen($_GET["contact_uuid"]) > 0) { $phone_type_text = check_str($_POST["phone_type_text"]); $phone_label = check_str($_POST["phone_label"]); $phone_label_custom = check_str($_POST["phone_label_custom"]); + $phone_speed_dial = check_str($_POST["phone_speed_dial"]); $phone_number = check_str($_POST["phone_number"]); $phone_extension = check_str($_POST["phone_extension"]); $phone_primary = check_str($_POST["phone_primary"]); @@ -128,6 +134,7 @@ if (strlen($_GET["contact_uuid"]) > 0) { $sql .= "phone_type_video, "; $sql .= "phone_type_text, "; $sql .= "phone_label, "; + $sql .= "phone_speed_dial, "; $sql .= "phone_number, "; $sql .= "phone_extension, "; $sql .= "phone_primary, "; @@ -143,6 +150,7 @@ if (strlen($_GET["contact_uuid"]) > 0) { $sql .= (($phone_type_video) ? 1 : 'null').", "; $sql .= (($phone_type_text) ? 1 : 'null').", "; $sql .= "'".$phone_label."', "; + $sql .= "'".$phone_speed_dial."', "; $sql .= "'".$phone_number."', "; $sql .= "'".$phone_extension."', "; $sql .= (($phone_primary) ? 1 : 0).", "; @@ -164,6 +172,7 @@ if (strlen($_GET["contact_uuid"]) > 0) { $sql .= "phone_type_video = ".(($phone_type_video) ? 1 : 'null').", "; $sql .= "phone_type_text = ".(($phone_type_text) ? 1 : 'null').", "; $sql .= "phone_label = '".$phone_label."', "; + $sql .= "phone_speed_dial = '".$phone_speed_dial."', "; $sql .= "phone_number = '".$phone_number."', "; $sql .= "phone_extension = '".$phone_extension."', "; $sql .= "phone_primary = ".(($phone_primary) ? 1 : 0).", "; @@ -195,6 +204,7 @@ if (strlen($_GET["contact_uuid"]) > 0) { $phone_type_video = $row["phone_type_video"]; $phone_type_text = $row["phone_type_text"]; $phone_label = $row["phone_label"]; + $phone_speed_dial = $row["phone_speed_dial"]; $phone_number = $row["phone_number"]; $phone_extension = $row["phone_extension"]; $phone_primary = $row["phone_primary"]; @@ -297,6 +307,17 @@ if (strlen($_GET["contact_uuid"]) > 0) { echo "\n"; echo "\n"; + echo "\n"; + echo "\n"; + echo " ".$text['label-phone_speed_dial']."\n"; + echo "\n"; + echo "\n"; + echo " \n"; + echo "
\n"; + echo $text['description-phone_speed_dial']."\n"; + echo "\n"; + echo "\n"; + echo "\n"; echo "\n"; echo " ".$text['label-phone_number']."\n"; @@ -360,4 +381,5 @@ if (strlen($_GET["contact_uuid"]) > 0) { //include the footer require_once "resources/footer.php"; + ?> diff --git a/app/dialplan/resources/switch/conf/dialplan/070_speed_dial.xml b/app/dialplan/resources/switch/conf/dialplan/070_speed_dial.xml new file mode 100644 index 0000000000..6e05afae3e --- /dev/null +++ b/app/dialplan/resources/switch/conf/dialplan/070_speed_dial.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/app/dialplan/resources/switch/conf/dialplan/490_do-not-disturb.xml b/app/dialplan/resources/switch/conf/dialplan/490_do-not-disturb.xml index d4943722e6..602dba354e 100644 --- a/app/dialplan/resources/switch/conf/dialplan/490_do-not-disturb.xml +++ b/app/dialplan/resources/switch/conf/dialplan/490_do-not-disturb.xml @@ -1,5 +1,9 @@ - + + + + + diff --git a/app/extensions/app_config.php b/app/extensions/app_config.php index 5e245014b3..71ff88d683 100644 --- a/app/extensions/app_config.php +++ b/app/extensions/app_config.php @@ -72,7 +72,7 @@ $apps[$x]['permissions'][$y]['groups'][] = "admin"; $y++; $apps[$x]['permissions'][$y]['name'] = "number_alias"; - //$apps[$x]['permissions'][$y]['groups'][] = "superadmin"; + $apps[$x]['permissions'][$y]['groups'][] = "superadmin"; //$apps[$x]['permissions'][$y]['groups'][] = "admin"; $y++; $apps[$x]['permissions'][$y]['name'] = "extension_toll"; diff --git a/resources/install/scripts/app/agent_status/index.lua b/resources/install/scripts/app/agent_status/index.lua index bd333d1721..b15da74b2c 100644 --- a/resources/install/scripts/app/agent_status/index.lua +++ b/resources/install/scripts/app/agent_status/index.lua @@ -6,8 +6,14 @@ debug["sql"] = true; --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); + +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end --set the api api = freeswitch.API(); @@ -66,14 +72,19 @@ end --get the agent password - sql = "SELECT * FROM v_call_center_agents "; - sql = sql .. "WHERE domain_uuid = '" .. domain_uuid .."' "; - sql = sql .. "AND agent_id = '" .. agent_id .."' "; + local params = {domain_uuid = domain_uuid, agent_id = agent_id} + local sql = "SELECT * FROM v_call_center_agents "; + sql = sql .. "WHERE domain_uuid = :domain_uuid "; + sql = sql .. "AND agent_id = :agent_id "; if (agent_authorized ~= 'true') then - sql = sql .. "AND agent_password = '" .. agent_password .."' "; + sql = sql .. "AND agent_password = :agent_password "; + params.agent_password = agent_password; end - freeswitch.consoleLog("notice", "[user status] sql: " .. sql .. "\n"); - dbh:query(sql, function(row) + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[user status] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); + end + + dbh:query(sql, params, function(row) --set the variables agent_name = row.agent_name; agent_id = row.agent_id; @@ -91,13 +102,14 @@ --get the user_uuid if (agent_authorized == 'true') then - sql = "SELECT user_uuid, user_status FROM v_users "; - sql = sql .. "WHERE username = '".. agent_name .."' "; - sql = sql .. "AND domain_uuid = '" .. domain_uuid .."' "; + local sql = "SELECT user_uuid, user_status FROM v_users "; + sql = sql .. "WHERE username = :agent_name "; + sql = sql .. "AND domain_uuid = :domain_uuid "; + local params = {agent_name = agent_name, domain_uuid = domain_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("NOTICE", "[call_center] sql: ".. sql .. "\n"); + freeswitch.consoleLog("notice", "[call_center] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - dbh:query(sql, function(row) + dbh:query(sql, params, function(row) --get the user info user_uuid = row.user_uuid; user_status = row.user_status; @@ -113,13 +125,14 @@ freeswitch.consoleLog("NOTICE", "[call_center] user_status: ".. status .. "\n"); --set the user_status in the users table - sql = "UPDATE v_users SET "; - sql = sql .. "user_status = '"..status.."' "; - sql = sql .. "WHERE user_uuid = '" .. user_uuid .."' "; + local sql = "UPDATE v_users SET "; + sql = sql .. "user_status = :status "; + sql = sql .. "WHERE user_uuid = :user_uuid "; + local params = {status = status, user_uuid = user_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("NOTICE", "[call_center] sql: ".. sql .. "\n"); + freeswitch.consoleLog("notice", "[call_center] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - dbh:query(sql); + dbh:query(sql, params); --send a login or logout to mod_callcenter cmd = "callcenter_config agent set status "..agent_name.."@"..domain_name.." '"..status.."'"; @@ -166,6 +179,16 @@ status = "Invalid ID or Password"; end +--set the status and presence + if (session:ready()) then + if (action == "login") then + session:execute("playback", sounds_dir.."/ivr/ivr-you_are_now_logged_in.wav"); + end + if (action == "logout") then + session:execute("playback", sounds_dir.."/ivr/ivr-you_are_now_logged_out.wav"); + end + end + --send the status to the display if (status ~= nil) then reply = api:executeString("uuid_display "..uuid.." '"..status.."'"); @@ -175,15 +198,3 @@ if (session:ready()) then session:execute("sleep", "2000"); end - ---set the status and presence - if (session:ready()) then - if (action == "login") then - session:execute("playback", sounds_dir.."/ivr/ivr-you_are_now_logged_in.wav"); - --session:execute("playback", "tone_stream://%(500,0,300,200,100,50,25)"); - end - if (action == "logout") then - session:execute("playback", sounds_dir.."/ivr/ivr-you_are_now_logged_out.wav"); - --session:execute("playback", "tone_stream://%(200,0,500,600,700)"); - end - end diff --git a/resources/install/scripts/app/call_block/index.lua b/resources/install/scripts/app/call_block/index.lua index 5c8117ee69..b2d6723225 100644 --- a/resources/install/scripts/app/call_block/index.lua +++ b/resources/install/scripts/app/call_block/index.lua @@ -46,12 +46,17 @@ This method causes the script to get its manadatory arguments directly from the -- Command line parameters local params = { - cid_num = string.match(tostring(session:getVariable("caller_id_number")), "%d+"), - cid_name = session:getVariable("caller_id_name"), - domain_name = session:getVariable("domain_name"), - userid = "", -- session:getVariable("id") - loglevel = "W" -- Warning, Debug, Info - } + cid_num = string.match(tostring(session:getVariable("caller_id_number")), "%d+"), + cid_name = session:getVariable("caller_id_name"), + domain_name = session:getVariable("domain_name"), + userid = "", -- session:getVariable("id") + loglevel = "W" -- Warning, Debug, Info + } + +--check if cid_num is numeric + if (tonumber(params["cid_num"]) == nil) then + return + end -- local storage local sql = nil @@ -88,8 +93,8 @@ This method causes the script to get its manadatory arguments directly from the --if not cached then get the information from the database if (cache == "-ERR NOT FOUND") then --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + Database = require "resources.functions.database"; + dbh = Database.new('system'); --log if not connect if dbh:connected() == false then @@ -99,14 +104,14 @@ This method causes the script to get its manadatory arguments directly from the --check if the the call block is blocked sql = "SELECT * FROM v_call_block as c " sql = sql .. "JOIN v_domains as d ON c.domain_uuid=d.domain_uuid " - sql = sql .. "WHERE c.call_block_number = '" .. params["cid_num"] .. "' AND d.domain_name = '" .. params["domain_name"] .."'" - status = dbh:query(sql, function(rows) + sql = sql .. "WHERE c.call_block_number = :cid_num AND d.domain_name = :domain_name " + dbh:query(sql, params, function(rows) found_cid_num = rows["call_block_number"]; found_uuid = rows["call_block_uuid"]; found_enabled = rows["call_block_enabled"]; found_action = rows["call_block_action"]; found_count = rows["call_block_count"]; - end) + end) -- dbh:affected_rows() doesn't do anything if using core:db so this is the workaround: --set the cache @@ -171,7 +176,9 @@ This method causes the script to get its manadatory arguments directly from the k = k + 1 end if (source == "database") then - dbh:query("UPDATE v_call_block SET call_block_count = " .. found_count + 1 .. " WHERE call_block_uuid = '" .. found_uuid .. "'") + dbh:query("UPDATE v_call_block SET call_block_count = :call_block_count WHERE call_block_uuid = :call_block_uuid",{ + call_block_count = found_count + 1, call_block_uuid = found_uuid + }) end session:execute("set", "call_blocked=true"); logger("W", "NOTICE", "number " .. params["cid_num"] .. " blocked with " .. found_count .. " previous hits, domain_name: " .. params["domain_name"]) diff --git a/resources/install/scripts/app/conference_center/index.lua b/resources/install/scripts/app/conference_center/index.lua index 1e0ce98c61..581f1b2617 100644 --- a/resources/install/scripts/app/conference_center/index.lua +++ b/resources/install/scripts/app/conference_center/index.lua @@ -37,8 +37,14 @@ debug["sql"] = false; --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); + +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end --prepare the api object api = freeswitch.API(); @@ -80,11 +86,11 @@ end --get the moderator_pin - sql = [[SELECT moderator_pin FROM v_meetings - WHERE meeting_uuid = ']] .. meeting_uuid ..[[']]; - freeswitch.consoleLog("notice", "[voicemail] sql: " .. sql .. "\n"); - status = dbh:query(sql, function(row) - moderator_pin = string.lower(row["moderator_pin"]); + local sql = "SELECT moderator_pin FROM v_meetings WHERE meeting_uuid = :meeting_uuid"; + local params = {meeting_uuid = meeting_uuid} + freeswitch.consoleLog("notice", "[voicemail] sql: " .. sql .. "; params:" .. json.encode(params) .. "\n"); + dbh:query(sql, params, function(row) + moderator_pin = string.lower(row["moderator_pin"]); end); --get the link_address @@ -159,19 +165,19 @@ end_epoch = os.time(); --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + dbh = Database.new('system'); --get the conference sessions if (conference_session_uuid) then - sql = [[SELECT count(*) as num_rows + local sql = [[SELECT count(*) as num_rows FROM v_conference_sessions - WHERE conference_session_uuid = ']] .. conference_session_uuid ..[[']]; - status = dbh:query(sql, function(row) - num_rows = string.lower(row["num_rows"]); + WHERE conference_session_uuid = :conference_session_uuid]]; + local params = {conference_session_uuid = conference_session_uuid}; + dbh:query(sql, params, function(row) + num_rows = string.lower(row["num_rows"]); end); if (debug["sql"]) then - freeswitch.consoleLog("notice", "[conference center] SQL: " .. sql .. " Rows: "..num_rows.."\n"); + freeswitch.consoleLog("notice", "[conference center] SQL: " .. sql .. "; params:" .. json.encode(params) .. "; Rows: "..num_rows.."\n"); end if (tonumber(num_rows) == 0) then local sql = {} @@ -191,22 +197,35 @@ table.insert(sql, ") "); table.insert(sql, "VALUES "); table.insert(sql, "( "); - table.insert(sql, "'".. conference_session_uuid .."', "); - table.insert(sql, "'".. domain_uuid .."', "); - table.insert(sql, "'".. meeting_uuid .."', "); + table.insert(sql, ":conference_session_uuid, "); + table.insert(sql, ":domain_uuid, "); + table.insert(sql, ":meeting_uuid, "); --if (conference_recording) then - -- table.insert(sql, "'".. conference_recording .."', "); + -- table.insert(sql, ":conference_recording, "); --end --if (wait_mod) then - -- table.insert(sql, "'".. wait_mod .."', "); + -- table.insert(sql, ":wait_mod, "); --end - --table.insert(sql, "'".. start_epoch .."', "); - table.insert(sql, "'".. profile .."' "); + --table.insert(sql, ":start_epoch, "); + table.insert(sql, ":profile "); table.insert(sql, ") "); - SQL_STRING = table.concat(sql, "\n"); - dbh:query(SQL_STRING); + + sql = table.concat(sql, "\n"); + + local params = { + conference_session_uuid = conference_session_uuid; + domain_uuid = domain_uuid; + meeting_uuid = meeting_uuid; + -- conference_recording = conference_recording; + -- wait_mod = wait_mod; + -- start_epoch = start_epoch; + profile = profile; + }; + + dbh:query(sql, params); + if (debug["sql"]) then - freeswitch.consoleLog("notice", "[conference center] SQL: " .. SQL_STRING .. "\n"); + freeswitch.consoleLog("notice", "[conference center] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end end end @@ -233,23 +252,37 @@ table.insert(sql, ") "); table.insert(sql, "VALUES "); table.insert(sql, "( "); - table.insert(sql, "'".. conference_session_detail_uuid .."', "); - table.insert(sql, "'".. domain_uuid .."', "); - table.insert(sql, "'".. conference_session_uuid .."', "); - table.insert(sql, "'".. meeting_uuid .."', "); - table.insert(sql, "'".. username .."', "); - table.insert(sql, "'".. caller_id_name .."', "); - table.insert(sql, "'".. caller_id_number .."', "); - table.insert(sql, "'".. network_addr .."', "); - table.insert(sql, "'".. uuid .."', "); + table.insert(sql, ":conference_session_detail_uuid, "); + table.insert(sql, ":domain_uuid, "); + table.insert(sql, ":conference_session_uuid, "); + table.insert(sql, ":meeting_uuid, "); + table.insert(sql, ":username, "); + table.insert(sql, ":caller_id_name, "); + table.insert(sql, ":caller_id_number, "); + table.insert(sql, ":network_addr, "); + table.insert(sql, ":uuid, "); if (conference_moderator) then - table.insert(sql, "'".. conference_moderator .."', "); + table.insert(sql, ":conference_moderator, "); end - table.insert(sql, "'".. start_epoch .."', "); - table.insert(sql, "'".. end_epoch .."' "); + table.insert(sql, ":start_epoch, "); + table.insert(sql, ":end_epoch "); table.insert(sql, ") "); - SQL_STRING = table.concat(sql, "\n"); - dbh:query(SQL_STRING); + sql = table.concat(sql, "\n"); + local params = { + conference_session_detail_uuid = conference_session_detail_uuid; + domain_uuid = domain_uuid; + conference_session_uuid = conference_session_uuid; + meeting_uuid = meeting_uuid; + username = username; + caller_id_name = caller_id_name; + caller_id_number = caller_id_number; + network_addr = network_addr; + uuid = uuid; + conference_moderator = conference_moderator; + start_epoch = start_epoch; + end_epoch = end_epoch; + }; + dbh:query(sql, params); end --if the conference is empty @@ -258,15 +291,16 @@ result = trim(api:executeString(cmd)); if (string.sub(result, -9) == "not found") then --get the conference start_epoch - sql = [[SELECT start_epoch + local sql = [[SELECT start_epoch FROM v_conference_session_details - WHERE conference_session_uuid = ']] .. conference_session_uuid ..[[' + WHERE conference_session_uuid = :conference_session_uuid ORDER BY start_epoch ASC LIMIT 1]]; - status = dbh:query(sql, function(row) - start_epoch = string.lower(row["start_epoch"]); + local params = {conference_session_uuid = conference_session_uuid}; + dbh:query(sql, params, function(row) + start_epoch = string.lower(row["start_epoch"]); end); - --freeswitch.consoleLog("notice", "[conference center] sql: " .. sql .. "\n"); + --freeswitch.consoleLog("notice", "[conference center] sql: " .. sql .. "; params:" .. json.encode(params) .. "\n"); --set the conference_recording conference_recording = recordings_dir.."/archive/"..os.date("%Y", start_epoch).."/"..os.date("%b", start_epoch).."/"..os.date("%d", start_epoch) .."/"..conference_session_uuid; @@ -274,15 +308,21 @@ --conference has ended set the end_epoch local sql = {} table.insert(sql, "update v_conference_sessions set "); - table.insert(sql, "recording = '".. conference_recording .."', "); - table.insert(sql, "start_epoch = '".. start_epoch .."', "); - table.insert(sql, "end_epoch = '".. end_epoch .."' "); - table.insert(sql, "where conference_session_uuid = '"..conference_session_uuid.."' "); - SQL_STRING = table.concat(sql, "\n"); + table.insert(sql, "recording = :conference_recording, "); + table.insert(sql, "start_epoch = :start_epoch, "); + table.insert(sql, "end_epoch = :end_epoch "); + table.insert(sql, "where conference_session_uuid = :conference_session_uuid "); + sql = table.concat(sql, "\n"); + local params = { + conference_recording = conference_recording; + start_epoch = start_epoch; + end_epoch = end_epoch; + conference_session_uuid = conference_session_uuid; + }; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[conference center] SQL: " .. SQL_STRING .. "\n"); + freeswitch.consoleLog("notice", "[conference center] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - dbh:query(SQL_STRING); + dbh:query(sql, params); --convert the wav to an mp3 if (record == "true") then --cmd = "sox "..conference_recording..".wav -r 16000 -c 1 "..conference_recording..".mp3"; @@ -358,21 +398,23 @@ --get the domain_uuid if (domain_name ~= nil and domain_uuid == nil) then - sql = "SELECT domain_uuid FROM v_domains "; - sql = sql .. "WHERE domain_name = '" .. domain_name .."' "; + local sql = "SELECT domain_uuid FROM v_domains "; + sql = sql .. "WHERE domain_name = :domain_name "; + local params = {domain_name = domain_name}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[conference center] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[conference center] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(rows) + dbh:query(sql, params, function(rows) domain_uuid = string.lower(rows["domain_uuid"]); end); end --conference center details - sql = [[SELECT * FROM v_conference_centers - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND conference_center_extension = ']] .. destination_number .. [[']]; - status = dbh:query(sql, function(row) + local sql = [[SELECT * FROM v_conference_centers + WHERE domain_uuid = :domain_uuid + AND conference_center_extension = :destination_number]]; + local params = {domain_uuid = domain_uuid, destination_number = destination_number}; + dbh:query(sql, params, function(row) conference_center_uuid = string.lower(row["conference_center_uuid"]); conference_center_greeting = row["conference_center_greeting"]; end); @@ -381,29 +423,24 @@ end --connect to the switch database - if (file_exists(database_dir.."/core.db")) then - dbh_switch = freeswitch.Dbh("sqlite://"..database_dir.."/core.db"); - if (debug["sql"]) then - freeswitch.consoleLog("notice", "[conference center] dbh_switch sqlite\n"); - end - else - if (debug["sql"]) then - freeswitch.consoleLog("notice", "[conference center] dbh_switch pgsql/mysql\n"); - end - dbh_switch = database_handle('switch'); - end + local dbh_switch = Database.new('switch') --check if someone has already joined the conference local_hostname = trim(api:execute("switchname", "")); freeswitch.consoleLog("notice", "[conference center] local_hostname is " .. local_hostname .. "\n"); - sql = "SELECT hostname FROM channels WHERE application = 'conference' AND dest = '" .. destination_number .. "' AND cid_num <> '".. caller_id_number .."' LIMIT 1"; + sql = "SELECT hostname FROM channels WHERE application = 'conference' " + .. "AND dest = :destination_number AND cid_num <> :caller_id_number LIMIT 1"; + params = {destination_number = destination_number, caller_id_number = caller_id_number}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[conference center] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[conference center] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - status = dbh_switch:query(sql, function(rows) + dbh_switch:query(sql, params, function(rows) conference_hostname = rows["hostname"]; end); + --close the database connection + dbh_switch:release(); + --if conference hosntame exist, then we bridge there if (conference_hostname ~= nil) then freeswitch.consoleLog("notice", "[conference center] conference_hostname is " .. conference_hostname .. "\n"); @@ -447,42 +484,46 @@ digit_timeout = 5000; pin_number = session:playAndGetDigits(min_digits, max_digits, max_tries, digit_timeout, "#", prompt_audio_file, "", "\\d+"); end - if (pin_number ~= "") then - sql = [[SELECT * FROM v_conference_rooms as r, v_meetings as m - WHERE r.domain_uuid = ']] .. domain_uuid ..[[' - AND r.meeting_uuid = m.meeting_uuid - AND m.domain_uuid = ']] .. domain_uuid ..[[' - AND (m.moderator_pin = ']] .. pin_number ..[[' or m.participant_pin = ']] .. pin_number ..[[') - AND r.enabled = 'true' - AND m.enabled = 'true' - AND ( - ( r.start_datetime <> '' AND r.start_datetime is not null AND r.start_datetime <= ']] .. os.date("%Y-%m-%d %X") .. [[' ) OR - ( r.start_datetime = '' OR r.start_datetime is null ) - ) - AND ( - ( r.stop_datetime <> '' AND r.stop_datetime is not null AND r.stop_datetime > ']] .. os.date("%Y-%m-%d %X") .. [[' ) OR - ( r.stop_datetime = '' OR r.stop_datetime is null ) - ) ]]; - if (debug["sql"]) then - freeswitch.consoleLog("notice", "[conference center] SQL: " .. sql .. "\n"); + --use the pin_number to find the conference room + if (pin_number ~= "") then + local sql = [[SELECT * FROM v_conference_rooms as r, v_meetings as m + WHERE r.domain_uuid = :domain_uuid + AND r.meeting_uuid = m.meeting_uuid + AND m.domain_uuid = :domain_uuid + AND (m.moderator_pin = :pin_number or m.participant_pin = :pin_number) + AND r.enabled = 'true' + AND m.enabled = 'true' + AND ( + ( r.start_datetime <> '' AND r.start_datetime is not null AND r.start_datetime <= :timestam ) OR + ( r.start_datetime = '' OR r.start_datetime is null ) + ) + AND ( + ( r.stop_datetime <> '' AND r.stop_datetime is not null AND r.stop_datetime > :timestam ) OR + ( r.stop_datetime = '' OR r.stop_datetime is null ) + ) ]]; + local params = { + domain_uuid = domain_uuid; + pin_number = pin_number; + timestam = os.date("%Y-%m-%d %X"); + }; + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[conference center] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); + end + dbh:query(sql, params, function(row) + conference_room_uuid = string.lower(row["conference_room_uuid"]); + end); + end + --if the conference room was not found then return nil + if (conference_room_uuid == nil) then + return nil; + else + return pin_number; end - status = dbh:query(sql, function(row) - conference_room_uuid = string.lower(row["conference_room_uuid"]); - end); - end - if (conference_room_uuid == nil) then - return nil; - else - return pin_number; - end end --get the pin pin_number = session:getVariable("pin_number"); - if (not pin_number) then - pin_number = nil; - pin_number = get_pin_number(domain_uuid, conference_center_greeting); - end + pin_number = get_pin_number(domain_uuid, conference_center_greeting); if (pin_number == nil) then pin_number = get_pin_number(domain_uuid, conference_center_greeting); end @@ -495,19 +536,24 @@ pin_number = get_pin_number(domain_uuid, conference_center_greeting); end if (pin_number ~= nil) then - sql = [[SELECT * FROM v_conference_rooms as r, v_meetings as m - WHERE r.domain_uuid = ']] .. domain_uuid ..[[' + local sql = [[SELECT * FROM v_conference_rooms as r, v_meetings as m + WHERE r.domain_uuid = :domain_uuid AND r.meeting_uuid = m.meeting_uuid - AND r.conference_center_uuid = ']] .. conference_center_uuid ..[[' - AND m.domain_uuid = ']] .. domain_uuid ..[[' - AND (m.moderator_pin = ']] .. pin_number ..[[' or m.participant_pin = ']] .. pin_number ..[[') + AND r.conference_center_uuid = :conference_center_uuid + AND m.domain_uuid = :domain_uuid + AND (m.moderator_pin = :pin_number or m.participant_pin = :pin_number) AND r.enabled = 'true' AND m.enabled = 'true' - ]]; + ]]; + local params = { + domain_uuid = domain_uuid; + conference_center_uuid = conference_center_uuid; + pin_number = pin_number; + }; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[conference center] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[conference center] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(row) + dbh:query(sql, params, function(row) conference_room_uuid = string.lower(row["conference_room_uuid"]); meeting_uuid = string.lower(row["meeting_uuid"]); record = string.lower(row["record"]); diff --git a/resources/install/scripts/app/fax/resources/scripts/hangup_rx.lua b/resources/install/scripts/app/fax/resources/scripts/hangup_rx.lua index 990cc2ae7c..c18eec80a0 100644 --- a/resources/install/scripts/app/fax/resources/scripts/hangup_rx.lua +++ b/resources/install/scripts/app/fax/resources/scripts/hangup_rx.lua @@ -32,8 +32,14 @@ require "resources.functions.config"; --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); + +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end --define the explode function require "resources.functions.explode"; @@ -58,8 +64,8 @@ --get the domain_uuid using the domain name required for multi-tenant if (domain_name ~= nil) then sql = "SELECT domain_uuid FROM v_domains "; - sql = sql .. "WHERE domain_name = '" .. domain_name .. "' "; - status = dbh:query(sql, function(rows) + sql = sql .. "WHERE domain_name = :domain_name "; + dbh:query(sql, {domain_name = domain_name}, function(rows) domain_uuid = rows["domain_uuid"]; end); end @@ -154,13 +160,14 @@ end --get the fax settings from the database - sql = [[SELECT * FROM v_fax - WHERE fax_uuid = ']] .. fax_uuid ..[[' - AND domain_uuid = ']] .. domain_uuid ..[[']]; + local sql = [[SELECT * FROM v_fax + WHERE fax_uuid = :fax_uuid + AND domain_uuid = :domain_uuid]]; + local params = {fax_uuid = fax_uuid, domain_uuid = domain_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[fax] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[fax] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(row) + dbh:query(sql, params, function(row) dialplan_uuid = row["dialplan_uuid"]; fax_extension = row["fax_extension"]; fax_accountcode = row["accountcode"]; @@ -247,57 +254,72 @@ sql = sql .. ") "; sql = sql .. "values "; sql = sql .. "("; - sql = sql .. "'"..uuid.."', "; - sql = sql .. "'"..domain_uuid.."', "; + sql = sql .. ":uuid, "; + sql = sql .. ":domain_uuid, "; if (fax_uuid ~= nil) then - sql = sql .. "'"..fax_uuid.."', "; + sql = sql .. ":fax_uuid, "; end - sql = sql .. "'"..fax_success.."', "; - sql = sql .. "'"..fax_result_code .."', "; - sql = sql .. "'"..fax_result_text.."', "; - sql = sql .. "'"..fax_file.."', "; + sql = sql .. ":fax_success, "; + sql = sql .. ":fax_result_code, "; + sql = sql .. ":fax_result_text, "; + sql = sql .. ":fax_file, "; if (fax_ecm_used ~= nil) then - sql = sql .. "'"..fax_ecm_used.."', "; + sql = sql .. ":fax_ecm_used, "; end if (fax_local_station_id ~= nil) then - sql = sql .. "'"..fax_local_station_id.."', "; - end - if (fax_document_transferred_pages == nil) then - sql = sql .. "'0', "; - else - sql = sql .. "'"..fax_document_transferred_pages.."', "; - end - if (fax_document_total_pages == nil) then - sql = sql .. "'0', "; - else - sql = sql .. "'"..fax_document_total_pages.."', "; + sql = sql .. ":fax_local_station_id, "; end + sql = sql .. ":fax_document_transferred_pages, "; + sql = sql .. ":fax_document_total_pages, "; if (fax_image_resolution ~= nil) then - sql = sql .. "'"..fax_image_resolution.."', "; + sql = sql .. ":fax_image_resolution, "; end if (fax_image_size ~= nil) then - sql = sql .. "'"..fax_image_size.."', "; + sql = sql .. ":fax_image_size, "; end if (fax_bad_rows ~= nil) then - sql = sql .. "'"..fax_bad_rows.."', "; + sql = sql .. ":fax_bad_rows, "; end if (fax_transfer_rate ~= nil) then - sql = sql .. "'"..fax_transfer_rate.."', "; + sql = sql .. ":fax_transfer_rate, "; end if (fax_uri ~= nil) then - sql = sql .. "'"..fax_uri.."', "; + sql = sql .. ":fax_uri, "; end if (database["type"] == "sqlite") then - sql = sql .. "'"..os.date("%Y-%m-%d %X").."', "; + sql = sql .. ":fax_date, "; else sql = sql .. "now(), "; end - sql = sql .. "'"..os.time().."' "; + sql = sql .. ":fax_time "; sql = sql .. ")"; + + local params = { + uuid = uuid; + domain_uuid = domain_uuid; + fax_uuid = fax_uuid; + fax_success = fax_success; + fax_result_code = fax_result_code; + fax_result_text = fax_result_text; + fax_file = fax_file; + fax_ecm_used = fax_ecm_used; + fax_local_station_id = fax_local_station_id; + fax_document_transferred_pages = fax_document_transferred_pages or '0'; + fax_document_total_pages = fax_document_total_pages or '0'; + fax_image_resolution = fax_image_resolution; + fax_image_size = fax_image_size; + fax_bad_rows = fax_bad_rows; + fax_transfer_rate = fax_transfer_rate; + fax_uri = fax_uri; + fax_date = os.date("%Y-%m-%d %X"); + fax_time = os.time(); + }; + if (debug["sql"]) then - freeswitch.consoleLog("notice", "[fax] "..sql.."\n"); + freeswitch.consoleLog("notice", "[fax] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - dbh:query(sql); + + dbh:query(sql, params); --add the fax files if (fax_success ~= nil) then @@ -333,39 +355,49 @@ table.insert(sql, ") "); table.insert(sql, "values "); table.insert(sql, "("); - table.insert(sql, "'" .. uuid .. "', "); - table.insert(sql, "'" .. fax_uuid .. "', "); + table.insert(sql, ":uuid, "); + table.insert(sql, ":fax_uuid, "); table.insert(sql, "'rx', "); table.insert(sql, "'tif', "); - table.insert(sql, "'" .. fax_file .. "', "); + table.insert(sql, ":fax_file, "); if (caller_id_name ~= nil) then - table.insert(sql, "'" .. caller_id_name .. "', "); + table.insert(sql, ":caller_id_name, "); end if (caller_id_number ~= nil) then - table.insert(sql, "'" .. caller_id_number .. "', "); + table.insert(sql, ":caller_id_number, "); end if (database["type"] == "sqlite") then - table.insert(sql, "'"..os.date("%Y-%m-%d %X").."', "); + table.insert(sql, ":fax_date, "); else table.insert(sql, "now(), "); end - table.insert(sql, "'" .. os.time() .. "', "); + table.insert(sql, ":fax_time, "); if (storage_type == "base64") then - table.insert(sql, "'" .. fax_base64 .. "', "); + table.insert(sql, ":fax_base64, "); end - table.insert(sql, "'" .. domain_uuid .. "'"); + table.insert(sql, ":domain_uuid"); table.insert(sql, ")"); sql = table.concat(sql, "\n"); + local params = { + uuid = uuid; + domain_uuid = domain_uuid; + fax_uuid = fax_uuid; + fax_file = fax_file; + caller_id_name = caller_id_name; + caller_id_number = caller_id_number; + fax_base64 = fax_base64; + fax_date = os.date("%Y-%m-%d %X"); + fax_time = os.time(); + }; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[fax] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[fax] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end if (storage_type == "base64") then - local Database = require "resources.functions.database" local dbh = Database.new('system', 'base64'); - dbh:query(sql); + dbh:query(sql, params); dbh:release(); else - result = dbh:query(sql); + result = dbh:query(sql, params); end end end 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 e47ef9afa2..e35f97d85d 100644 --- a/resources/install/scripts/app/fax/resources/scripts/queue/retry.lua +++ b/resources/install/scripts/app/fax/resources/scripts/queue/retry.lua @@ -9,6 +9,12 @@ local Tasks = require "app.fax.resources.scripts.queue.tasks" local send_mail = require "resources.functions.send_mail" +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end + local fax_task_uuid = env:getHeader('fax_task_uuid') if not fax_task_uuid then log.warning("No [fax_task_uuid] channel variable") @@ -204,42 +210,49 @@ "fax_retry_limit"; "fax_retry_sleep"; "fax_uri"; - "fax_date"; "fax_epoch"; } - local values = { - "'"..uuid .. "'"; - "'"..domain_uuid .. "'"; - opt(fax_uuid); - opt(fax_success); - opt(fax_result_code); - opt(fax_result_text); - opt(fax_file); - opt(fax_ecm_used); - opt(fax_local_station_id); - opt(fax_document_transferred_pages, "'0'"); - opt(fax_document_total_pages, "'0'"); - opt(fax_image_resolution); - opt(fax_image_size); - opt(fax_bad_rows); - opt(fax_transfer_rate); - opt(fax_retry_attempts); - opt(fax_retry_limit); - opt(fax_retry_sleep); - opt(fax_uri); - now_sql(); - "'"..os.time().."' "; + local params = { + fax_log_uuid = uuid; + domain_uuid = domain_uuid; + fax_uuid = fax_uuid or dbh.NULL; + fax_success = fax_success or dbh.NULL; + fax_result_code = fax_result_code or dbh.NULL; + fax_result_text = fax_result_text or dbh.NULL; + fax_file = fax_file or dbh.NULL; + fax_ecm_used = fax_ecm_used or dbh.NULL; + fax_local_station_id = fax_local_station_id or dbh.NULL; + fax_document_transferred_pages = fax_document_transferred_pages or "'0'"; + fax_document_total_pages = fax_document_total_pages or "'0'"; + fax_image_resolution = fax_image_resolution or dbh.NULL; + fax_image_size = fax_image_size or dbh.NULL; + fax_bad_rows = fax_bad_rows or dbh.NULL; + fax_transfer_rate = fax_transfer_rate or dbh.NULL; + fax_retry_attempts = fax_retry_attempts or dbh.NULL; + fax_retry_limit = fax_retry_limit or dbh.NULL; + fax_retry_sleep = fax_retry_sleep or dbh.NULL; + fax_uri = fax_uri or dbh.NULL; + fax_epoch = os.time(); } - local sql = "insert into v_fax_logs(" .. table.concat(fields, ",") .. ")" .. - "values(" .. table.concat(values, ",") .. ")" + local values = ":" .. table.concat(fields, ",:") + fields = table.concat(fields, ",") .. ",fax_date" - if (debug["sql"]) then - log.noticef("SQL: %s", sql); + if database["type"] == "sqlite" then + params.fax_date = os.date("%Y-%m-%d %X"); + values = values .. ",:fax_date" + else + values = values .. ",now()" end - dbh:query(sql); + local sql = "insert into v_fax_logs(" .. fields .. ")values(" .. values .. ")" + + if (debug["sql"]) then + log.noticef("SQL: %s; params: %s", sql, json.encode(params, dbh.NULL)); + end + + dbh:query(sql, params); end -- add the fax files @@ -259,49 +272,58 @@ -- build SQL local sql do - sql = { - "insert into v_fax_files("; - "fax_file_uuid"; ","; - "fax_uuid"; ","; - "fax_mode"; ","; - "fax_destination"; ","; - "fax_file_type"; ","; - "fax_file_path"; ","; - "fax_caller_id_name"; ","; - "fax_caller_id_number"; ","; - "fax_date"; ","; - "fax_epoch"; ","; - "fax_base64"; ","; - "domain_uuid"; " "; - ") values ("; - opt(uuid); ","; - opt(fax_uuid); ","; - "'tx'"; ","; - opt(sip_to_user); ","; - "'tif'"; ","; - opt(fax_file); ","; - opt(origination_caller_id_name); ","; - opt(origination_caller_id_number); ","; - now_sql(); ","; - "'" .. os.time() .. "'"; ","; - opt(fax_base64); ","; - opt(domain_uuid); " "; - ")" + + local fields = { + "fax_file_uuid"; + "fax_uuid"; + "fax_mode"; + "fax_destination"; + "fax_file_type"; + "fax_file_path"; + "fax_caller_id_name"; + "fax_caller_id_number"; + "fax_epoch"; + "fax_base64"; + "domain_uuid"; } - sql = table.concat(sql, "\n"); - if (debug["sql"]) then - log.noticef("SQL: %s", sql); - end - end + local params = { + fax_file_uuid = uuid; + fax_uuid = fax_uuid or dbh.NULL; + fax_mode = "tx"; + fax_destination = sip_to_user or dbh.NULL; + fax_file_type = "tif"; + fax_file_path = fax_file or dbh.NULL; + fax_caller_id_name = origination_caller_id_name or dbh.NULL; + fax_caller_id_number = origination_caller_id_number or dbh.NULL; + fax_epoch = os.time(); + fax_base64 = fax_base64 or dbh.NULL; + domain_uuid = domain_uuid or dbh.NULL; + } - if storage_type == "base64" then - local Database = require "resources.functions.database" - local dbh = Database.new('system', 'base64'); - dbh:query(sql); - dbh:release(); - else - result = dbh:query(sql) + local values = ":" .. table.concat(fields, ",:") + fields = table.concat(fields, ",") .. ",fax_date" + + if database["type"] == "sqlite" then + params.fax_date = os.date("%Y-%m-%d %X"); + values = values .. ",:fax_date" + else + values = values .. ",now()" + end + + local sql = "insert into v_fax_files(" .. fields .. ")values(" .. values .. ")" + + if (debug["sql"]) then + log.noticef("SQL: %s; params: %s", sql, json.encode(params, dbh.NULL)); + end + + if storage_type == "base64" then + local dbh = Database.new('system', 'base64'); + dbh:query(sql, params); + dbh:release(); + else + dbh:query(sql, params) + end end end @@ -390,7 +412,7 @@ os.remove(fax_file); end - end end end + end diff --git a/resources/install/scripts/app/is_local/index.lua b/resources/install/scripts/app/is_local/index.lua index cad93afe82..2175a9fe45 100644 --- a/resources/install/scripts/app/is_local/index.lua +++ b/resources/install/scripts/app/is_local/index.lua @@ -29,8 +29,13 @@ outbound_caller_id_number = session:getVariable("outbound_caller_id_number"); --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end --prepare the api object api = freeswitch.API(); @@ -43,13 +48,18 @@ --get the destination number if (cache == "-ERR NOT FOUND") then - sql = "SELECT destination_number, destination_context " + local dbh = Database.new('system'); + + local sql = "SELECT destination_number, destination_context " sql = sql .. "FROM v_destinations " - sql = sql .. "WHERE destination_number = '"..destination_number.."' " + sql = sql .. "WHERE destination_number = :destination_number " sql = sql .. "AND destination_type = 'inbound' " sql = sql .. "AND destination_enabled = 'true' " - --freeswitch.consoleLog("notice", "SQL:" .. sql .. "\n"); - assert(dbh:query(sql, function(row) + local params = {destination_number = destination_number}; + if (debug["sql"]) then + freeswitch.consoleLog("notice", "SQL:" .. sql .. "; params: " .. json.encode(params) .. "\n"); + end + dbh:query(sql, params, function(row) --set the outbound caller id if (outbound_caller_id_name ~= nil) then @@ -77,7 +87,8 @@ --transfer the call session:transfer(row.destination_number, "XML", row.destination_context); - end)); + end); + else --add the function require "resources.functions.explode"; diff --git a/resources/install/scripts/app/provision/index.lua b/resources/install/scripts/app/provision/index.lua index b304d7bdeb..de162f5a75 100644 --- a/resources/install/scripts/app/provision/index.lua +++ b/resources/install/scripts/app/provision/index.lua @@ -37,8 +37,14 @@ profile = "internal"; --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); + +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end --answer session:answer(); @@ -92,14 +98,15 @@ --get the device uuid for the phone that will have its configuration overridden if (user ~= nil and domain ~= nil and domain_uuid ~= nil) then - sql = [[SELECT * FROM v_device_lines ]]; - sql = sql .. [[WHERE user_id = ']] .. user .. [[' ]]; - sql = sql .. [[AND server_address = ']]..domain..[[' ]]; - sql = sql .. [[AND domain_uuid = ']]..domain_uuid..[[' ]]; + local sql = [[SELECT device_uuid FROM v_device_lines ]]; + sql = sql .. [[WHERE user_id = :user ]]; + sql = sql .. [[AND server_address = :domain ]]; + sql = sql .. [[AND domain_uuid = :domain_uuid ]]; + local params = {user = user, domain = domain, domain_uuid = domain_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("NOTICE", "[provision] sql: ".. sql .. "\n"); + freeswitch.consoleLog("NOTICE", "[provision] SQL: ".. sql .. "; params: " .. json.encode(params) .. "\n"); end - dbh:query(sql, function(row) + dbh:query(sql, params, function(row) --get device uuid device_uuid = row.device_uuid; freeswitch.consoleLog("NOTICE", "[provision] device_uuid: ".. device_uuid .. "\n"); @@ -109,14 +116,15 @@ --get the alternate device uuid using the device username and password authorized = 'false'; if (user_id ~= nil and password ~= nil and domain_uuid ~= nil) then - sql = [[SELECT * FROM v_devices ]]; - sql = sql .. [[WHERE device_username = ']]..user_id..[[' ]]; - sql = sql .. [[AND device_password = ']]..password..[[' ]] - sql = sql .. [[AND domain_uuid = ']]..domain_uuid..[[' ]]; + local sql = [[SELECT device_uuid FROM v_devices ]]; + sql = sql .. [[WHERE device_username = :user_id ]]; + sql = sql .. [[AND device_password = :password ]] + sql = sql .. [[AND domain_uuid = :domain_uuid ]]; + local params = {user_id = user_id, password = password, domain_uuid = domain_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("NOTICE", "[provision] sql: ".. sql .. "\n"); + freeswitch.consoleLog("NOTICE", "[provision] SQL: ".. sql .. "; params: " .. json.encode(params) .. "\n"); end - dbh:query(sql, function(row) + dbh:query(sql, params, function(row) --get the alternate device_uuid device_uuid_alternate = row.device_uuid; freeswitch.consoleLog("NOTICE", "[provision] alternate device_uuid: ".. device_uuid_alternate .. "\n"); @@ -132,13 +140,14 @@ --this device already has an alternate find the correct device_uuid and then override current one if (authorized == 'true' and action == "login" and device_uuid_alternate ~= nil and device_uuid ~= nil and domain_uuid ~= nil) then - sql = [[SELECT * FROM v_devices ]]; - sql = sql .. [[WHERE device_uuid_alternate = ']]..device_uuid..[[' ]]; - sql = sql .. [[AND domain_uuid = ']]..domain_uuid..[[' ]]; + local sql = [[SELECT * FROM v_devices ]]; + sql = sql .. [[WHERE device_uuid_alternate = :device_uuid ]]; + sql = sql .. [[AND domain_uuid = :domain_uuid ]]; + local params = {device_uuid = device_uuid, domain_uuid = domain_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("NOTICE", "[provision] sql: ".. sql .. "\n"); + freeswitch.consoleLog("NOTICE", "[provision] SQL: ".. sql .. "; params: " .. json.encode(params) .. "\n"); end - dbh:query(sql, function(row) + dbh:query(sql, params, function(row) if (row.device_uuid_alternate ~= nil) then device_uuid = row.device_uuid; end @@ -147,21 +156,23 @@ --remove the alternate device from another device so that it can be added to this device if (authorized == 'true' and action == "login" and device_uuid_alternate ~= nil and domain_uuid ~= nil) then - sql = [[SELECT * FROM v_device_lines ]]; - sql = sql .. [[WHERE device_uuid = ']]..device_uuid_alternate..[[' ]]; - sql = sql .. [[AND domain_uuid = ']]..domain_uuid..[[' ]]; + local sql = [[SELECT * FROM v_device_lines ]]; + sql = sql .. [[WHERE device_uuid = :device_uuid ]]; + sql = sql .. [[AND domain_uuid = :domain_uuid ]]; + local params = {device_uuid = device_uuid_alternate, domain_uuid = domain_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("NOTICE", "[provision] sql: ".. sql .. "\n"); + freeswitch.consoleLog("NOTICE", "[provision] SQL: ".. sql .. "; params: " .. json.encode(params) .. "\n"); end - dbh:query(sql, function(row) + dbh:query(sql, params, function(row) --remove the previous alternate device uuid - sql = [[UPDATE v_devices SET device_uuid_alternate = null ]]; - sql = sql .. [[WHERE device_uuid_alternate = ']]..device_uuid_alternate..[[' ]]; - sql = sql .. [[AND domain_uuid = ']]..domain_uuid..[[' ]]; + local sql = [[UPDATE v_devices SET device_uuid_alternate = null ]]; + sql = sql .. [[WHERE device_uuid_alternate = :device_uuid_alternate ]]; + sql = sql .. [[AND domain_uuid = :domain_uuid ]]; + local params = {device_uuid_alternate = device_uuid_alternate, domain_uuid = domain_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("NOTICE", "[provision] sql: ".. sql .. "\n"); + freeswitch.consoleLog("NOTICE", "[provision] SQL: ".. sql .. "; params: " .. json.encode(params) .. "\n"); end - dbh:query(sql); + dbh:query(sql, params); --send a sync command to the previous device --create the event notify object local event = freeswitch.Event('NOTIFY'); @@ -183,26 +194,29 @@ --send a hangup session:hangup(); --add the new alternate - sql = [[UPDATE v_devices SET device_uuid_alternate = ']]..device_uuid_alternate..[[']]; - sql = sql .. [[WHERE device_uuid = ']]..device_uuid..[[' ]]; - sql = sql .. [[AND domain_uuid = ']]..domain_uuid..[[' ]]; + local sql = [[UPDATE v_devices SET device_uuid_alternate = :device_uuid_alternate ]]; + sql = sql .. [[WHERE device_uuid = :device_uuid ]]; + sql = sql .. [[AND domain_uuid = :domain_uuid ]]; + local params = {device_uuid_alternate = device_uuid_alternate, + device_uuid = device_uuid, domain_uuid = domain_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("NOTICE", "[provision] sql: ".. sql .. "\n"); + freeswitch.consoleLog("NOTICE", "[provision] SQL: ".. sql .. "; params: " .. json.encode(params) .. "\n"); end - dbh:query(sql); + dbh:query(sql, params); end end --remove the override to the device uuid (logout) if (authorized == 'true' and action == "logout") then if (device_uuid_alternate ~= nil and device_uuid ~= nil and domain_uuid ~= nil) then - sql = [[UPDATE v_devices SET device_uuid_alternate = null ]]; - sql = sql .. [[WHERE device_uuid_alternate = ']]..device_uuid..[[' ]]; - sql = sql .. [[AND domain_uuid = ']]..domain_uuid..[[' ]]; + local sql = [[UPDATE v_devices SET device_uuid_alternate = null ]]; + sql = sql .. [[WHERE device_uuid_alternate = :device_uuid ]]; + sql = sql .. [[AND domain_uuid = :domain_uuid ]]; + local params = {device_uuid = device_uuid, domain_uuid = domain_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("NOTICE", "[provision] sql: ".. sql .. "\n"); + freeswitch.consoleLog("NOTICE", "[provision] sql: ".. sql .. "; params: " .. json.encode(params) .. "\n"); end - dbh:query(sql); + dbh:query(sql, params); end end diff --git a/resources/install/scripts/app/ring_groups/index.lua b/resources/install/scripts/app/ring_groups/index.lua index 86f06c43a0..1a6d7204f3 100644 --- a/resources/install/scripts/app/ring_groups/index.lua +++ b/resources/install/scripts/app/ring_groups/index.lua @@ -30,8 +30,14 @@ local log = require "resources.functions.log".ring_group --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); + +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end --include functions require "resources.functions.trim"; @@ -104,8 +110,9 @@ local log = require "resources.functions.log".ring_group ring_group_forward_enabled = ""; ring_group_forward_destination = ""; sql = "SELECT * FROM v_ring_groups "; - sql = sql .. "where ring_group_uuid = '"..ring_group_uuid.."' "; - status = dbh:query(sql, function(row) + sql = sql .. "where ring_group_uuid = :ring_group_uuid "; + local params = {ring_group_uuid = ring_group_uuid}; + status = dbh:query(sql, params, function(row) domain_uuid = row["domain_uuid"]; ring_group_name = row["ring_group_name"]; ring_group_extension = row["ring_group_extension"]; @@ -202,19 +209,20 @@ local log = require "resources.functions.log".ring_group session:execute("transfer", ring_group_forward_destination.." XML "..context); else --get the strategy of the ring group, if random, we use random() to order the destinations - sql = [[ - SELECT - r.ring_group_strategy - FROM - v_ring_groups as r - WHERE - ring_group_uuid = ']]..ring_group_uuid..[[' - AND r.domain_uuid = ']]..domain_uuid..[[' - AND r.ring_group_enabled = 'true' - ]]; + local sql = [[ + SELECT + r.ring_group_strategy + FROM + v_ring_groups as r + WHERE + ring_group_uuid = :ring_group_uuid + AND r.domain_uuid = :domain_uuid + AND r.ring_group_enabled = 'true' + ]]; + local params = {ring_group_uuid = ring_group_uuid, domain_uuid = domain_uuid}; - assert(dbh:query(sql, function(row) + assert(dbh:query(sql, params, function(row) if (row.ring_group_strategy == "random") then if (database["type"] == "mysql") then sql_order = 'rand()' @@ -236,16 +244,18 @@ local log = require "resources.functions.log".ring_group v_ring_groups as r, v_ring_group_destinations as d WHERE d.ring_group_uuid = r.ring_group_uuid - AND d.ring_group_uuid = ']]..ring_group_uuid..[[' - AND r.domain_uuid = ']]..domain_uuid..[[' + AND d.ring_group_uuid = :ring_group_uuid + AND r.domain_uuid = :domain_uuid AND r.ring_group_enabled = 'true' ORDER BY ]]..sql_order..[[ - ]]; - --freeswitch.consoleLog("notice", "SQL:" .. sql .. "\n"); + ]]; + if debug["sql"] then + freeswitch.consoleLog("notice", "[ring group] SQL:" .. sql .. "; params:" .. json.encode(params) .. "\n"); + end destinations = {}; x = 1; - assert(dbh:query(sql, function(row) + assert(dbh:query(sql, params, function(row) if (row.destination_prompt == "1" or row.destination_prompt == "2") then prompt = "true"; end @@ -283,25 +293,29 @@ local log = require "resources.functions.log".ring_group --get the dialplan data and save it to a table if (external) then sql = [[select * from v_dialplans as d, v_dialplan_details as s - where (d.domain_uuid = ']] .. domain_uuid .. [[' or d.domain_uuid is null) - and d.app_uuid = '8c914ec3-9fc0-8ab5-4cda-6c9288bdc9a3' - and d.dialplan_enabled = 'true' - and d.dialplan_uuid = s.dialplan_uuid - order by - d.dialplan_order asc, - d.dialplan_name asc, - d.dialplan_uuid asc, - s.dialplan_detail_group asc, - CASE s.dialplan_detail_tag - WHEN 'condition' THEN 1 - WHEN 'action' THEN 2 - WHEN 'anti-action' THEN 3 - ELSE 100 END, - s.dialplan_detail_order asc ]] - --freeswitch.consoleLog("notice", "SQL:" .. sql .. "\n"); + where (d.domain_uuid = :domain_uuid or d.domain_uuid is null) + and d.app_uuid = '8c914ec3-9fc0-8ab5-4cda-6c9288bdc9a3' + and d.dialplan_enabled = 'true' + and d.dialplan_uuid = s.dialplan_uuid + order by + d.dialplan_order asc, + d.dialplan_name asc, + d.dialplan_uuid asc, + s.dialplan_detail_group asc, + CASE s.dialplan_detail_tag + WHEN 'condition' THEN 1 + WHEN 'action' THEN 2 + WHEN 'anti-action' THEN 3 + ELSE 100 END, + s.dialplan_detail_order asc + ]]; + params = {domain_uuid = domain_uuid}; + if debug["sql"] then + freeswitch.consoleLog("notice", "[ring group] SQL:" .. sql .. "; params:" .. json.encode(params) .. "\n"); + end dialplans = {}; x = 1; - assert(dbh:query(sql, function(row) + assert(dbh:query(sql, params, function(row) dialplans[x] = row; x = x + 1; end)); @@ -628,10 +642,13 @@ local log = require "resources.functions.log".ring_group --execute the time out action session:execute(ring_group_timeout_app, ring_group_timeout_data); else - sql = "SELECT ring_group_timeout_app, ring_group_timeout_data FROM v_ring_groups "; - sql = sql .. "where ring_group_uuid = '"..ring_group_uuid.."' "; - --freeswitch.consoleLog("notice", "[ring group] SQL:" .. sql .. "\n"); - dbh:query(sql, function(row) + local sql = "SELECT ring_group_timeout_app, ring_group_timeout_data FROM v_ring_groups "; + sql = sql .. "where ring_group_uuid = :ring_group_uuid"; + local params = {ring_group_uuid = ring_group_uuid}; + if debug["sql"] then + freeswitch.consoleLog("notice", "[ring group] SQL:" .. sql .. "; params:" .. json.encode(params) .. "\n"); + end + dbh:query(sql, params, function(row) --send missed call notification missed(); --execute the time out action diff --git a/resources/install/scripts/app/ring_groups/resources/scripts/destination.lua b/resources/install/scripts/app/ring_groups/resources/scripts/destination.lua index 1d63cfbe52..47cd1f3109 100644 --- a/resources/install/scripts/app/ring_groups/resources/scripts/destination.lua +++ b/resources/install/scripts/app/ring_groups/resources/scripts/destination.lua @@ -27,8 +27,14 @@ require "resources.functions.config"; --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); + +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end --set default variables sounds_dir = ""; @@ -105,17 +111,19 @@ freeswitch.consoleLog("NOTICE", "[ring_group] menu_selection: "..menu_selection.."\n"); if (menu_selection == "1") then --first, check to see if the destination is already in this ring group - sql = [[ + local sql = [[ SELECT COUNT(*) AS in_group FROM v_ring_group_destinations WHERE - domain_uuid = ']]..domain_uuid..[[' - AND ring_group_uuid = ']]..ring_group_uuid..[[' - AND destination_number = ']]..destination..[[' + domain_uuid = :domain_uuid + AND ring_group_uuid = :ring_group_uuid + AND destination_number = :destination ]]; - --freeswitch.consoleLog("NOTICE", "[ring_group] SQL "..sql.."\n"); + local params = {domain_uuid = domain_uuid, ring_group_uuid = ring_group_uuid, + destination = destination}; + --freeswitch.consoleLog("NOTICE", "[ring_group] SQL: " .. sql .. "; params: " .. json.encode(params) .. "\n"); - assert(dbh:query(sql, function(row) + assert(dbh:query(sql, params, function(row) if (row.in_group == "0") then sql = [[ INSERT INTO @@ -128,15 +136,26 @@ destination_timeout ) VALUES - ( ']]..ring_group_destination_uuid..[[', - ']]..domain_uuid..[[', - ']]..ring_group_uuid..[[', - ']]..destination..[[', - ]]..destination_delay..[[, - ]]..destination_timeout..[[ + ( :ring_group_destination_uuid, + :domain_uuid, + :ring_group_uuid, + :destination, + :destination_delay, + :destination_timeout )]]; - freeswitch.consoleLog("NOTICE", "[ring_group][destination] SQL "..sql.."\n"); - dbh:query(sql); + + params = { + ring_group_destination_uuid = ring_group_destination_uuid; + domain_uuid = domain_uuid; + ring_group_uuid = ring_group_uuid; + destination = destination; + destination_delay = destination_delay; + destination_timeout = destination_timeout; + + }; + + freeswitch.consoleLog("NOTICE", "[ring_group][destination] SQL: " .. sql .. "; params: " .. json.encode(params) .. "\n"); + dbh:query(sql, params); freeswitch.consoleLog("NOTICE", "[ring_group][destination] LOG IN\n"); session:streamFile("ivr/ivr-you_are_now_logged_in.wav"); @@ -147,16 +166,18 @@ end)); end if (menu_selection == "2") then - sql = [[ + local sql = [[ DELETE FROM v_ring_group_destinations WHERE - domain_uuid =']]..domain_uuid..[[' - AND ring_group_uuid=']]..ring_group_uuid..[[' - AND destination_number=']]..destination..[[' + domain_uuid =:domain_uuid + AND ring_group_uuid=:ring_group_uuid + AND destination_number=:destination ]]; - freeswitch.consoleLog("NOTICE", "[ring_group][destination] SQL "..sql.."\n"); - dbh:query(sql); + local params = {domain_uuid = domain_uuid, ring_group_uuid = ring_group_uuid, + destination = destination}; + freeswitch.consoleLog("NOTICE", "[ring_group][destination] SQL: " .. sql .. "; params: " .. json.encode(params) .. "\n"); + dbh:query(sql, params); freeswitch.consoleLog("NOTICE", "[ring_group][destination] LOG OUT\n"); session:streamFile("ivr/ivr-you_are_now_logged_out.wav"); diff --git a/resources/install/scripts/app/speed_dial/index.lua b/resources/install/scripts/app/speed_dial/index.lua new file mode 100644 index 0000000000..437345fabf --- /dev/null +++ b/resources/install/scripts/app/speed_dial/index.lua @@ -0,0 +1,98 @@ +-- FusionPBX +-- Version: MPL 1.1 + +-- The contents of this file are subject to the Mozilla Public License Version +-- 1.1 (the "License"); you may not use this file except in compliance with +-- the License. You may obtain a copy of the License at +-- http://www.mozilla.org/MPL/ + +-- Software distributed under the License is distributed on an "AS IS" basis, +-- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +-- for the specific language governing rights and limitations under the +-- License. + +-- The Original Code is FusionPBX + +-- The Initial Developer of the Original Code is +-- Mark J Crane +-- Portions created by the Initial Developer are Copyright (C) 2016 +-- the Initial Developer. All Rights Reserved. + +-- load config + require "resources.functions.config"; + +--set debug + debug["sql"] = true; + +--load libraries + local log = require "resources.functions.log"["app:dialplan:outbound:speed_dial"] + local Database = require "resources.functions.database"; + local cache = require "resources.functions.cache"; + local json = require "resources.functions.lunajson"; + +--get the variables + domain_name = session:getVariable("domain_name"); + domain_uuid = session:getVariable("domain_uuid"); + context = session:getVariable("context"); + +--get the argv values + destination = argv[2]; + +-- search in memcache first + local key = "app:dialplan:outbound:speed_dial:" .. destination .. "@" .. domain_name + local source = "memcache" + local value = cache.get(key) + +-- decode value from memcache + if value then + local t = json.decode(value) + if not (t and t.phone_number and t.context) then + log.warning("can not decode value from memcache: %s", value) + value = nil + else + value = t + end + end + +-- search in database + if not value then + -- set source flag + source = "database" + + -- connect to database + local dbh = Database.new('system'); + + -- search for the phone number in database using the speed dial + local sql = "SELECT phone_number " + sql = sql .. "FROM v_contact_phones " + sql = sql .. "WHERE phone_speed_dial = :phone_speed_dial " + sql = sql .. "AND domain_uuid = :domain_uuid " + + local params = {phone_speed_dial = destination, domain_uuid = domain_uuid}; + + if (debug["sql"]) then + log.noticef("SQL: %s; params: %s", sql, json.encode(params)); + end + + local phone_number = dbh:first_value(sql, params) + + -- release database connection + dbh:release() + + -- set the cache + if phone_number then + value = {context = context, phone_number = phone_number} + cache.set(key, json.encode(value), expire["speed_dial"]) + end + end + +-- transfer + if value then + --log the result + log.noticef("%s XML %s source: %s", destination, context, source) + + --transfer the call + session:transfer(value.phone_number, "XML", context); + else + log.warningf('can not find number: %s in domain: %s', destination, domain_name) + end diff --git a/resources/install/scripts/app/voicemail/index.lua b/resources/install/scripts/app/voicemail/index.lua index cd19648600..1bd08d2034 100644 --- a/resources/install/scripts/app/voicemail/index.lua +++ b/resources/install/scripts/app/voicemail/index.lua @@ -50,8 +50,13 @@ password_tries = 0; --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + Database = require "resources.functions.database"; + dbh = Database.new('system'); + +--include json library (as global object) + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end --set the api api = freeswitch.API(); @@ -69,6 +74,9 @@ destination_number = session:getVariable("destination_number"); caller_id_name = session:getVariable("caller_id_name"); caller_id_number = session:getVariable("caller_id_number"); + if (string.sub(caller_id_number, 1, 1) == "/") then + caller_id_number = string.sub(caller_id_number, 2, -1); + end voicemail_greeting_number = session:getVariable("voicemail_greeting_number"); skip_instructions = session:getVariable("skip_instructions"); skip_greeting = session:getVariable("skip_greeting"); @@ -101,12 +109,13 @@ if (domain_uuid == nil) then --get the domain_uuid using the domain name required for multi-tenant if (domain_name ~= nil) then - sql = "SELECT domain_uuid FROM v_domains "; - sql = sql .. "WHERE domain_name = '" .. domain_name .. "' "; + local sql = "SELECT domain_uuid FROM v_domains "; + sql = sql .. "WHERE domain_name = :domain_name "; + local params = {domain_name = domain_name}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(rows) + dbh:query(sql, params, function(rows) domain_uuid = rows["domain_uuid"]; end); end @@ -149,6 +158,17 @@ end end end + + if settings['voicemail'] then + if settings['voicemail']['voicemail_to_sms'] then + voicemail_to_sms = (settings['voicemail']['voicemail_to_sms']['boolean'] == 'true'); + end + if settings['voicemail']['voicemail_to_sms_did'] then + voicemail_to_sms_did = settings['voicemail']['voicemail_to_sms_did']['text']; + end + voicemail_to_sms_did = voicemail_to_sms_did or ''; + end + if (not temp_dir) or (#temp_dir == 0) then if (settings['server'] ~= nil) then if (settings['server']['temp'] ~= nil) then @@ -163,17 +183,19 @@ if (voicemail_id ~= nil) then if (session:ready()) then --get the information from the database - sql = [[SELECT * FROM v_voicemails - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND voicemail_id = ']] .. voicemail_id ..[[' + local sql = [[SELECT * FROM v_voicemails + WHERE domain_uuid = :domain_uuid + AND voicemail_id = :voicemail_id AND voicemail_enabled = 'true' ]]; + local params = {domain_uuid = domain_uuid, voicemail_id = voicemail_id}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(row) + dbh:query(sql, params, function(row) voicemail_uuid = string.lower(row["voicemail_uuid"]); voicemail_password = row["voicemail_password"]; greeting_id = row["greeting_id"]; + voicemail_alternate_greet_id = row["voicemail_alternate_greet_id"]; voicemail_mail_to = row["voicemail_mail_to"]; voicemail_attach_file = row["voicemail_attach_file"]; voicemail_local_after_email = row["voicemail_local_after_email"]; @@ -230,6 +252,7 @@ require "app.voicemail.resources.functions.listen_to_recording"; require "app.voicemail.resources.functions.message_waiting"; require "app.voicemail.resources.functions.send_email"; + require "app.voicemail.resources.functions.send_sms"; require "app.voicemail.resources.functions.delete_recording"; require "app.voicemail.resources.functions.message_saved"; require "app.voicemail.resources.functions.return_call"; @@ -253,11 +276,12 @@ debug["info"] = "true"; --get voicemail message details - sql = [[SELECT * FROM v_domains WHERE domain_name = ']] .. domain_name ..[[']] + local sql = [[SELECT * FROM v_domains WHERE domain_name = :domain_name]]; + local params = {domain_name = domain_name}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(row) + dbh:query(sql, params, function(row) domain_uuid = string.lower(row["domain_uuid"]); end); @@ -299,13 +323,14 @@ --check the voicemail quota if (vm_disk_quota) then --get voicemail message seconds - sql = [[SELECT coalesce(sum(message_length), 0) as message_sum FROM v_voicemail_messages - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND voicemail_uuid = ']] .. voicemail_uuid ..[[']] - if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); - end - status = dbh:query(sql, function(row) + local sql = [[SELECT coalesce(sum(message_length), 0) as message_sum FROM v_voicemail_messages + WHERE domain_uuid = :domain_uuid + AND voicemail_uuid = :voicemail_uuid]] + local params = {domain_uuid = domain_uuid, voicemail_uuid = voicemail_uuid}; + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); + end + dbh:query(sql, params, function(row) message_sum = row["message_sum"]; end); if (tonumber(vm_disk_quota) <= tonumber(message_sum)) then @@ -349,13 +374,14 @@ --get the voicemail destinations sql = [[select * from v_voicemail_destinations - where voicemail_uuid = ']]..voicemail_uuid..[[']] - --freeswitch.consoleLog("notice", "[voicemail][destinations] SQL:" .. sql .. "\n"); + where voicemail_uuid = :voicemail_uuid]] + params = {voicemail_uuid=voicemail_uuid}; + --freeswitch.consoleLog("notice", "[voicemail][destinations] SQL:" .. sql .. "; params:" .. json.encode(params) .. "\n"); destinations = {}; x = 1; table.insert(destinations, {domain_uuid=domain_uuid,voicemail_destination_uuid=voicemail_uuid,voicemail_uuid=voicemail_uuid,voicemail_uuid_copy=voicemail_uuid}); x = x + 1; - assert(dbh:query(sql, function(row) + assert(dbh:query(sql, params, function(row) destinations[x] = row; x = x + 1; end)); @@ -388,68 +414,90 @@ if (storage_type == "base64") then table.insert(sql, "message_base64, "); end + if (transcribe_enabled == "true") then + table.insert(sql, "message_transcription, "); + end table.insert(sql, "message_length "); --table.insert(sql, "message_status, "); --table.insert(sql, "message_priority, "); table.insert(sql, ") "); table.insert(sql, "VALUES "); table.insert(sql, "( "); - table.insert(sql, "'"..voicemail_message_uuid.."', "); - table.insert(sql, "'"..domain_uuid.."', "); - table.insert(sql, "'"..row.voicemail_uuid_copy.."', "); - table.insert(sql, "'"..start_epoch.."', "); - table.insert(sql, "'"..caller_id_name.."', "); - table.insert(sql, "'"..caller_id_number.."', "); + table.insert(sql, ":voicemail_message_uuid, "); + table.insert(sql, ":domain_uuid, "); + table.insert(sql, ":voicemail_uuid, "); + table.insert(sql, ":start_epoch, "); + table.insert(sql, ":caller_id_name, "); + table.insert(sql, ":caller_id_number, "); if (storage_type == "base64") then - table.insert(sql, "'"..message_base64.."', "); + table.insert(sql, ":message_base64, "); end - table.insert(sql, "'"..message_length.."' "); - --table.insert(sql, "'"..message_status.."', "); - --table.insert(sql, "'"..message_priority.."' "); + if (transcribe_enabled == "true") then + table.insert(sql, ":transcription, "); + end + table.insert(sql, ":message_length "); + --table.insert(sql, ":message_status, "); + --table.insert(sql, ":message_priority "); table.insert(sql, ") "); sql = table.concat(sql, "\n"); + local params = { + voicemail_message_uuid = voicemail_message_uuid; + domain_uuid = domain_uuid; + voicemail_uuid = row.voicemail_uuid_copy; + start_epoch = start_epoch; + caller_id_name = caller_id_name; + caller_id_number = caller_id_number; + message_base64 = message_base64; + transcription = transcription; + message_length = message_length; + --message_status = message_status; + --message_priority = message_priority; + }; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end if (storage_type == "base64") then local Database = require "resources.functions.database" local dbh = Database.new('system', 'base64'); - dbh:query(sql); + dbh:query(sql, params); dbh:release(); else - dbh:query(sql); + dbh:query(sql, params); end end - --get saved and new message counts + local params = {domain_uuid = domain_uuid, voicemail_uuid = row.voicemail_uuid_copy}; + + --get new message count sql = [[SELECT count(*) as new_messages FROM v_voicemail_messages - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND voicemail_uuid = ']] .. row.voicemail_uuid_copy ..[[' + WHERE domain_uuid = :domain_uuid + AND voicemail_uuid = :voicemail_uuid AND (message_status is null or message_status = '') ]]; - if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); - end - status = dbh:query(sql, function(result) + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); + end + dbh:query(sql, params, function(result) new_messages = result["new_messages"]; end); + + --get saved message count sql = [[SELECT count(*) as saved_messages FROM v_voicemail_messages - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND voicemail_uuid = ']] .. row.voicemail_uuid_copy ..[[' + WHERE domain_uuid = :domain_uuid + AND voicemail_uuid = :voicemail_uuid AND message_status = 'saved' ]]; - if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); - end - status = dbh:query(sql, function(result) + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); + end + dbh:query(sql, params, function(result) saved_messages = result["saved_messages"]; end); --get the voicemail_id - sql = [[SELECT voicemail_id FROM v_voicemails - WHERE voicemail_uuid = ']] .. row.voicemail_uuid_copy ..[[']]; - if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); - end - status = dbh:query(sql, function(result) + sql = [[SELECT voicemail_id FROM v_voicemails WHERE voicemail_uuid = :voicemail_uuid]]; + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); + end + dbh:query(sql, params, function(result) voicemail_id_copy = result["voicemail_id"]; end); @@ -473,6 +521,9 @@ --send the email with the voicemail recording attached if (tonumber(message_length) > 2) then send_email(voicemail_id_copy, voicemail_message_uuid); + if (voicemail_to_sms) then + send_sms(voicemail_id_copy, voicemail_message_uuid); + end end end --for diff --git a/resources/install/scripts/app/voicemail/resources/functions/change_password.lua b/resources/install/scripts/app/voicemail/resources/functions/change_password.lua index 711932681d..0b6bab9f0a 100644 --- a/resources/install/scripts/app/voicemail/resources/functions/change_password.lua +++ b/resources/install/scripts/app/voicemail/resources/functions/change_password.lua @@ -32,15 +32,17 @@ dtmf_digits = ''; password = macro(session, "password_new", 20, 5000, ''); --update the voicemail password - sql = [[UPDATE v_voicemails - set voicemail_password = ']] .. password ..[[' - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND voicemail_id = ']] .. voicemail_id ..[[' + local sql = [[UPDATE v_voicemails + set voicemail_password = :password + WHERE domain_uuid = :domain_uuid + AND voicemail_id = :voicemail_id AND voicemail_enabled = 'true' ]]; + local params = {password = password, domain_uuid = domain_uuid, + voicemail_id = voicemail_id}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - dbh:query(sql); + dbh:query(sql, params); --has been changed to dtmf_digits = ''; macro(session, "password_changed", 20, 3000, password); diff --git a/resources/install/scripts/app/voicemail/resources/functions/check_password.lua b/resources/install/scripts/app/voicemail/resources/functions/check_password.lua index 7763cfc2ba..be165d9462 100644 --- a/resources/install/scripts/app/voicemail/resources/functions/check_password.lua +++ b/resources/install/scripts/app/voicemail/resources/functions/check_password.lua @@ -44,14 +44,15 @@ --get the voicemail settings from the database if (voicemail_id) then if (session:ready()) then - sql = [[SELECT * FROM v_voicemails - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND voicemail_id = ']] .. voicemail_id ..[[' + local sql = [[SELECT * FROM v_voicemails + WHERE domain_uuid = :domain_uuid + AND voicemail_id = :voicemail_id AND voicemail_enabled = 'true' ]]; + local params = {domain_uuid = domain_uuid, voicemail_id = voicemail_id}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(row) + dbh:query(sql, params, function(row) voicemail_uuid = string.lower(row["voicemail_uuid"]); voicemail_password = row["voicemail_password"]; greeting_id = row["greeting_id"]; diff --git a/resources/install/scripts/app/voicemail/resources/functions/choose_greeting.lua b/resources/install/scripts/app/voicemail/resources/functions/choose_greeting.lua index 40fea45077..09e56e11f1 100644 --- a/resources/install/scripts/app/voicemail/resources/functions/choose_greeting.lua +++ b/resources/install/scripts/app/voicemail/resources/functions/choose_greeting.lua @@ -40,11 +40,13 @@ --check to see if the greeting file exists if (storage_type == "base64" or storage_type == "http_cache") then greeting_invalid = true; - sql = [[SELECT * FROM v_voicemail_greetings - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND voicemail_id = ']].. voicemail_id.. [[' - AND greeting_id = ']].. greeting_id.. [[' ]]; - status = dbh:query(sql, function(row) + local sql = [[SELECT * FROM v_voicemail_greetings + WHERE domain_uuid = :domain_uuid + AND voicemail_id = :voicemail_id + AND greeting_id = :greeting_id]]; + local params = {domain_uuid = domain_uuid, voicemail_id = voicemail_id, + greeting_id = greeting_id}; + dbh:query(sql, params, function(row) --greeting found greeting_invalid = false; end); @@ -74,31 +76,39 @@ --valid greeting_id update the database if (session:ready()) then + local params = {domain_uuid = domain_uuid, voicemail_uuid = voicemail_uuid}; + local sql = "UPDATE v_voicemails SET " if (greeting_id == "0") then - sql = [[UPDATE v_voicemails SET greeting_id = null ]]; + sql = sql .. "greeting_id = null "; else - sql = [[UPDATE v_voicemails SET greeting_id = ']]..greeting_id..[[' ]]; + sql = sql .. "greeting_id = :greeting_id "; + params.greeting_id = greeting_id; end - sql = sql ..[[WHERE domain_uuid = ']] .. domain_uuid ..[[' ]] - sql = sql ..[[AND voicemail_uuid = ']] .. voicemail_uuid ..[[' ]]; + sql = sql .. "WHERE domain_uuid = :domain_uuid "; + sql = sql .. "AND voicemail_uuid = :voicemail_uuid "; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - dbh:query(sql); + dbh:query(sql, params); end --get the greeting from the database if (storage_type == "base64") then local dbh = Database.new('system', 'base64/read') - - sql = [[SELECT * FROM v_voicemail_greetings - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND voicemail_id = ']].. voicemail_id.. [[' - AND greeting_id = ']].. greeting_id.. [[' ]]; + local sql = [[SELECT greeting_base64 + FROM v_voicemail_greetings + WHERE domain_uuid = :domain_uuid + AND voicemail_id = :voicemail_id + AND greeting_id = :greeting_id]]; + local params = { + domain_uuid = domain_uuid; + voicemail_id = voicemail_id; + greeting_id = greeting_id; + }; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(row) + dbh:query(sql, params, function(row) --set the voicemail message path greeting_location = voicemail_dir.."/"..voicemail_id.."/greeting_"..greeting_id..".wav"; --vm_message_ext; diff --git a/resources/install/scripts/app/voicemail/resources/functions/delete_recording.lua b/resources/install/scripts/app/voicemail/resources/functions/delete_recording.lua index db4bd10135..da50805eb3 100644 --- a/resources/install/scripts/app/voicemail/resources/functions/delete_recording.lua +++ b/resources/install/scripts/app/voicemail/resources/functions/delete_recording.lua @@ -32,11 +32,13 @@ macro(session, "message_deleted", 1, 100, ''); end end + --get the voicemail_uuid - sql = [[SELECT * FROM v_voicemails - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND voicemail_id = ']] .. voicemail_id ..[[']]; - status = dbh:query(sql, function(row) + local sql = [[SELECT * FROM v_voicemails + WHERE domain_uuid = :domain_uuid + AND voicemail_id = :voicemail_id]]; + local params = {domain_uuid = domain_uuid, voicemail_id = voicemail_id}; + dbh:query(sql, params, function(row) db_voicemail_uuid = row["voicemail_uuid"]; end); --flush dtmf digits from the input buffer @@ -46,13 +48,14 @@ os.remove(voicemail_dir.."/"..voicemail_id.."/msg_"..uuid.."."..vm_message_ext); --delete from the database sql = [[DELETE FROM v_voicemail_messages - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND voicemail_uuid = ']] .. db_voicemail_uuid ..[[' - AND voicemail_message_uuid = ']] .. uuid ..[[']]; + WHERE domain_uuid = :domain_uuid + AND voicemail_uuid = :voicemail_uuid + AND voicemail_message_uuid = :uuid]]; + params = {domain_uuid = domain_uuid, voicemail_uuid = db_voicemail_uuid, uuid = uuid}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - dbh:query(sql); + dbh:query(sql, params); --log to console if (debug["info"]) then freeswitch.consoleLog("notice", "[voicemail][deleted] message: " .. uuid .. "\n"); diff --git a/resources/install/scripts/app/voicemail/resources/functions/forward_add_intro.lua b/resources/install/scripts/app/voicemail/resources/functions/forward_add_intro.lua index d05ba0f027..ccd2b155e4 100644 --- a/resources/install/scripts/app/voicemail/resources/functions/forward_add_intro.lua +++ b/resources/install/scripts/app/voicemail/resources/functions/forward_add_intro.lua @@ -95,21 +95,25 @@ --save the merged file into the database as base64 if (storage_type == "base64") then + local file = require "resources.functions.file" + --get the content of the file - local f = io.open(message_intro_location, "rb"); - local file_content = f:read("*all"); - f:close(); + local file_content = assert(file.read_base64(message_intro_location)); --save the merged file as base64 - local sql = {} - sql = [[UPDATE SET v_voicemail_messages - SET message_intro_base64 = ']].. base64.encode(file_content) ..[[' - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND voicemail_message_uuid = ']].. uuid.. [[' ]]; - sql = table.concat(sql, "\n"); + local sql = [[UPDATE SET v_voicemail_messages + SET message_intro_base64 = :file_content + WHERE domain_uuid = :domain_uuid + AND voicemail_message_uuid = :uuid]]; + local params = {file_content = file_content, domain_uuid = domain_uuid, uuid = uuid}; + if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params: " .. json.encode(params) .. "\n"); end + + local dbh = Database.new('system', 'base64') + dbh:query(sql, params) + dbh:release() end end diff --git a/resources/install/scripts/app/voicemail/resources/functions/forward_to_extension.lua b/resources/install/scripts/app/voicemail/resources/functions/forward_to_extension.lua index e03f36cb49..37aa4e7fb3 100644 --- a/resources/install/scripts/app/voicemail/resources/functions/forward_to_extension.lua +++ b/resources/install/scripts/app/voicemail/resources/functions/forward_to_extension.lua @@ -52,14 +52,15 @@ --get voicemail message details if (session:ready()) then - sql = [[SELECT * FROM v_voicemail_messages - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND voicemail_uuid = ']] .. voicemail_uuid ..[[' - AND voicemail_message_uuid = ']] .. uuid ..[[']] + local sql = [[SELECT * FROM v_voicemail_messages + WHERE domain_uuid = :domain_uuid + AND voicemail_uuid = :voicemail_uuid + AND voicemail_message_uuid = :uuid]] + local params = {domain_uuid = domain_uuid, voicemail_uuid = voicemail_uuid, uuid = uuid}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(row) + dbh:query(sql, params, function(row) --get the values from the database created_epoch = row["created_epoch"]; caller_id_name = row["caller_id_name"]; @@ -72,14 +73,15 @@ end --get the voicemail settings - sql = [[SELECT * FROM v_voicemails - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND voicemail_id = ']] .. forward_voicemail_id ..[[' + local sql = [[SELECT * FROM v_voicemails + WHERE domain_uuid = :domain_uuid + AND voicemail_id = :voicemail_id AND voicemail_enabled = 'true' ]]; + local params = {domain_uuid = domain_uuid, voicemail_id = forward_voicemail_id}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(row) + dbh:query(sql, params, function(row) forward_voicemail_uuid = string.lower(row["voicemail_uuid"]); forward_voicemail_mail_to = row["voicemail_mail_to"]; forward_voicemail_attach_file = row["voicemail_attach_file"]; @@ -108,33 +110,41 @@ table.insert(sql, ") "); table.insert(sql, "VALUES "); table.insert(sql, "( "); - table.insert(sql, "'".. voicemail_message_uuid .."', "); - table.insert(sql, "'".. domain_uuid .."', "); - table.insert(sql, "'".. forward_voicemail_uuid .."', "); + table.insert(sql, ":voicemail_message_uuid, "); + table.insert(sql, ":domain_uuid, "); + table.insert(sql, ":forward_voicemail_uuid, "); if (storage_type == "base64") then - table.insert(sql, "'".. message_base64 .."', "); + table.insert(sql, ":message_base64, "); end - table.insert(sql, "'".. created_epoch .."', "); - table.insert(sql, "'".. caller_id_name .."', "); - table.insert(sql, "'".. caller_id_number .."', "); - table.insert(sql, "'".. message_length .."' "); - --table.insert(sql, "'".. message_status .."', "); - --table.insert(sql, "'".. message_priority .."' "); + table.insert(sql, ":created_epoch, "); + table.insert(sql, ":caller_id_name, "); + table.insert(sql, ":caller_id_number, "); + table.insert(sql, ":message_length "); + --table.insert(sql, ":message_status, "); + --table.insert(sql, ":message_priority "); table.insert(sql, ") "); sql = table.concat(sql, "\n"); + local params = { + voicemail_message_uuid = voicemail_message_uuid; + domain_uuid = domain_uuid; + forward_voicemail_uuid = forward_voicemail_uuid; + message_base64 = message_base64; + created_epoch = created_epoch; + caller_id_name = caller_id_name; + caller_id_number = caller_id_number; + message_length = message_length; + -- message_status = message_status; + -- message_priority = message_priority; + }; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end if (storage_type == "base64") then - array = explode("://", database["system"]); - local luasql = require "luasql.postgres"; - local env = assert (luasql.postgres()); - local dbh = env:connect(array[2]); - res, serr = dbh:execute(sql); - dbh:close(); - env:close(); + local dbh = Database.new('system', 'base64') + dbh:query(sql, params); + dbh:release(); else - dbh:query(sql); + dbh:query(sql, params); end --offer to add an intro to the forwarded message diff --git a/resources/install/scripts/app/voicemail/resources/functions/listen_to_recording.lua b/resources/install/scripts/app/voicemail/resources/functions/listen_to_recording.lua index 537be7c42d..5f66629507 100644 --- a/resources/install/scripts/app/voicemail/resources/functions/listen_to_recording.lua +++ b/resources/install/scripts/app/voicemail/resources/functions/listen_to_recording.lua @@ -23,8 +23,6 @@ -- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -- POSSIBILITY OF SUCH DAMAGE. - local Database = require "resources.functions.database" - --define function to listen to the recording function listen_to_recording (message_number, uuid, created_epoch, caller_id_name, caller_id_number) @@ -76,13 +74,14 @@ if (storage_type == "base64") then local dbh = Database.new('system', 'base64/read') - sql = [[SELECT * FROM v_voicemail_messages - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND voicemail_message_uuid = ']].. uuid.. [[' ]]; + local sql = [[SELECT * FROM v_voicemail_messages + WHERE domain_uuid = :domain_uuid + AND voicemail_message_uuid = :uuid]]; + local params = {domain_uuid = domain_uuid, uuid = uuid}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[ivr_menu] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(row) + dbh:query(sql, params, function(row) --set the voicemail message path mkdir(voicemail_dir.."/"..voicemail_id); message_intro_location = voicemail_dir.."/"..voicemail_id.."/intro_"..uuid.."."..vm_message_ext; diff --git a/resources/install/scripts/app/voicemail/resources/functions/macro.lua b/resources/install/scripts/app/voicemail/resources/functions/macro.lua index e76090c9ea..2ab2b65d00 100644 --- a/resources/install/scripts/app/voicemail/resources/functions/macro.lua +++ b/resources/install/scripts/app/voicemail/resources/functions/macro.lua @@ -1,5 +1,5 @@ -- Part of FusionPBX --- Copyright (C) 2013-2016 Mark J Crane +-- Copyright (C) 2013 - 2016 Mark J Crane -- All rights reserved. -- -- Redistribution and use in source and binary forms, with or without diff --git a/resources/install/scripts/app/voicemail/resources/functions/main_menu.lua b/resources/install/scripts/app/voicemail/resources/functions/main_menu.lua index f6ed58221c..8b5a40b1c6 100644 --- a/resources/install/scripts/app/voicemail/resources/functions/main_menu.lua +++ b/resources/install/scripts/app/voicemail/resources/functions/main_menu.lua @@ -32,14 +32,15 @@ session:flushDigits(); --new voicemail count if (session:ready()) then - sql = [[SELECT count(*) as new_messages FROM v_voicemail_messages - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND voicemail_uuid = ']] .. voicemail_uuid ..[[' + local sql = [[SELECT count(*) as new_messages FROM v_voicemail_messages + WHERE domain_uuid = :domain_uuid + AND voicemail_uuid = :voicemail_uuid AND (message_status is null or message_status = '') ]]; - if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); - end - status = dbh:query(sql, function(row) + local params = {domain_uuid = domain_uuid, voicemail_uuid = voicemail_uuid}; + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); + end + dbh:query(sql, params, function(row) new_messages = row["new_messages"]; end); dtmf_digits = macro(session, "new_messages", 1, 100, new_messages); @@ -48,32 +49,34 @@ if (session:ready()) then if (string.len(dtmf_digits) == 0) then sql = [[SELECT count(*) as saved_messages FROM v_voicemail_messages - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND voicemail_uuid = ']] .. voicemail_uuid ..[[' + WHERE domain_uuid = :domain_uuid + AND voicemail_uuid = :voicemail_uuid AND message_status = 'saved' ]]; - if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); - end - status = dbh:query(sql, function(row) + local params = {domain_uuid = domain_uuid, voicemail_uuid = voicemail_uuid}; + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); + end + dbh:query(sql, params, function(row) saved_messages = row["saved_messages"]; end); dtmf_digits = macro(session, "saved_messages", 1, 100, saved_messages); end end - --get domain timezone - if (session:ready()) then - if (string.len(dtmf_digits) == 0) then - sql = [[SELECT domain_setting_value as current_time_zone FROM v_domain_settings - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND domain_setting_subcategory='time_zone' ]]; - if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); - end - status = dbh:query(sql, function(row) - current_time_zone = row["current_time_zone"]; - end); - end - end + --get domain timezone + if (session:ready()) then + if (string.len(dtmf_digits) == 0) then + local sql = [[SELECT domain_setting_value as current_time_zone FROM v_domain_settings + WHERE domain_uuid = :domain_uuid + AND domain_setting_subcategory='time_zone' ]]; + local params = {domain_uuid = domain_uuid}; + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); + end + dbh:query(sql, params, function(row) + current_time_zone = row["current_time_zone"]; + end); + end + end --to listen to new message if (session:ready() and new_messages ~= '0') then if (string.len(dtmf_digits) == 0) then diff --git a/resources/install/scripts/app/voicemail/resources/functions/menu_messages.lua b/resources/install/scripts/app/voicemail/resources/functions/menu_messages.lua index a1555d2b69..ae9380b9b3 100644 --- a/resources/install/scripts/app/voicemail/resources/functions/menu_messages.lua +++ b/resources/install/scripts/app/voicemail/resources/functions/menu_messages.lua @@ -41,19 +41,21 @@ --message_status new,saved if (session:ready()) then if (voicemail_id ~= nil) then - sql = [[SELECT voicemail_message_uuid, created_epoch, caller_id_name, caller_id_number FROM v_voicemail_messages - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND voicemail_uuid = ']] .. voicemail_uuid ..[[']] + local sql = [[SELECT voicemail_message_uuid, created_epoch, caller_id_name, caller_id_number + FROM v_voicemail_messages + WHERE domain_uuid = :domain_uuid + AND voicemail_uuid = :voicemail_uuid ]] if (message_status == "new") then sql = sql .. [[AND (message_status is null or message_status = '') ]]; elseif (message_status == "saved") then sql = sql .. [[AND message_status = 'saved' ]]; end sql = sql .. [[ORDER BY created_epoch desc;]]; + local params = {domain_uuid = domain_uuid, voicemail_uuid = voicemail_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(row) + dbh:query(sql, params, function(row) --get the values from the database --row["voicemail_message_uuid"]; --row["created_epoch"]; diff --git a/resources/install/scripts/app/voicemail/resources/functions/message_count.lua b/resources/install/scripts/app/voicemail/resources/functions/message_count.lua index 3bad00a8c2..8165587183 100644 --- a/resources/install/scripts/app/voicemail/resources/functions/message_count.lua +++ b/resources/install/scripts/app/voicemail/resources/functions/message_count.lua @@ -5,13 +5,13 @@ local log = require "resources.functions.log"["voicemail-count"] local message_count_by_uuid_sql = [[SELECT ( SELECT count(*) FROM v_voicemail_messages - WHERE voicemail_uuid = '%s' + WHERE voicemail_uuid = :voicemail_uuid AND (message_status is null or message_status = '') ) as new_messages, ( SELECT count(*) FROM v_voicemail_messages - WHERE voicemail_uuid = '%s' + WHERE voicemail_uuid = :voicemail_uuid AND message_status = 'saved' ) as saved_messages ]] @@ -19,15 +19,13 @@ local message_count_by_uuid_sql = [[SELECT function message_count_by_uuid(voicemail_uuid) local new_messages, saved_messages = "0", "0" - local sql = string.format(message_count_by_uuid_sql, - voicemail_uuid, voicemail_uuid - ) + local params = {voicemail_uuid = voicemail_uuid}; if debug["sql"] then - log.noticef("SQL: %s", sql) + log.noticef("SQL: %s; params: %s", message_count_by_uuid_sql, json.encode(params)) end - dbh:query(sql, function(row) + dbh:query(message_count_by_uuid_sql, params, function(row) new_messages, saved_messages = row.new_messages, row.saved_messages end) @@ -42,14 +40,14 @@ local message_count_by_id_sql = [[SELECT ( SELECT count(*) FROM v_voicemail_messages as m inner join v_voicemails as v on v.voicemail_uuid = m.voicemail_uuid - WHERE v.voicemail_id = '%s' AND v.domain_uuid = '%s' + WHERE v.voicemail_id = :voicemail_id AND v.domain_uuid = :domain_uuid AND (m.message_status is null or m.message_status = '') ) as new_messages, ( SELECT count(*) FROM v_voicemail_messages as m inner join v_voicemails as v on v.voicemail_uuid = m.voicemail_uuid - WHERE v.voicemail_id = '%s' AND v.domain_uuid = '%s' + WHERE v.voicemail_id = :voicemail_id AND v.domain_uuid = :domain_uuid AND m.message_status = 'saved' ) as saved_messages ]] @@ -57,15 +55,13 @@ local message_count_by_id_sql = [[SELECT function message_count_by_id(voicemail_id, domain_uuid) local new_messages, saved_messages = "0", "0" - local sql = string.format(message_count_by_id_sql, - voicemail_id, domain_uuid, voicemail_id, domain_uuid - ) + local params = {voicemail_id = voicemail_id, domain_uuid = domain_uuid}; if debug["sql"] then - log.noticef("SQL: %s", sql) + log.noticef("SQL: %s; params: %s", message_count_by_id_sql, json.encode(params)) end - dbh:query(sql, function(row) + dbh:query(message_count_by_id_sql, params, function(row) new_messages, saved_messages = row.new_messages, row.saved_messages end) diff --git a/resources/install/scripts/app/voicemail/resources/functions/message_saved.lua b/resources/install/scripts/app/voicemail/resources/functions/message_saved.lua index 2604684b29..15bec62635 100644 --- a/resources/install/scripts/app/voicemail/resources/functions/message_saved.lua +++ b/resources/install/scripts/app/voicemail/resources/functions/message_saved.lua @@ -30,21 +30,23 @@ --flush dtmf digits from the input buffer session:flushDigits(); --get the voicemail_uuid - sql = [[SELECT * FROM v_voicemails - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND voicemail_id = ']] .. voicemail_id ..[[']]; - status = dbh:query(sql, function(row) + local sql = [[SELECT * FROM v_voicemails + WHERE domain_uuid = :domain_uuid + AND voicemail_id = :voicemail_id]]; + local params = {domain_uuid = domain_uuid, voicemail_id = voicemail_id}; + dbh:query(sql, params, function(row) db_voicemail_uuid = row["voicemail_uuid"]; end); --delete from the database sql = [[UPDATE v_voicemail_messages SET message_status = 'saved' - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND voicemail_uuid = ']] .. db_voicemail_uuid ..[[' - AND voicemail_message_uuid = ']] .. uuid ..[[']]; + WHERE domain_uuid = :domain_uuid + AND voicemail_uuid = :voicemail_uuid + AND voicemail_message_uuid = :uuid]]; + params = {domain_uuid = domain_uuid, voicemail_uuid = db_voicemail_uuid, uuid = uuid}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - dbh:query(sql); + dbh:query(sql, params); --log to console if (debug["info"]) then freeswitch.consoleLog("notice", "[voicemail][saved] id: " .. voicemail_id .. " message: "..uuid.."\n"); diff --git a/resources/install/scripts/app/voicemail/resources/functions/message_waiting.lua b/resources/install/scripts/app/voicemail/resources/functions/message_waiting.lua index 76ff31fce6..59a1f05ec7 100644 --- a/resources/install/scripts/app/voicemail/resources/functions/message_waiting.lua +++ b/resources/install/scripts/app/voicemail/resources/functions/message_waiting.lua @@ -34,16 +34,18 @@ --get the voicemail id and all related mwi accounts local sql = [[SELECT extension, number_alias from v_extensions - WHERE domain_uuid = ']] .. domain_uuid ..[[' + WHERE domain_uuid = :domain_uuid AND ( - mwi_account = ']]..voicemail_id..[[' - or mwi_account = ']]..voicemail_id..[[@]]..domain_name..[[' - or number_alias = ']]..voicemail_id..[[' - )]]; + mwi_account = :voicemail_id + or mwi_account = :mwi_account + or number_alias = :voicemail_id + )]]; + local params = {domain_uuid = domain_uuid, voicemail_id = voicemail_id, + mwi_account = voicemail_id .. "@" .. domain_name}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - dbh:query(sql, function(row) + dbh:query(sql, params, function(row) table.insert(accounts, row["extension"]); end); diff --git a/resources/install/scripts/app/voicemail/resources/functions/play_greeting.lua b/resources/install/scripts/app/voicemail/resources/functions/play_greeting.lua index 68d31d77e8..900f8629a7 100644 --- a/resources/install/scripts/app/voicemail/resources/functions/play_greeting.lua +++ b/resources/install/scripts/app/voicemail/resources/functions/play_greeting.lua @@ -51,15 +51,17 @@ if (storage_type == "base64") then local dbh = Database.new('system', 'base64/read') - sql = [[SELECT * FROM v_voicemail_greetings - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND voicemail_id = ']].. voicemail_id.. [[' - AND greeting_id = ']].. greeting_id.. [[' ]]; + local sql = [[SELECT * FROM v_voicemail_greetings + WHERE domain_uuid = :domain_uuid + AND voicemail_id = :voicemail_id + AND greeting_id = :greeting_id ]]; + local params = {domain_uuid = domain_uuid, voicemail_id = voicemail_id, + greeting_id = greeting_id}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end local saved - status = dbh:query(sql, function(row) + dbh:query(sql, params, function(row) --set the voicemail message path mkdir(voicemail_dir.."/"..voicemail_id); greeting_location = voicemail_dir.."/"..voicemail_id.."/greeting_"..greeting_id..".wav"; --vm_message_ext; @@ -104,4 +106,4 @@ end end end -end + end diff --git a/resources/install/scripts/app/voicemail/resources/functions/record_menu.lua b/resources/install/scripts/app/voicemail/resources/functions/record_menu.lua index 5afed16a4c..86f0a01759 100644 --- a/resources/install/scripts/app/voicemail/resources/functions/record_menu.lua +++ b/resources/install/scripts/app/voicemail/resources/functions/record_menu.lua @@ -90,12 +90,14 @@ end --delete the previous recording - sql = "delete from v_voicemail_greetings "; - sql = sql .. "where domain_uuid = '".. domain_uuid .. "' "; - sql = sql .. "and voicemail_id = '".. voicemail_id .."' "; - sql = sql .. "and greeting_id = '".. greeting_id .."' "; + local sql = "delete from v_voicemail_greetings "; + sql = sql .. "where domain_uuid = :domain_uuid "; + sql = sql .. "and voicemail_id = :voicemail_id "; + sql = sql .. "and greeting_id = :greeting_id "; + local params = {domain_uuid = domain_uuid, + voicemail_id = voicemail_id, greeting_id = greeting_id}; --freeswitch.consoleLog("notice", "[SQL] DELETING: " .. greeting_id .. "\n"); - dbh:query(sql); + dbh:query(sql, params); --get a new uuid voicemail_greeting_uuid = api:execute("create_uuid"); @@ -116,38 +118,48 @@ table.insert(array, ") "); table.insert(array, "VALUES "); table.insert(array, "( "); - table.insert(array, "'"..voicemail_greeting_uuid.."', "); - table.insert(array, "'"..domain_uuid.."', "); - table.insert(array, "'"..voicemail_id.."', "); - table.insert(array, "'"..greeting_id.."', "); + table.insert(array, ":greeting_uuid, "); + table.insert(array, ":domain_uuid, "); + table.insert(array, ":voicemail_id, "); + table.insert(array, ":greeting_id, "); if (storage_type == "base64") then - table.insert(array, "'"..greeting_base64.."', "); + table.insert(array, ":greeting_base64, "); end - table.insert(array, "'Greeting "..greeting_id.."', "); - table.insert(array, "'greeting_"..greeting_id..".wav' "); + table.insert(array, ":greeting_name, "); + table.insert(array, ":greeting_filename "); table.insert(array, ") "); sql = table.concat(array, "\n"); + params = { + greeting_uuid = voicemail_greeting_uuid; + domain_uuid = domain_uuid; + voicemail_id = voicemail_id; + greeting_id = greeting_id; + greeting_base64 = greeting_base64; + greeting_name = "Greeting "..greeting_id; + greeting_filename = "greeting_"..greeting_id..".wav" + }; --freeswitch.consoleLog("notice", "[SQL] INSERTING: " .. greeting_id .. "\n"); if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end if (storage_type == "base64") then - local Database = require "resources.functions.database" local dbh = Database.new('system', 'base64'); - dbh:query(sql); + dbh:query(sql, params); dbh:release(); else - dbh:query(sql); + dbh:query(sql, params); end --use the new greeting - local array = {} - table.insert(array, "update v_voicemails "); - table.insert(array, "set greeting_id = '".. greeting_id .."' "); - table.insert(array, "where domain_uuid = '".. domain_uuid .."' "); - table.insert(array, "and voicemail_id = '".. voicemail_id .."' "); - sql = table.concat(array, "\n"); - dbh:query(sql); + sql = {} + table.insert(sql, "update v_voicemails "); + table.insert(sql, "set greeting_id = :greeting_id "); + table.insert(sql, "where domain_uuid = :domain_uuid "); + table.insert(sql, "and voicemail_id = :voicemail_id "); + sql = table.concat(sql, "\n"); + params = {domain_uuid = domain_uuid, greeting_id = greeting_id, + voicemail_id = voicemail_id}; + dbh:query(sql, params); advanced(); end diff --git a/resources/install/scripts/app/voicemail/resources/functions/record_message.lua b/resources/install/scripts/app/voicemail/resources/functions/record_message.lua index 22f9d860f4..85c1f0101e 100644 --- a/resources/install/scripts/app/voicemail/resources/functions/record_message.lua +++ b/resources/install/scripts/app/voicemail/resources/functions/record_message.lua @@ -26,6 +26,62 @@ --load libraries local Database = require "resources.functions.database" local Settings = require "resources.functions.lazy_settings" + local JSON = require "resources.functions.lunajson" + +--define uuid function + local random = math.random; + local function gen_uuid() + local template ='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'; + return string.gsub(template, '[xy]', function (c) + local v = (c == 'x') and random(0, 0xf) or random(8, 0xb); + return string.format('%x', v); + end) + end + + local function transcribe(file_path,settings) + --transcription variables + local transcribe_provider = settings:get('voicemail', 'transcribe_provider', 'text') or ''; + transcribe_language = settings:get('voicemail', 'transcribe_language', 'text') or 'en-US'; + + if (debug["info"]) then + freeswitch.consoleLog("notice", "[voicemail] transcribe_provider: " .. transcribe_provider .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] transcribe_language: " .. transcribe_language .. "\n"); + + end + + if (transcribe_provider == "microsoft") then + local api_key1 = settings:get('voicemail', 'microsoft_key1', 'text') or ''; + local api_key2 = settings:get('voicemail', 'microsoft_key2', 'text') or ''; + if (api_key1 ~= '' and api_key2 ~= '') then + access_token_cmd = "curl -X POST \"https://api.cognitive.microsoft.com/sts/v1.0/issueToken\" -H \"Content-type: application/x-www-form-urlencoded\" -H \"Content-Length: 0\" -H \"Ocp-Apim-Subscription-Key: "..api_key1.."\"" + local handle = io.popen(access_token_cmd); + local access_token_result = handle:read("*a"); + handle:close(); + if (debug["info"]) then + freeswitch.consoleLog("notice", "[voicemail] CMD: " .. access_token_cmd .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] RESULT: " .. access_token_result .. "\n"); + end + transcribe_cmd = "curl -X POST \"https://speech.platform.bing.com/recognize?scenarios=smd&appid=D4D52672-91D7-4C74-8AD8-42B1D98141A5&locale=en-US&device.os=Freeswitch&version=3.0&format=json&instanceid=" .. gen_uuid() .. "&requestid=" .. gen_uuid() .. "\" -H 'Authorization: Bearer " .. access_token_result .. "' -H 'Content-type: audio/wav; codec=\"audio/pcm\"; samplerate=8000; trustsourcerate=false' --data-binary @"..file_path + local handle = io.popen(transcribe_cmd); + local transcribe_result = handle:read("*a"); + handle:close(); + local transcribe_json = JSON.decode(transcribe_result); + if (debug["info"]) then + freeswitch.consoleLog("notice", "[voicemail] CMD: " .. transcribe_cmd .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] RESULT: " .. transcribe_result .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] TRANSCRIPTION: " .. transcribe_json["results"][1]["name"] .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] CONFIDENCE: " .. transcribe_json["results"][1]["confidence"] .. "\n"); + end + + transcription = transcribe_json["results"][1]["name"]; + transcription = transcription:gsub(".*<%/profanity>","..."); + confidence = transcribe_json["results"][1]["confidence"]; + end + return transcription; + end + + return ''; + end --save the recording function record_message() @@ -33,7 +89,12 @@ local settings = Settings.new(db, domain_name, domain_uuid) local max_len_seconds = settings:get('voicemail', 'message_max_length', 'numeric') or 300; - + transcribe_enabled = settings:get('voicemail', 'transcribe_enabled', 'boolean') or "false"; + + if (debug["info"]) then + freeswitch.consoleLog("notice", "[voicemail] transcribe_enabled: " .. transcribe_enabled .. "\n"); + end + --record your message at the tone press any key or stop talking to end the recording if (skip_instructions == "true") then --skip the instructions @@ -73,12 +134,13 @@ session:hangup(); else --get the voicemail options - sql = [[SELECT * FROM v_voicemail_options WHERE voicemail_uuid = ']] .. voicemail_uuid ..[[' ORDER BY voicemail_option_order asc ]]; + local sql = [[SELECT * FROM v_voicemail_options WHERE voicemail_uuid = :voicemail_uuid ORDER BY voicemail_option_order asc ]]; + local params = {voicemail_uuid = voicemail_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end count = 0; - status = dbh:query(sql, function(row) + dbh:query(sql, params, function(row) --check for matching options if (tonumber(row.voicemail_option_digits) ~= nil) then row.voicemail_option_digits = "^"..row.voicemail_option_digits.."$"; @@ -157,13 +219,16 @@ mkdir(voicemail_dir.."/"..voicemail_id); if (vm_message_ext == "mp3") then shout_exists = trim(api:execute("module_exists", "mod_shout")); - if (shout_exists == "true") then + if (shout_exists == "true" and transcribe_enabled == "false") then freeswitch.consoleLog("notice", "using mod_shout for mp3 encoding\n"); --record in mp3 directly result = session:recordFile(voicemail_dir.."/"..voicemail_id.."/msg_"..uuid..".mp3", max_len_seconds, record_silence_threshold, silence_seconds); else --create initial wav recording result = session:recordFile(voicemail_dir.."/"..voicemail_id.."/msg_"..uuid..".wav", max_len_seconds, record_silence_threshold, silence_seconds); + if (transcribe_enabled == "true") then + transcription = transcribe(voicemail_dir.."/"..voicemail_id.."/msg_"..uuid..".wav",settings); + end --use lame to encode, if available if (file_exists("/usr/bin/lame")) then freeswitch.consoleLog("notice", "using lame for mp3 encoding\n"); @@ -183,6 +248,9 @@ end else result = session:recordFile(voicemail_dir.."/"..voicemail_id.."/msg_"..uuid.."."..vm_message_ext, max_len_seconds, record_silence_threshold, silence_seconds); + if (transcribe_enabled == "true") then + transcription = transcribe(voicemail_dir.."/"..voicemail_id.."/msg_"..uuid.."."..vm_message_ext,settings); + end end end diff --git a/resources/install/scripts/app/voicemail/resources/functions/record_name.lua b/resources/install/scripts/app/voicemail/resources/functions/record_name.lua index 2cfdaa572f..f6036947c4 100644 --- a/resources/install/scripts/app/voicemail/resources/functions/record_name.lua +++ b/resources/install/scripts/app/voicemail/resources/functions/record_name.lua @@ -62,20 +62,21 @@ voicemail_name_base64 = assert(file.read_base64(voicemail_name_location)); --update the voicemail name - sql = "UPDATE v_voicemails "; - sql = sql .. "set voicemail_name_base64 = '".. voicemail_name_base64 .. "' "; - sql = sql .. "where domain_uuid = '".. domain_uuid .. "' "; - sql = sql .. "and voicemail_id = '".. voicemail_id .."'"; + local sql = "UPDATE v_voicemails "; + sql = sql .. "set voicemail_name_base64 = :voicemail_name_base64 "; + sql = sql .. "where domain_uuid = :domain_uuid "; + sql = sql .. "and voicemail_id = :voicemail_id"; + local params = {voicemail_name_base64 = voicemail_name_base64, + domain_uuid = domain_uuid, voicemail_id = voicemail_id}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[recording] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[recording] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end if (storage_type == "base64") then - local Database = require "resources.functions.database" local dbh = Database.new('system', 'base64'); - dbh:query(sql); + dbh:query(sql, params); dbh:release(); else - dbh:query(sql); + dbh:query(sql, params); end elseif (storage_type == "http_cache") then freeswitch.consoleLog("notice", "[voicemail] ".. storage_type .. " ".. storage_path .."\n"); diff --git a/resources/install/scripts/app/voicemail/resources/functions/send_email.lua b/resources/install/scripts/app/voicemail/resources/functions/send_email.lua index ed0dce8335..7e2d90f5ef 100644 --- a/resources/install/scripts/app/voicemail/resources/functions/send_email.lua +++ b/resources/install/scripts/app/voicemail/resources/functions/send_email.lua @@ -34,13 +34,14 @@ local settings = Settings.new(db, domain_name, domain_uuid) --get voicemail message details - sql = [[SELECT * FROM v_voicemails - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND voicemail_id = ']] .. id ..[[']] + local sql = [[SELECT * FROM v_voicemails + WHERE domain_uuid = :domain_uuid + AND voicemail_id = :voicemail_id]] + local params = {domain_uuid = domain_uuid, voicemail_id = id}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(row) + dbh:query(sql, params, function(row) db_voicemail_uuid = string.lower(row["voicemail_uuid"]); --voicemail_password = row["voicemail_password"]; --greeting_id = row["greeting_id"]; @@ -71,13 +72,14 @@ end --get voicemail message details - sql = [[SELECT * FROM v_voicemail_messages - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND voicemail_message_uuid = ']] .. uuid ..[[']] + local sql = [[SELECT * FROM v_voicemail_messages + WHERE domain_uuid = :domain_uuid + AND voicemail_message_uuid = :uuid]] + local params = {domain_uuid = domain_uuid, uuid = uuid}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(row) + dbh:query(sql, params, function(row) --get the values from the database --uuid = row["voicemail_message_uuid"]; created_epoch = row["created_epoch"]; @@ -115,8 +117,13 @@ local message_date = os.date("%A, %d %b %Y %I:%M %p", created_epoch) --prepare the files - file_subject = scripts_dir.."/app/voicemail/resources/templates/"..default_language.."/"..default_dialect.."/email_subject.tpl"; - file_body = scripts_dir.."/app/voicemail/resources/templates/"..default_language.."/"..default_dialect.."/email_body.tpl"; + if (transcription ~= nil) then + file_subject = scripts_dir.."/app/voicemail/resources/templates/"..default_language.."/"..default_dialect.."/email_subject.tpl"; + file_body = scripts_dir.."/app/voicemail/resources/templates/"..default_language.."/"..default_dialect.."/email_body_transcription.tpl"; + else + file_subject = scripts_dir.."/app/voicemail/resources/templates/"..default_language.."/"..default_dialect.."/email_subject.tpl"; + file_body = scripts_dir.."/app/voicemail/resources/templates/"..default_language.."/"..default_dialect.."/email_body.tpl"; + end if (not file_exists(file_subject)) then file_subject = scripts_dir.."/app/voicemail/resources/templates/en/us/email_subject.tpl"; file_body = scripts_dir.."/app/voicemail/resources/templates/en/us/email_body.tpl"; @@ -166,6 +173,9 @@ body = body:gsub("${caller_id_name}", caller_id_name); body = body:gsub("${caller_id_number}", caller_id_number); body = body:gsub("${message_date}", message_date); + if (transcription ~= nil) then + body = body:gsub("${message_text}", transcription); + end body = body:gsub("${message_duration}", message_length_formatted); body = body:gsub("${account}", voicemail_name_formatted); body = body:gsub("${voicemail_id}", id); @@ -203,14 +213,16 @@ if (string.len(voicemail_mail_to) > 2) then if (voicemail_local_after_email == "false") then --delete the voicemail message details - sql = [[DELETE FROM v_voicemail_messages - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND voicemail_uuid = ']] .. db_voicemail_uuid ..[[' - AND voicemail_message_uuid = ']] .. uuid ..[[']] + local sql = [[DELETE FROM v_voicemail_messages + WHERE domain_uuid = :domain_uuid + AND voicemail_uuid = :voicemail_uuid + AND voicemail_message_uuid = :uuid]] + local params = {domain_uuid = domain_uuid, + voicemail_uuid = db_voicemail_uuid, uuid = uuid}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - status = dbh:query(sql); + dbh:query(sql, params); --delete voicemail recording file if (file_exists(file)) then os.remove(file); diff --git a/resources/install/scripts/app/voicemail/resources/functions/send_sms.lua b/resources/install/scripts/app/voicemail/resources/functions/send_sms.lua new file mode 100644 index 0000000000..6fd9124f82 --- /dev/null +++ b/resources/install/scripts/app/voicemail/resources/functions/send_sms.lua @@ -0,0 +1,99 @@ +-- Part of FusionPBX +-- Copyright (C) 2013 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. + +--define a function to send sms + function send_sms(id, uuid) + debug["info"] = true; + api = freeswitch.API(); + + --get voicemail message details + sql = [[SELECT * FROM v_voicemails + WHERE domain_uuid = ']] .. domain_uuid ..[[' + AND voicemail_id = ']] .. id ..[[']] + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); + end + status = dbh:query(sql, function(row) + db_voicemail_uuid = string.lower(row["voicemail_uuid"]); + voicemail_sms_to = row["voicemail_sms_to"]; + voicemail_file = row["voicemail_file"]; + end); + + --get the sms_body template + if (settings['voicemail']['voicemail_sms_body'] ~= nil) then + if (settings['voicemail']['voicemail_sms_body']['text'] ~= nil) then + sms_body = settings['voicemail']['voicemail_sms_body']['text']; + end + else + sms_body = 'You have a new voicemail from: ${caller_id_name} - ${caller_id_number} length ${message_length_formatted}'; + end + + + --require the sms address to send to + if (string.len(voicemail_sms_to) > 2) then + --include languages file + local Text = require "resources.functions.text" + local text = Text.new("app.voicemail.app_languages") + + --get voicemail message details + sql = [[SELECT * FROM v_voicemail_messages + WHERE domain_uuid = ']] .. domain_uuid ..[[' + AND voicemail_message_uuid = ']] .. uuid ..[[']] + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[voicemail] SQL: " .. sql .. "\n"); + end + status = dbh:query(sql, function(row) + --get the values from the database + --uuid = row["voicemail_message_uuid"]; + created_epoch = row["created_epoch"]; + caller_id_name = row["caller_id_name"]; + caller_id_number = row["caller_id_number"]; + message_length = row["message_length"]; + end); + + --format the message length and date + message_length_formatted = format_seconds(message_length); + if (debug["info"]) then + freeswitch.consoleLog("notice", "[voicemail] message length: " .. message_length .. "\n"); + freeswitch.consoleLog("notice", "[voicemail] domain_name: " .. domain_name .. "\n"); + end + local message_date = os.date("%A, %d %b %Y %I:%M %p", created_epoch) + + sms_body = sms_body:gsub("${caller_id_name}", caller_id_name); + sms_body = sms_body:gsub("${caller_id_number}", caller_id_number); + sms_body = sms_body:gsub("${message_date}", message_date); + sms_body = sms_body:gsub("${message_duration}", message_length_formatted); + sms_body = sms_body:gsub("${account}", id); + sms_body = sms_body:gsub("${domain_name}", domain_name); + sms_body = sms_body:gsub("${sip_to_user}", id); + sms_body = sms_body:gsub("${dialed_user}", id); + +-- sms_body = "hello"; + cmd = "luarun app.lua sms outbound " .. voicemail_sms_to .. "@" .. domain_name .. " " .. voicemail_to_sms_did .. " '" .. sms_body .. "'"; + api:executeString(cmd); + + end + + end \ No newline at end of file diff --git a/resources/install/scripts/app/voicemail/resources/scripts/mwi.lua b/resources/install/scripts/app/voicemail/resources/scripts/mwi.lua index 20c7286020..149ddc2757 100644 --- a/resources/install/scripts/app/voicemail/resources/scripts/mwi.lua +++ b/resources/install/scripts/app/voicemail/resources/scripts/mwi.lua @@ -40,8 +40,8 @@ runonce = false; --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); --used to stop the lua service local file = assert(io.open(run_file, "w")); diff --git a/resources/install/scripts/app/voicemail/resources/scripts/mwi_subscribe.lua b/resources/install/scripts/app/voicemail/resources/scripts/mwi_subscribe.lua index 2ac501f1e7..9f37a011a7 100644 --- a/resources/install/scripts/app/voicemail/resources/scripts/mwi_subscribe.lua +++ b/resources/install/scripts/app/voicemail/resources/scripts/mwi_subscribe.lua @@ -14,7 +14,7 @@ local vm_message_count do local vm_to_uuid_sql = [[SELECT v.voicemail_uuid FROM v_voicemails as v inner join v_domains as d on v.domain_uuid = d.domain_uuid -WHERE v.voicemail_id = '%s' and d.domain_name = '%s']] +WHERE v.voicemail_id = :voicemail_id and d.domain_name = :domain_name]] local vm_messages_sql = [[SELECT ( SELECT count(*) @@ -50,7 +50,9 @@ function vm_message_count(account, use_cache) local sql = string.format(vm_to_uuid_sql, dbh:escape(id), dbh:escape(domain_name) ) - uuid = dbh:first_value(sql) + uuid = dbh:first_value(vm_to_uuid_sql, { + voicemail_id = id, domain_name = domain_name + }) if uuid and #uuid > 0 then cache.set('voicemail_uuid:' .. account, uuid, 3600) @@ -58,22 +60,21 @@ function vm_message_count(account, use_cache) end end - local sql + local row if uuid and #uuid > 0 then - sql = string.format(vm_messages_sql, - dbh:quoted(uuid), dbh:quoted(uuid) - ) + local sql = string.format(vm_messages_sql, ":voicemail_uuid", ":voicemail_uuid") + row = dbh:first_row(sql, {voicemail_uuid = uuid}) else - local uuid_sql = '(' .. string.format(vm_to_uuid_sql, - dbh:escape(id), dbh:escape(domain_name) - ) .. ')' + local uuid_sql = '(' .. vm_to_uuid_sql .. ')' - sql = string.format(vm_messages_sql, + local sql = string.format(vm_messages_sql, uuid_sql, uuid_sql ) - end - local row = sql and dbh:first_row(sql) + row = dbh:first_row(sql, { + voicemail_id = id, domain_name = domain_name + }) + end dbh:release() diff --git a/resources/install/scripts/app/voicemail/resources/templates/en/us/email_body_transcription.tpl b/resources/install/scripts/app/voicemail/resources/templates/en/us/email_body_transcription.tpl new file mode 100644 index 0000000000..1506eae2b0 --- /dev/null +++ b/resources/install/scripts/app/voicemail/resources/templates/en/us/email_body_transcription.tpl @@ -0,0 +1,69 @@ + + + + + + + + +
+ New Voicemail +
+ + + + + + + + + + + + + + + + + + + + + + +
+ To + + ${voicemail_name_formatted} +
+ From + + ${caller_id_number} +
+ Message + + ${message} +
+ Message Text + + ${message_text} +
+ Length + + ${message_duration} +
+
+ \ No newline at end of file diff --git a/resources/install/scripts/app/xml_handler/resources/scripts/configuration/acl.conf.lua b/resources/install/scripts/app/xml_handler/resources/scripts/configuration/acl.conf.lua index bc739429c5..7df083ec4e 100644 --- a/resources/install/scripts/app/xml_handler/resources/scripts/configuration/acl.conf.lua +++ b/resources/install/scripts/app/xml_handler/resources/scripts/configuration/acl.conf.lua @@ -48,8 +48,14 @@ end --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); + + --include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end --exits the script if we didn't connect properly assert(dbh:connected()); @@ -76,12 +82,13 @@ --get the nodes sql = "select * from v_access_control_nodes "; - sql = sql .. "where access_control_uuid = '"..row.access_control_uuid.."' "; + sql = sql .. "where access_control_uuid = :access_control_uuid"; + local params = {access_control_uuid = row.access_control_uuid} if (debug["sql"]) then - freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end x = 0; - dbh:query(sql, function(field) + dbh:query(sql, params, function(field) if (string.len(field.node_domain) > 0) then table.insert(xml, [[ ]]); else diff --git a/resources/install/scripts/app/xml_handler/resources/scripts/configuration/callcenter.conf.lua b/resources/install/scripts/app/xml_handler/resources/scripts/configuration/callcenter.conf.lua index 57cda269fc..84e919abc1 100644 --- a/resources/install/scripts/app/xml_handler/resources/scripts/configuration/callcenter.conf.lua +++ b/resources/install/scripts/app/xml_handler/resources/scripts/configuration/callcenter.conf.lua @@ -39,8 +39,8 @@ if (XML_STRING == "-ERR NOT FOUND") or (XML_STRING == "-ERR CONNECTION FAILURE") then --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); --exits the script if we didn't connect properly assert(dbh:connected()); diff --git a/resources/install/scripts/app/xml_handler/resources/scripts/configuration/conference.conf.lua b/resources/install/scripts/app/xml_handler/resources/scripts/configuration/conference.conf.lua index 36f8cba3cb..e8b72f6333 100644 --- a/resources/install/scripts/app/xml_handler/resources/scripts/configuration/conference.conf.lua +++ b/resources/install/scripts/app/xml_handler/resources/scripts/configuration/conference.conf.lua @@ -25,8 +25,14 @@ -- POSSIBILITY OF SUCH DAMAGE. --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); + +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end --exits the script if we didn't connect properly assert(dbh:connected()); @@ -45,19 +51,20 @@ if (debug["sql"]) then freeswitch.consoleLog("notice", "[conference_control] SQL: " .. sql .. "\n"); end - status = dbh:query(sql, function(field) + dbh:query(sql, function(field) conference_control_uuid = field["conference_control_uuid"]; table.insert(xml, [[ ]]); --get the conference control details from the database sql = [[SELECT * FROM v_conference_control_details - WHERE conference_control_uuid = ']] .. conference_control_uuid ..[[' + WHERE conference_control_uuid = :conference_control_uuid AND control_enabled = 'true' ]]; + local params = {conference_control_uuid = conference_control_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[conference_control] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[conference_control] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(row) + dbh:query(sql, params, function(row) --conference_control_uuid = row["conference_control_uuid"]; --conference_control_detail_uuid = row["conference_control_detail_uuid"]; table.insert(xml, [[ ]]); @@ -74,19 +81,20 @@ if (debug["sql"]) then freeswitch.consoleLog("notice", "[conference_profiles] SQL: " .. sql .. "\n"); end - status = dbh:query(sql, function(field) + dbh:query(sql, function(field) conference_profile_uuid = field["conference_profile_uuid"]; table.insert(xml, [[ ]]); --get the conference profile parameters from the database sql = [[SELECT * FROM v_conference_profile_params - WHERE conference_profile_uuid = ']] .. conference_profile_uuid ..[[' + WHERE conference_profile_uuid = :conference_profile_uuid AND profile_param_enabled = 'true' ]]; + local params = {conference_profile_uuid = conference_profile_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[conference_profiles] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[conference_profiles] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(row) + dbh:query(sql, params, function(row) --conference_profile_uuid = row["conference_profile_uuid"]; --conference_profile_param_uuid = row["conference_profile_param_uuid"]; --profile_param_description = row["profile_param_description"]; diff --git a/resources/install/scripts/app/xml_handler/resources/scripts/configuration/ivr.conf.lua b/resources/install/scripts/app/xml_handler/resources/scripts/configuration/ivr.conf.lua index fff5d76c3a..4001e27508 100644 --- a/resources/install/scripts/app/xml_handler/resources/scripts/configuration/ivr.conf.lua +++ b/resources/install/scripts/app/xml_handler/resources/scripts/configuration/ivr.conf.lua @@ -41,6 +41,10 @@ --required includes local Database = require "resources.functions.database" local Settings = require "resources.functions.lazy_settings" + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end --set the sound prefix sound_prefix = sounds_dir.."/${default_language}/${default_dialect}/${default_voice}/"; @@ -52,14 +56,15 @@ assert(dbh:connected()); --get the ivr menu from the database - sql = [[SELECT * FROM v_ivr_menus - WHERE ivr_menu_uuid = ']] .. ivr_menu_uuid ..[[' + local sql = [[SELECT * FROM v_ivr_menus + WHERE ivr_menu_uuid = :ivr_menu_uuid AND ivr_menu_enabled = 'true' ]]; + local params = {ivr_menu_uuid = ivr_menu_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[ivr_menu] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[ivr_menu] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(row) + dbh:query(sql, params, function(row) domain_uuid = row["domain_uuid"]; ivr_menu_name = row["ivr_menu_name"]; ivr_menu_extension = row["ivr_menu_extension"]; @@ -109,13 +114,14 @@ if not file_exists(path) then local sql = "SELECT recording_base64 FROM v_recordings " .. - "WHERE domain_uuid = '" .. domain_uuid .. "' " .. - "AND recording_filename = '" .. name .. "' " + "WHERE domain_uuid = :domain_uuid " .. + "AND recording_filename = :name " + local params = {domain_uuid = domain_uuid, name = name}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[ivr_menu] SQL: "..sql.."\n"); + freeswitch.consoleLog("notice", "[ivr_menu] SQL: "..sql.."; params:" .. json.encode(params) .. "\n"); end - dbh:query(sql, function(row) + dbh:query(sql, params, function(row) --get full path to recording is_base64, name = true, path @@ -226,11 +232,12 @@ table.insert(xml, [[ >]]); --get the ivr menu options - sql = [[SELECT * FROM v_ivr_menu_options WHERE ivr_menu_uuid = ']] .. ivr_menu_uuid ..[[' ORDER BY ivr_menu_option_order asc ]]; + local sql = [[SELECT * FROM v_ivr_menu_options WHERE ivr_menu_uuid = :ivr_menu_uuid ORDER BY ivr_menu_option_order asc ]]; + local params = {ivr_menu_uuid = ivr_menu_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[ivr_menu] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[ivr_menu] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(r) + dbh:query(sql, params, function(r) ivr_menu_option_digits = r.ivr_menu_option_digits ivr_menu_option_action = r.ivr_menu_option_action ivr_menu_option_param = r.ivr_menu_option_param diff --git a/resources/install/scripts/app/xml_handler/resources/scripts/configuration/local_stream.conf.lua b/resources/install/scripts/app/xml_handler/resources/scripts/configuration/local_stream.conf.lua index fbdaabc2f1..bcc19b3ca7 100644 --- a/resources/install/scripts/app/xml_handler/resources/scripts/configuration/local_stream.conf.lua +++ b/resources/install/scripts/app/xml_handler/resources/scripts/configuration/local_stream.conf.lua @@ -1,7 +1,7 @@ --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); --exits the script if we didn't connect properly assert(dbh:connected()); diff --git a/resources/install/scripts/app/xml_handler/resources/scripts/configuration/sofia.conf.lua b/resources/install/scripts/app/xml_handler/resources/scripts/configuration/sofia.conf.lua index af45ad6f84..ed2eec27dc 100644 --- a/resources/install/scripts/app/xml_handler/resources/scripts/configuration/sofia.conf.lua +++ b/resources/install/scripts/app/xml_handler/resources/scripts/configuration/sofia.conf.lua @@ -41,8 +41,14 @@ end --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); + + --include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end --exits the script if we didn't connect properly assert(dbh:connected()); @@ -52,11 +58,12 @@ --get the domain_uuid if (domain_name ~= nil) then sql = "SELECT domain_uuid FROM v_domains "; - sql = sql .. "WHERE domain_name = '" .. domain_name .."' "; + sql = sql .. "WHERE domain_name = :domain_name"; + local params = {domain_name = domain_name}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(rows) + dbh:query(sql, params, function(rows) domain_uuid = rows["domain_uuid"]; end); end @@ -88,14 +95,15 @@ sql = sql .. "from v_sip_profiles as p, v_sip_profile_settings as s "; sql = sql .. "where s.sip_profile_setting_enabled = 'true' "; sql = sql .. "and p.sip_profile_enabled = 'true' "; - sql = sql .. "and (p.sip_profile_hostname = '" .. hostname.. "' or p.sip_profile_hostname is null or p.sip_profile_hostname = '') "; + sql = sql .. "and (p.sip_profile_hostname = :hostname or p.sip_profile_hostname is null or p.sip_profile_hostname = '') "; sql = sql .. "and p.sip_profile_uuid = s.sip_profile_uuid "; sql = sql .. "order by p.sip_profile_name asc "; + local params = {hostname = hostname}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "; params: " .. json.encode(params) .. "\n"); end x = 0; - dbh:query(sql, function(row) + dbh:query(sql, params, function(row) --set as variables sip_profile_name = row.sip_profile_name; --sip_profile_description = row.sip_profile_description; @@ -117,19 +125,20 @@ --get the gateways if (domain_count > 1) then sql = "select * from v_gateways as g, v_domains as d "; - sql = sql .. "where g.profile = '"..sip_profile_name.."' "; + sql = sql .. "where g.profile = :profile "; sql = sql .. "and g.enabled = 'true' "; sql = sql .. "and (g.domain_uuid = d.domain_uuid or g.domain_uuid is null) "; else sql = "select * from v_gateways as g "; - sql = sql .. "where g.enabled = 'true' and g.profile = '"..sip_profile_name.."' "; + sql = sql .. "where g.enabled = 'true' and g.profile = :profile "; end - sql = sql .. "and (g.hostname = '" .. hostname.. "' or g.hostname is null or g.hostname = '') "; + sql = sql .. "and (g.hostname = :hostname or g.hostname is null or g.hostname = '') "; + local params = {profile = sip_profile_name, hostname = hostname}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end x = 0; - dbh:query(sql, function(field) + dbh:query(sql, params, function(field) table.insert(xml, [[ ]]); if (string.len(field.username) > 0) then diff --git a/resources/install/scripts/app/xml_handler/resources/scripts/dialplan/dialplan.lua b/resources/install/scripts/app/xml_handler/resources/scripts/dialplan/dialplan.lua index 582e763aeb..c283365b7b 100644 --- a/resources/install/scripts/app/xml_handler/resources/scripts/dialplan/dialplan.lua +++ b/resources/install/scripts/app/xml_handler/resources/scripts/dialplan/dialplan.lua @@ -47,8 +47,14 @@ if not XML_STRING then --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); + + --include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end --exits the script if we didn't connect properly assert(dbh:connected()); diff --git a/resources/install/scripts/app/xml_handler/resources/scripts/directory/action/acl.lua b/resources/install/scripts/app/xml_handler/resources/scripts/directory/action/acl.lua index 8132861696..0d9de9351f 100644 --- a/resources/install/scripts/app/xml_handler/resources/scripts/directory/action/acl.lua +++ b/resources/install/scripts/app/xml_handler/resources/scripts/directory/action/acl.lua @@ -3,6 +3,12 @@ local log = require "resources.functions.log"["directory_acl"] local dbh = Database.new('system') +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end + --build the xml local xml = {} table.insert(xml, [[]]) @@ -13,18 +19,19 @@ local sql = "SELECT * FROM v_domains as d, v_extensions as e " sql = sql .. "where d.domain_uuid = e.domain_uuid and e.cidr is not null and e.cidr <> '' " if domain_name then - sql = sql .. "and d.domain_name = '"..domain_name.."' " + sql = sql .. "and d.domain_name = :domain_name " else sql = sql .. "order by d.domain_name" end + local params = {domain_name = domain_name} if debug['sql'] then - log.noticef("SQL - %s", sql) + log.noticef("SQL: %s; params: %s", sql, json.encode(params)) end local prev_domain_name - dbh:query(sql, function(row) + dbh:query(sql, params, function(row) if prev_domain_name ~= row.domain_name then if prev_domain_name then table.insert(xml, [[ ]]) diff --git a/resources/install/scripts/app/xml_handler/resources/scripts/directory/action/directory.lua b/resources/install/scripts/app/xml_handler/resources/scripts/directory/action/directory.lua index 7ba1923aa3..7c649dab77 100644 --- a/resources/install/scripts/app/xml_handler/resources/scripts/directory/action/directory.lua +++ b/resources/install/scripts/app/xml_handler/resources/scripts/directory/action/directory.lua @@ -1,8 +1,15 @@ + --connect to the database local Database = require "resources.functions.database" local log = require "resources.functions.log"["directory_dir"] local dbh = Database.new('system') +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end + --build the xml local xml = {} table.insert(xml, [[]]) @@ -11,16 +18,17 @@ --process when the sip profile is rescanned, sofia is reloaded, or sip redirect local sql = "SELECT * FROM v_domains as d, v_extensions as e " - sql = sql .. "where d.domain_uuid = e.domain_uuid and " - sql = sql .. "(e.directory_visible = 'true' or e.directory_exten_visible='true') " + sql = sql .. "where d.domain_uuid = e.domain_uuid " + sql = sql .. "and (e.directory_visible = 'true' or e.directory_exten_visible='true') " if domain_name then - sql = sql .. "and d.domain_name = '"..domain_name.."' " + sql = sql .. "and d.domain_name = :domain_name " else - sql = sql .. "order by d.domain_name" + sql = sql .. "order by d.domain_name " end + local sql_params = {domain_name = domain_name} if debug['sql'] then - log.noticef("SQL - %s", sql) + log.noticef("SQL: %s; params: %s", sql, json.encode(sql_params)) end -- export this params @@ -37,7 +45,7 @@ local prev_domain_name - dbh:query(sql, function(row) + dbh:query(sql, sql_params, function(row) if prev_domain_name ~= row.domain_name then if prev_domain_name then table.insert(xml, [[ ]]) diff --git a/resources/install/scripts/app/xml_handler/resources/scripts/directory/action/domains.lua b/resources/install/scripts/app/xml_handler/resources/scripts/directory/action/domains.lua index cfd42346e3..e68a2a1f9a 100644 --- a/resources/install/scripts/app/xml_handler/resources/scripts/directory/action/domains.lua +++ b/resources/install/scripts/app/xml_handler/resources/scripts/directory/action/domains.lua @@ -25,8 +25,8 @@ -- POSSIBILITY OF SUCH DAMAGE. --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); --exits the script if we didn't connect properly assert(dbh:connected()); @@ -36,7 +36,7 @@ table.insert(xml, [[]]); table.insert(xml, [[]]); table.insert(xml, [[
]]); - sql = "SELECT domain_name FROM v_domains "; + local sql = "SELECT domain_name FROM v_domains "; dbh:query(sql, function(row) table.insert(xml, [[ ]]); end); diff --git a/resources/install/scripts/app/xml_handler/resources/scripts/directory/action/group_call.lua b/resources/install/scripts/app/xml_handler/resources/scripts/directory/action/group_call.lua index a201cb3409..2351ee4e41 100644 --- a/resources/install/scripts/app/xml_handler/resources/scripts/directory/action/group_call.lua +++ b/resources/install/scripts/app/xml_handler/resources/scripts/directory/action/group_call.lua @@ -34,8 +34,14 @@ --set the cache if (XML_STRING == "-ERR NOT FOUND") then --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + local dbh = Database.new('system'); + + --include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end --exits the script if we didn't connect properly assert(dbh:connected()); @@ -44,28 +50,35 @@ if (domain_uuid == nil) then --get the domain_uuid if (domain_name ~= nil) then - sql = "SELECT domain_uuid FROM v_domains "; - sql = sql .. "WHERE domain_name = '" .. domain_name .."' "; + local sql = "SELECT domain_uuid FROM v_domains "; + sql = sql .. "WHERE domain_name = :domain_name "; + local params = {domain_name = domain_name}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "; params: " .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(rows) + dbh:query(sql, params, function(rows) domain_uuid = rows["domain_uuid"]; end); end end + if not domain_uuid then + freeswitch.consoleLog("warning", "[xml_handler] Can not find domain name: " .. tostring(domain_name) .. "\n"); + return + end + --build the call group array - sql = [[ + local sql = [[ select * from v_extensions - where domain_uuid = ']]..domain_uuid..[[' + where domain_uuid = :domain_uuid order by call_group asc ]]; + local params = {domain_uuid = domain_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "; params: " .. json.encode(params) .. "\n"); end call_group_array = {}; - status = dbh:query(sql, function(row) + dbh:query(sql, params, function(row) call_group = row['call_group']; --call_group = str_replace(";", ",", call_group); tmp_array = explode(",", call_group); diff --git a/resources/install/scripts/app/xml_handler/resources/scripts/directory/action/reverse-auth-lookup.lua b/resources/install/scripts/app/xml_handler/resources/scripts/directory/action/reverse-auth-lookup.lua index 6711bc1f0f..087a54a5ee 100644 --- a/resources/install/scripts/app/xml_handler/resources/scripts/directory/action/reverse-auth-lookup.lua +++ b/resources/install/scripts/app/xml_handler/resources/scripts/directory/action/reverse-auth-lookup.lua @@ -31,22 +31,32 @@ --group_call - call group has been called --user_call - user has been called +--get logger + local log = require "resources.functions.log".xml_handler; + --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); + +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end --exits the script if we didn't connect properly assert(dbh:connected()); --get the domain_uuid - if (domain_uuid == nil and domain_name ~= nil) then + if (domain_uuid == nil) then if (domain_name ~= nil) then - sql = "SELECT domain_uuid FROM v_domains "; - sql = sql .. "WHERE domain_name = '" .. domain_name .."' "; + local sql = "SELECT domain_uuid FROM v_domains "; + sql = sql .. "WHERE domain_name = :domain_name "; + local params = {domain_name = domain_name} if (debug["sql"]) then - freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n"); + log.noticef("SQL: %s; params %s", sql, json.encode(params)); end - status = dbh:query(sql, function(rows) + dbh:query(sql, params, function(rows) domain_uuid = rows["domain_uuid"]; end); end @@ -54,11 +64,14 @@ --get the extension information if (domain_uuid ~= nil) then - sql = "SELECT * FROM v_extensions WHERE domain_uuid = '" .. domain_uuid .. "' and (extension = '" .. user .. "' or number_alias = '" .. user .. "') and enabled = 'true' "; + local sql = "SELECT * FROM v_extensions WHERE domain_uuid = :domain_uuid " + .. "and (extension = :user or number_alias = :user) " + .. "and enabled = 'true' "; + local params = {domain_uuid=domain_uuid, user=user}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n"); + log.noticef("SQL: %s; params %s", sql, json.encode(params)); end - dbh:query(sql, function(row) + dbh:query(sql, params, function(row) --general domain_uuid = row.domain_uuid; extension_uuid = row.extension_uuid; @@ -83,7 +96,7 @@ table.insert(xml, [[]]); table.insert(xml, [[
]]); table.insert(xml, [[ ]]); - table.insert(xml, [[ ]]); + table.insert(xml, [[ ]]); table.insert(xml, [[ ]]); table.insert(xml, [[ ]]); table.insert(xml, [[ ]]); diff --git a/resources/install/scripts/app/xml_handler/resources/scripts/directory/directory.lua b/resources/install/scripts/app/xml_handler/resources/scripts/directory/directory.lua index bf11c2dc38..dd5431a36c 100644 --- a/resources/install/scripts/app/xml_handler/resources/scripts/directory/directory.lua +++ b/resources/install/scripts/app/xml_handler/resources/scripts/directory/directory.lua @@ -1,6 +1,6 @@ -- xml_handler.lua -- Part of FusionPBX --- Copyright (C) 2013 - 2015 Mark J Crane +-- Copyright (C) 2013 - 2016 Mark J Crane -- All rights reserved. -- -- Redistribution and use in source and binary forms, with or without @@ -46,6 +46,12 @@ number_alias_string = ""; vm_mailto = ""; +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end + -- event source local event_calling_function = params:getHeader("Event-Calling-Function") local event_calling_file = params:getHeader("Event-Calling-File") @@ -70,26 +76,63 @@ --all other directory actions: sip_auth, user_call --except for the action: group_call + -- Do we need use proxy to make call to ext. reged on different FS + -- true - send call to FS where ext reged + -- false - send call directly to ext + local USE_FS_PATH = xml_handler and xml_handler["fs_path"] + + -- Make sance only for extensions with number_alias + -- false - you should register with AuthID=UserID=Extension (default) + -- true - you should register with AuthID=Extension and UserID=Number Alias + -- also in this case you need 2 records in memcache for one extension + local DIAL_STRING_BASED_ON_USERID = xml_handler and xml_handler["reg_as_number_alias"] + + -- Use number as presence_id + -- When you have e.g. extension like `user-100` with number-alias `100` + -- by default presence_id is `user-100`. This option allow use `100` as presence_id + local NUMBER_AS_PRESENCE_ID = xml_handler and xml_handler["number_as_presence_id"] + + local sip_auth_method = params:getHeader("sip_auth_method") + if sip_auth_method then + sip_auth_method = sip_auth_method:upper(); + end + + -- Get UserID. If used UserID ~= AuthID then we have to disable `inbound-reg-force-matching-username` + -- on sofia profile and check UserID=Number-Alias and AuthID=Extension on register manually. + -- But in load balancing mode in proxy INVITE we have UserID equal to origin UserID but + -- AuthID equal to callee AuthID. (e.g. 105 call to 100 and one FS forward call to other FS + -- then we have UserID=105 but AuthID=100). + -- Because we do not verify source of INVITE (FS or user device) we have to accept any UserID + -- for INVITE in such mode. So we just substitute correct UserID for check. + -- !!! NOTE !!! do not change USE_FS_PATH before this check. + local from_user = params:getHeader("sip_from_user") + if USE_FS_PATH and sip_auth_method == 'INVITE' then + from_user = user + end + + -- Check eather we need build dial-string. Before request dial-string FusionPBX set `dialed_extension` + -- variable. So if we have no such variable we do not need build dial-string. + dialed_extension = params:getHeader("dialed_extension"); + if (dialed_extension == nil) then + -- freeswitch.consoleLog("notice", "[xml_handler-directory.lua] dialed_extension is null\n"); + USE_FS_PATH = false; + else + -- freeswitch.consoleLog("notice", "[xml_handler-directory.lua] dialed_extension is " .. dialed_extension .. "\n"); + end + + -- verify from_user and number alias for this methods + local METHODS = { + -- _ANY_ = true, + REGISTER = true, + -- INVITE = true, + } + if (user == nil) then user = ""; end - --get the cache - if (trim(api:execute("module_exists", "mod_memcache")) == "true") then - if (domain_name) then - XML_STRING = trim(api:execute("memcache", "get directory:" .. user .. "@" .. domain_name)); - end - if (XML_STRING == "-ERR NOT FOUND") or (XML_STRING == "-ERR CONNECTION FAILURE") then - source = "database"; - continue = true; - else - source = "cache"; - continue = true; - end - else - XML_STRING = ""; - source = "database"; - continue = true; + if (from_user == "") or (from_user == nil) then + from_user = user end --prevent processing for invalid user @@ -98,27 +141,58 @@ continue = false; end + -- cleanup + XML_STRING = nil; + + -- get the cache. We can use cache only if we do not use `fs_path` + -- or we do not need dial-string. In other way we have to use database. + if (continue) and (not USE_FS_PATH) then + if (trim(api:execute("module_exists", "mod_memcache")) == "true") then + if (domain_name) then + local key = "directory:" .. (from_user or user) .. "@" .. domain_name + XML_STRING = trim(api:execute("memcache", "get " .. key)); + + if debug['cache'] then + if XML_STRING:sub(1, 4) == '-ERR' then + freeswitch.consoleLog("notice", "[xml_handler-directory][memcache] get key: " .. key .. " fail: " .. XML_STRING .. "\n") + else + freeswitch.consoleLog("notice", "[xml_handler-directory][memcache] get key: " .. key .. " pass!" .. "\n") + end + end + else + XML_STRING = "-ERR NOT FOUND" + end + if (XML_STRING == "-ERR NOT FOUND") or (XML_STRING == "-ERR CONNECTION FAILURE") then + source = "database"; + continue = true; + else + source = "cache"; + continue = true; + end + else + XML_STRING = ""; + source = "database"; + continue = true; + end + end + --show the params in the console --if (params:serialize() ~= nil) then -- freeswitch.consoleLog("notice", "[xml_handler-directory.lua] Params:\n" .. params:serialize() .. "\n"); --end - --set the variable from the params - dialed_extension = params:getHeader("dialed_extension"); - if (dialed_extension == nil) then - --freeswitch.consoleLog("notice", "[xml_handler-directory.lua] dialed_extension is null\n"); - xml_handler["fs_path"] = false; - else - --freeswitch.consoleLog("notice", "[xml_handler-directory.lua] dialed_extension is " .. dialed_extension .. "\n"); - end - + local loaded_from_db = false --build the XML string from the database - if (source == "database") or (xml_handler["fs_path"]) then + if (source == "database") or (USE_FS_PATH) then + loaded_from_db = true + + --include Database class + local Database = require "resources.functions.database"; + --database connection if (continue) then --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + dbh = Database.new('system'); --exits the script if we didn't connect properly assert(dbh:connected()); @@ -127,12 +201,13 @@ if (domain_uuid == nil) then --get the domain_uuid if (domain_name ~= nil) then - sql = "SELECT domain_uuid FROM v_domains "; - sql = sql .. "WHERE domain_name = '" .. domain_name .."' "; + local sql = "SELECT domain_uuid FROM v_domains " + .. "WHERE domain_name = :domain_name "; + local params = {domain_name = domain_name}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(rows) + dbh:query(sql, params, function(rows) domain_uuid = rows["domain_uuid"]; end); end @@ -146,13 +221,17 @@ --if load balancing is set to true then get the hostname if (continue) then - if (xml_handler["fs_path"]) then + if (USE_FS_PATH) then --get the domain_name from domains if (domain_name == nil) then - sql = "SELECT domain_name FROM v_domains "; - sql = sql .. "WHERE domain_uuid = '" .. domain_uuid .. "' "; - status = dbh:query(sql, function(row) + local sql = "SELECT domain_name FROM v_domains " + .. "WHERE domain_uuid = :domain_uuid "; + local params = {domain_uuid = domain_uuid}; + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); + end + dbh:query(sql, params, function(row) domain_name = row["domain_name"]; end); end @@ -165,33 +244,37 @@ require "resources.functions.file_exists"; --connect to the switch database - if (file_exists(database_dir.."/core.db")) then - --dbh_switch = freeswitch.Dbh("core:core"); -- when using sqlite - dbh_switch = freeswitch.Dbh("sqlite://"..database_dir.."/core.db"); - else - require "resources.functions.database_handle"; - dbh_switch = database_handle('switch'); + dbh_switch = Database.new('switch'); + + --get register name + local reg_user = dialed_extension + if not DIAL_STRING_BASED_ON_USERID then + reg_user = trim(api:execute("user_data", dialed_extension .. "@" .. domain_name .. " attr id")); end --get the destination hostname from the registration - sql = "SELECT hostname FROM registrations "; - sql = sql .. "WHERE reg_user = '"..dialed_extension.."' "; - sql = sql .. "AND realm = '"..domain_name.."' "; + local params = {reg_user=reg_user, domain_name=domain_name} + local sql = "SELECT hostname FROM registrations " + .. "WHERE reg_user = :reg_user " + .. "AND realm = :domain_name "; if (database["type"] == "mysql") then - now = os.time(); - sql = sql .. "AND expires > "..now; + params.now = os.time(); + sql = sql .. "AND expires > :now "; else - sql = sql .. "AND to_timestamp(expires) > NOW()"; + sql = sql .. "AND to_timestamp(expires) > NOW() "; end - status = dbh_switch:query(sql, function(row) + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); + end + dbh_switch:query(sql, params, function(row) database_hostname = row["hostname"]; end); --freeswitch.consoleLog("notice", "[xml_handler] sql: " .. sql .. "\n"); --freeswitch.consoleLog("notice", "[xml_handler-directory.lua] database_hostname is " .. database_hostname .. "\n"); - --hostname was not found set xml_handler["fs_path"] to false to prevent a database_hostname concatenation error + --hostname was not found set USE_FS_PATH to false to prevent a database_hostname concatenation error if (database_hostname == nil) then - xml_handler["fs_path"] = false; + USE_FS_PATH = false; end --close the database connection @@ -201,12 +284,15 @@ --get the extension from the database if (continue) then - sql = "SELECT * FROM v_extensions WHERE domain_uuid = '" .. domain_uuid .. "' and (extension = '" .. user .. "' or number_alias = '" .. user .. "') and enabled = 'true' "; + local sql = "SELECT * FROM v_extensions WHERE domain_uuid = :domain_uuid " + .. "and (extension = :user or number_alias = :user) " + .. "and enabled = 'true' "; + local params = {domain_uuid=domain_uuid, user=user}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end continue = false; - dbh:query(sql, function(row) + dbh:query(sql, params, function(row) --general continue = true; domain_uuid = row.domain_uuid; @@ -265,30 +351,48 @@ do_not_disturb = row.do_not_disturb; + -- check matching UserID and AuthName + if sip_auth_method then + local check_from_number = METHODS[sip_auth_method] or METHODS._ANY_ + if DIAL_STRING_BASED_ON_USERID then + continue = (sip_from_user == user) and ((not check_from_number) or (from_user == sip_from_number)) + else + continue = (sip_from_user == user) and ((not check_from_number) or (from_user == user)) + end + + if not continue then + XML_STRING = nil; + return 1; + end + end + + --set the presence_id + presence_id = (NUMBER_AS_PRESENCE_ID and sip_from_number or sip_from_user) .. "@" .. domain_name; + --set the dial_string if (string.len(row.dial_string) > 0) then dial_string = row.dial_string; else + local destination = (DIAL_STRING_BASED_ON_USERID and sip_from_number or sip_from_user) .. "@" .. domain_name; --set a default dial string if (dial_string == null) then - dial_string = "{sip_invite_domain=" .. domain_name .. ",presence_id=" .. user .. "@" .. domain_name .. "}${sofia_contact(" .. extension .. "@" .. domain_name .. ")}"; + dial_string = "{sip_invite_domain=" .. domain_name .. ",presence_id=" .. presence_id .. "}${sofia_contact(" .. destination .. ")}"; end --set the an alternative dial string if the hostnames don't match - if (xml_handler["fs_path"]) then + if (USE_FS_PATH) then if (local_hostname == database_hostname) then freeswitch.consoleLog("notice", "[xml_handler-directory.lua] local_host and database_host are the same\n"); else - --sofia/internal/${user_data(${destination_number}@${domain_name} attr id)}@${domain_name};fs_path=sip:server - user_id = trim(api:execute("user_data", user .. "@" .. domain_name .. " attr id")); - dial_string = "{sip_invite_domain=" .. domain_name .. ",presence_id=" .. user .. "@" .. domain_name .. "}sofia/internal/" .. user_id .. "@" .. domain_name .. ";fs_path=sip:" .. database_hostname; + local profile, proxy = "internal", database_hostname; + dial_string = "{sip_invite_domain=" .. domain_name .. ",presence_id=" .. presence_id .."}sofia/" .. profile .. "/" .. destination .. ";fs_path=sip:" .. proxy; --freeswitch.consoleLog("notice", "[xml_handler-directory.lua] dial_string " .. dial_string .. "\n"); end else - --freeswitch.consoleLog("notice", "[xml_handler-directory.lua] seems balancing is false??" .. tostring(xml_handler["fs_path"]) .. "\n"); + --freeswitch.consoleLog("notice", "[xml_handler-directory.lua] seems balancing is false??" .. tostring(USE_FS_PATH) .. "\n"); end --show debug informationa - if (xml_handler["fs_path"]) then + if (USE_FS_PATH) then freeswitch.consoleLog("notice", "[xml_handler] local_hostname: " .. local_hostname.. " database_hostname: " .. database_hostname .. " dial_string: " .. dial_string .. "\n"); end end @@ -298,15 +402,17 @@ --get the voicemail from the database if (continue) then vm_enabled = "true"; - if tonumber(user) == nil then - sql = "SELECT * FROM v_voicemails WHERE domain_uuid = '" .. domain_uuid .. "' and voicemail_id = '" .. number_alias .. "' "; + local sql = "SELECT * FROM v_voicemails WHERE domain_uuid = :domain_uuid and voicemail_id = :voicemail_id "; + local params = {domain_uuid = domain_uuid}; + if number_alias and #number_alias > 0 then + params.voicemail_id = number_alias; else - sql = "SELECT * FROM v_voicemails WHERE domain_uuid = '" .. domain_uuid .. "' and voicemail_id = '" .. user .. "' "; + params.voicemail_id = user; end if (debug["sql"]) then - freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - dbh:query(sql, function(row) + dbh:query(sql, params, function(row) if (string.len(row.voicemail_enabled) > 0) then vm_enabled = row.voicemail_enabled; end @@ -389,6 +495,7 @@ table.insert(xml, [[ ]]); table.insert(xml, [[ ]]); table.insert(xml, [[ ]]); + table.insert(xml, [[ ]]); if (string.len(call_group) > 0) then table.insert(xml, [[ ]]); end @@ -517,14 +624,26 @@ dbh:release(); --set the cache - if (user and domain_name) then - result = trim(api:execute("memcache", "set directory:" .. user .. "@" .. domain_name .. " '"..XML_STRING:gsub("'", "'").."' "..expire["directory"])); + local key = "directory:" .. sip_from_number .. "@" .. domain_name + if debug['cache'] then + freeswitch.consoleLog("notice", "[xml_handler-directory][memcache] set key: " .. key .. "\n") + end + result = trim(api:execute("memcache", "set " .. key .. " '"..XML_STRING:gsub("'", "'").."' "..expire["directory"])); + + if sip_from_number ~= sip_from_user then + key = "directory:" .. sip_from_user .. "@" .. domain_name + if debug['cache'] then + freeswitch.consoleLog("notice", "[xml_handler-directory][memcache] set key: " .. key .. "\n") + end + result = trim(api:execute("memcache", "set " .. key .. " '"..XML_STRING:gsub("'", "'").."' "..expire["directory"])); end - --save to the conf directory - --local file = assert(io.open(conf_dir .. "/directory/" .. user .. "@" .. domain_name .. ".xml.cache", "w")); - --file:write(XML_STRING); - --file:close(); + --send the xml to the console + if (debug["xml_string"]) then + local file = assert(io.open(temp_dir .. "/" .. user .. "@" .. domain_name .. ".xml", "w")); + file:write(XML_STRING); + file:close(); + end --send to the console if (debug["cache"]) then @@ -533,10 +652,22 @@ end end - --disable registration for number-alias - if (params:getHeader("sip_auth_method") == "REGISTER") then - if (api:execute("user_data", user .. "@" .. domain_name .." attr id") ~= user) then + if XML_STRING and (not loaded_from_db) and sip_auth_method then + local user_id = api:execute("user_data", from_user .. "@" .. domain_name .." attr id") + if user_id ~= user then XML_STRING = nil; + elseif METHODS[sip_auth_method] or METHODS._ANY_ then + local alias + if DIAL_STRING_BASED_ON_USERID then + alias = api:execute("user_data", from_user .. "@" .. domain_name .." attr number-alias") + end + if alias and #alias > 0 then + if from_user ~= alias then + XML_STRING = nil + end + elseif from_user ~= user_id then + XML_STRING = nil; + end end end diff --git a/resources/install/scripts/app/xml_handler/resources/scripts/languages/languages.lua b/resources/install/scripts/app/xml_handler/resources/scripts/languages/languages.lua index f0b01d242d..e5a009021b 100644 --- a/resources/install/scripts/app/xml_handler/resources/scripts/languages/languages.lua +++ b/resources/install/scripts/app/xml_handler/resources/scripts/languages/languages.lua @@ -67,29 +67,35 @@ --build the XML string from the database if (source == "database") then - --database connection + --connect to the database + local Database = require "resources.functions.database"; + dbh = Database.new('system'); + + --include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end + + --exits the script if we didn't connect properly + assert(dbh:connected()); + + --get the domain_uuid if (continue) then - --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); - - --exits the script if we didn't connect properly - assert(dbh:connected()); - - --get the domain_uuid - if (domain_uuid == nil) then - --get the domain_uuid - if (domain_name ~= nil) then - sql = "SELECT domain_uuid FROM v_domains "; - sql = sql .. "WHERE domain_name = '" .. domain_name .."' "; - if (debug["sql"]) then - freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n"); - end - status = dbh:query(sql, function(rows) - domain_uuid = rows["domain_uuid"]; - end); + if (domain_uuid == nil) then + --get the domain_uuid + if (domain_name ~= nil) then + local sql = "SELECT domain_uuid FROM v_domains "; + sql = sql .. "WHERE domain_name = :domain_name "; + local params = {domain_name = domain_name}; + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - end + dbh:query(sql, params, function(rows) + domain_uuid = rows["domain_uuid"]; + end); + end + end end --prevent processing for invalid domains @@ -113,20 +119,21 @@ table.insert(xml, [[ ]]); table.insert(xml, [[ ]]); - sql = "SELECT * FROM v_phrases as p, v_phrase_details as d "; - sql = sql .. "WHERE d.domain_uuid = '" .. domain_uuid .. "' "; - sql = sql .. "AND p.phrase_uuid = '".. macro_name .."' "; - sql = sql .. "AND p.phrase_language = '".. language .."' "; + local sql = "SELECT * FROM v_phrases as p, v_phrase_details as d "; + sql = sql .. "WHERE d.domain_uuid = :domain_uuid "; + sql = sql .. "AND p.phrase_uuid = :macro_name "; + sql = sql .. "AND p.phrase_language = :language "; sql = sql .. "AND p.phrase_uuid = d.phrase_uuid "; sql = sql .. "AND p.phrase_enabled = 'true' "; sql = sql .. "ORDER BY d.domain_uuid, p.phrase_uuid, d.phrase_detail_order ASC "; + local params = {domain_uuid = domain_uuid, macro_name = macro_name, language = language}; if (debug["sql"]) then freeswitch.consoleLog("notice", "[xml_handler] SQL: " .. sql .. "\n"); end previous_phrase_uuid = ""; match_tag = "open"; x = 0; - dbh:query(sql, function(row) + dbh:query(sql, params, function(row) --phrase_uuid,domain_uuid,phrase_name,phrase_language --phrase_description,phrase_enabled,phrase_detail_uuid --phrase_detail_group,phrase_detail_tag,phrase_detail_pattern diff --git a/resources/install/scripts/call_flow.lua b/resources/install/scripts/call_flow.lua index bddac99859..1a802d575e 100644 --- a/resources/install/scripts/call_flow.lua +++ b/resources/install/scripts/call_flow.lua @@ -37,6 +37,12 @@ local file = require "resources.functions.file" local log = require "resources.functions.log".call_flow +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end + --connect to the database local dbh = Database.new('system'); @@ -72,14 +78,15 @@ local function find_file(dbh, domain_name, domain_uuid, file_name) local storage_type = settings:get('recordings', 'storage_type', 'text') or '' if storage_type == 'base64' then local sql = "SELECT recording_base64 FROM v_recordings " - .. "WHERE domain_uuid = '" .. domain_uuid .."'" - .. "AND recording_filename = '".. file_name.. "' " + .. "WHERE domain_uuid = :domain_uuid" + .. "AND recording_filename = :file_name " + local params = {domain_uuid = domain_uuid, file_name = file_name}; if (debug["sql"]) then - log.notice("SQL: " .. sql) + log.notice("SQL: " .. sql .. "; params: " .. json.encode(params)) end local dbh = Database.new('system', 'base64/read') - local recording_base64 = dbh:first_value(sql); + local recording_base64 = dbh:first_value(sql, params); dbh:release(); if recording_base64 and #recording_base64 > 32 then @@ -149,11 +156,12 @@ if (session:ready()) then local default_voice = session:getVariable("default_voice") or 'callie'; --get the extension list - local sql = "SELECT * FROM v_call_flows where call_flow_uuid = '"..call_flow_uuid.."'" + local sql = "SELECT * FROM v_call_flows where call_flow_uuid = :call_flow_uuid" -- .. "and call_flow_enabled = 'true'" + local params = {call_flow_uuid = call_flow_uuid}; --log.notice("SQL: %s", sql); - dbh:query(sql, function(row) + dbh:query(sql, params, function(row) call_flow_name = row.call_flow_name; call_flow_extension = row.call_flow_extension; call_flow_feature_code = row.call_flow_feature_code; @@ -210,7 +218,9 @@ if (session:ready()) then log.noticef("label=%s,status=%s,uuid=%s,audio=%s", active_flow_label, toggle, call_flow_uuid, audio_file) --store in database - dbh:query("UPDATE v_call_flows SET call_flow_status = '"..toggle.."' WHERE call_flow_uuid = '"..call_flow_uuid.."'"); + dbh:query("UPDATE v_call_flows SET call_flow_status = :toggle WHERE call_flow_uuid = :call_flow_uuid", { + toggle = toggle, call_flow_uuid = call_flow_uuid + }); --answer session:answer(); diff --git a/resources/install/scripts/call_flow_monitor.lua b/resources/install/scripts/call_flow_monitor.lua index 6ca281c57b..a0af8f03f8 100644 --- a/resources/install/scripts/call_flow_monitor.lua +++ b/resources/install/scripts/call_flow_monitor.lua @@ -38,7 +38,7 @@ require "resources.functions.file_exists"; require "resources.functions.mkdir"; - require "resources.functions.database_handle"; + local Database = require "resources.functions.database"; local log = require "resources.functions.log".call_flow_monitor @@ -78,7 +78,7 @@ end --connect to the database - local dbh = database_handle('system'); + local dbh = Database.new('system'); --get the extension list if dbh:connected() then diff --git a/resources/install/scripts/call_forward.lua b/resources/install/scripts/call_forward.lua index 6565f3aad9..c7fb7c7904 100644 --- a/resources/install/scripts/call_forward.lua +++ b/resources/install/scripts/call_forward.lua @@ -37,24 +37,18 @@ --include config.lua require "resources.functions.config"; ---include config.lua - require "resources.functions.settings"; - require "resources.functions.channel_utils"; local log = require "resources.functions.log".call_forward local cache = require "resources.functions.cache" local Database = require "resources.functions.database" + local Settings = require "resources.functions.lazy_settings" local route_to_bridge = require "resources.functions.route_to_bridge" - local function opt(t, ...) - if select('#', ...) == 0 then - return t - end - if type(t) ~= 'table' then - return nil - end - return opt(t[...], select(2, ...)) +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" end local function empty(t) @@ -86,7 +80,7 @@ session:sleep(1000); --connect to the database - dbh = Database.new('system'); + local dbh = Database.new('system'); --request id is true if (request_id == "true") then @@ -110,12 +104,13 @@ --check to see if the pin number is correct if not session:ready() then return end local sql = "SELECT voicemail_password FROM v_voicemails "; - sql = sql .. "WHERE domain_uuid = '" .. domain_uuid .."' "; - sql = sql .. "AND voicemail_id = '" .. extension .."' "; + sql = sql .. "WHERE domain_uuid = :domain_uuid "; + sql = sql .. "AND voicemail_id = :extension "; + local params = {domain_uuid = domain_uuid, extension = extension}; if (debug["sql"]) then - log.notice(sql); + log.noticef("SQL: %s; params: %s", sql, json.encode(params)); end - local voicemail_password = dbh:first_value(sql) + local voicemail_password = dbh:first_value(sql, params) if (voicemail_password ~= caller_pin_number) then --access denied session:streamFile("phrase:voicemail_fail_auth:#"); @@ -127,16 +122,19 @@ if not session:ready() then return end local sql = "select * from v_extensions "; - sql = sql .. "where domain_uuid = '"..domain_uuid.."' "; + sql = sql .. "where domain_uuid = :domain_uuid "; + local params = {domain_uuid = domain_uuid}; if (extension_uuid ~= nil) then - sql = sql .. "and extension_uuid = '"..extension_uuid.."' "; + sql = sql .. "and extension_uuid = :extension_uuid "; + params.extension_uuid = extension_uuid; else - sql = sql .. "and (extension = '"..extension.."' or number_alias = '"..extension.."') "; + sql = sql .. "and (extension = :extension or number_alias = :extension) "; + params.extension = extension; end if (debug["sql"]) then - log.notice(sql); + log.noticef("SQL: %s; params: %s", sql, json.encode(params)); end - local row = dbh:first_row(sql) + local row = dbh:first_row(sql, params) if not row then return end extension_uuid = row.extension_uuid; @@ -178,9 +176,13 @@ if enabled == "true" and not empty(forward_caller_id_uuid) then local sql = "select destination_number, destination_description,".. "destination_caller_id_number, destination_caller_id_name " .. - "from v_destinations where domain_uuid = '" .. domain_uuid .. "' and " .. - "destination_type = 'inbound' and destination_uuid = '" .. forward_caller_id_uuid .. "'"; - local row = dbh:first_row(sql) + "from v_destinations where domain_uuid = :domain_uuid and " .. + "destination_type = 'inbound' and destination_uuid = :destination_uuid"; + local params = {domain_uuid = domain_uuid; destination_uuid = forward_caller_id_uuid} + if (debug["sql"]) then + log.noticef("SQL: %s; params: %s", sql, json.encode(params)); + end + local row = dbh:first_row(sql, params) if row then local caller_id_number = row.destination_caller_id_number if empty(caller_id_number) then @@ -212,66 +214,64 @@ --used for number_alias to get the correct user local sql = "select extension, number_alias from v_extensions "; - sql = sql .. "where domain_uuid = '"..domain_uuid.."' "; - sql = sql .. "and number_alias = '"..forward_all_destination.."' "; - dbh:query(sql, function(row) + sql = sql .. "where domain_uuid = :domain_uuid "; + sql = sql .. "and number_alias = :number_alias "; + local params = {domain_uuid = domain_uuid; number_alias = forward_all_destination} + if (debug["sql"]) then + log.noticef("SQL: %s; params: %s", sql, json.encode(params)); + end + dbh:query(sql, params, function(row) destination_user = row.extension; destination_extension = row.extension; destination_number_alias = row.number_alias or ''; end); - local presence_id - if destination_extension then - if (#destination_number_alias > 0) and (opt(settings(domain_uuid), 'provision', 'number_as_presence_id', 'boolean') == 'true') then - presence_id = destination_number_alias - else - presence_id = destination_extension - end - elseif extension then - -- setting here presence_id equal extension not dialed number allows work BLF and intercept. - -- $presence_id = extension_presence_id($this->extension, $this->number_alias); - if (#number_alias > 0) and (opt(settings(domain_uuid), 'provision', 'number_as_presence_id', 'boolean') == 'true') then - presence_id = number_alias - else - presence_id = extension - end - else - presence_id = forward_all_destination - end - - --set the dial_string - dial_string = "{presence_id="..presence_id.."@"..domain_name; - dial_string = dial_string .. ",instant_ringback=true"; - dial_string = dial_string .. ",domain_uuid="..domain_uuid; - dial_string = dial_string .. ",sip_invite_domain="..domain_name; - dial_string = dial_string .. ",domain_name="..domain_name; - dial_string = dial_string .. ",domain="..domain_name; - dial_string = dial_string .. ",toll_allow='"..toll_allow.."'"; - dial_string = dial_string .. ",sip_h_Diversion=;reason=unconditional"; - if (accountcode ~= nil) then - dial_string = dial_string .. ",accountcode="..accountcode; - end - dial_string = dial_string .. forward_caller_id - dial_string = dial_string .. "}"; - if (destination_user ~= nil) then cmd = "user_exists id ".. destination_user .." "..domain_name; else cmd = "user_exists id ".. forward_all_destination .." "..domain_name; end - user_exists = trim(api:executeString(cmd)); - if (user_exists == "true") then - if (destination_user ~= nil) then - dial_string = dial_string .. "user/"..destination_user.."@"..domain_name; - else - dial_string = dial_string .. "user/"..forward_all_destination.."@"..domain_name; - end + local user_exists = trim(api:executeString(cmd)); + + --set the dial_string + dial_string = "{instant_ringback=true"; + dial_string = dial_string .. ",domain_uuid="..domain_uuid; + dial_string = dial_string .. ",sip_invite_domain="..domain_name; + dial_string = dial_string .. ",domain_name="..domain_name; + dial_string = dial_string .. ",domain="..domain_name; + dial_string = dial_string .. ",extension_uuid="..extension_uuid; + dial_string = dial_string .. ",toll_allow='"..toll_allow.."'"; + dial_string = dial_string .. ",sip_h_Diversion=;reason=unconditional"; + if (not accountcode) or (#accountcode == 0) then + dial_string = dial_string .. ",sip_h_X-accountcode=${accountcode}"; else - local mode = opt(settings(domain_uuid), 'domain', 'bridge', 'text') + dial_string = dial_string .. ",sip_h_X-accountcode="..accountcode; + dial_string = dial_string .. ",accountcode="..accountcode; + end + dial_string = dial_string .. forward_caller_id + + if (user_exists == "true") then + -- we do not need here presence_id because user dial-string already has one + dial_string = dial_string .. ",dialed_extension=" .. forward_all_destination + dial_string = dial_string .. "}" + dial_string = dial_string .. "user/"..forward_all_destination.."@"..domain_name; + else + -- setting here presence_id equal extension not dialed number allows work BLF and intercept. + local settings, presence_id = Settings.new(dbh, domain_name, domain_uuid) + if (#number_alias > 0) and (settings:get('provision', 'number_as_presence_id', 'text') == 'true') then + presence_id = number_alias + else + presence_id = extension + end + + dial_string = dial_string .. ",presence_id="..presence_id.."@"..domain_name; + dial_string = dial_string .. "}"; + local mode = settings:get('domain', 'bridge', 'text') if mode == "outbound" or mode == "bridge" then local bridge = route_to_bridge(dbh, domain_uuid, { destination_number = forward_all_destination; ['${toll_allow}'] = toll_allow; + ['${user_exists}'] = 'false'; }) if bridge and bridge.bridge then dial_string = dial_string .. bridge.bridge @@ -297,12 +297,13 @@ if enabled == "true" and not empty(follow_me_uuid) then local sql = "update v_follow_me set "; sql = sql .. "follow_me_enabled = 'false' "; - sql = sql .. "where domain_uuid = '"..domain_uuid.."' "; - sql = sql .. "and follow_me_uuid = '"..follow_me_uuid.."' "; + sql = sql .. "where domain_uuid = :domain_uuid "; + sql = sql .. "and follow_me_uuid = :follow_me_uuid "; + local params = {domain_uuid = domain_uuid, follow_me_uuid = follow_me_uuid}; if (debug["sql"]) then - log.notice(sql); + log.noticef("SQL: %s; params: %s", sql, json.encode(params)); end - dbh:query(sql); + dbh:query(sql, params); end --check the destination @@ -315,20 +316,27 @@ do local sql = "update v_extensions set "; if (enabled == "true") then - sql = sql .. "forward_all_destination = '"..forward_all_destination.."', "; - sql = sql .. "dial_string = '"..dial_string:gsub("'", "''").."', "; + sql = sql .. "forward_all_destination = :forward_all_destination, "; + sql = sql .. "dial_string = :dial_string, "; sql = sql .. "do_not_disturb = 'false', "; else sql = sql .. "forward_all_destination = null, "; sql = sql .. "dial_string = null, "; end - sql = sql .. "forward_all_enabled = '"..forward_all_enabled.."' "; - sql = sql .. "where domain_uuid = '"..domain_uuid.."' "; - sql = sql .. "and extension_uuid = '"..extension_uuid.."' "; + sql = sql .. "forward_all_enabled = :forward_all_enabled "; + sql = sql .. "where domain_uuid = :domain_uuid "; + sql = sql .. "and extension_uuid = :extension_uuid "; + local params = { + forward_all_destination = forward_all_destination; + dial_string = dial_string; + forward_all_enabled = forward_all_enabled; + domain_uuid = domain_uuid; + extension_uuid = extension_uuid; + } if (debug["sql"]) then - log.notice(sql); + log.noticef("SQL: %s; params: %s", sql, json.encode(params)); end - dbh:query(sql); + dbh:query(sql, params); end --disconnect from database diff --git a/resources/install/scripts/cidlookup.lua b/resources/install/scripts/cidlookup.lua index d6c4e31b32..6dd990b85a 100644 --- a/resources/install/scripts/cidlookup.lua +++ b/resources/install/scripts/cidlookup.lua @@ -16,7 +16,7 @@ -- -- The Initial Developer of the Original Code is -- Mark J Crane --- Copyright (C) 2010-2014 +-- Copyright (C) 2010-2016 -- the Initial Developer. All Rights Reserved. -- -- Contributor(s): @@ -26,9 +26,6 @@ -- add this in Inbound Routes before transfer to use it: -- action set caller_id_name=${luarun cidlookup.lua ${uuid}} ---debug - debug["sql"] = true; - --define the trim function require "resources.functions.trim" @@ -71,42 +68,54 @@ --include config.lua require "resources.functions.config"; ---check if the session is ready +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end - --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); +--connect to the database + local Database = require "resources.functions.database"; + dbh = Database.new('system'); + if (database["type"] == "mysql") then + sql = "SELECT CONCAT(v_contacts.contact_name_given, ' ', v_contacts.contact_name_family,' (',v_contact_phones.phone_type,')') AS name FROM v_contacts "; + elseif (database["type"] == "pgsql") then + sql = "SELECT CASE WHEN contact_name_given = '' THEN v_contacts.contact_organization ELSE v_contacts.contact_name_given || ' ' || v_contacts.contact_name_family || ' (' || v_contact_phones.phone_label || ')' END AS name FROM v_contacts "; + else + sql = "SELECT v_contacts.contact_name_given || ' ' || v_contacts.contact_name_family || ' (' || v_contact_phones.phone_type || ')' AS name FROM v_contacts "; + end + sql = sql .. "INNER JOIN v_contact_phones ON v_contact_phones.contact_uuid = v_contacts.contact_uuid "; + sql = sql .. "INNER JOIN v_destinations ON v_destinations.domain_uuid = v_contacts.domain_uuid "; + sql = sql .. "WHERE v_contact_phones.phone_number = :caller " + local params = {caller = caller} - if (database["type"] == "mysql") then - sql = "SELECT CONCAT(v_contacts.contact_name_given, ' ', v_contacts.contact_name_family,' (',v_contact_phones.phone_type,')') AS name FROM v_contacts "; - else - sql = "SELECT v_contacts.contact_name_given || ' ' || v_contacts.contact_name_family || ' (' || v_contact_phones.phone_type || ')' AS name FROM v_contacts "; - end + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[cidlookup] SQL: "..sql.."; params:" .. json.encode(params) .. "\n"); + end - sql = sql .. "INNER JOIN v_contact_phones ON v_contact_phones.contact_uuid = v_contacts.contact_uuid "; - sql = sql .. "INNER JOIN v_destinations ON v_destinations.domain_uuid = v_contacts.domain_uuid "; - sql = sql .. "WHERE v_contact_phones.phone_number = '"..caller.."' AND v_destinations.destination_number='"..callee.."'"; + dbh:query(sql, params, function(row) + name = row.name; + end); - if (debug["sql"]) then - freeswitch.consoleLog("notice", "[cidlookup] "..sql.."\n"); - end - status = dbh:query(sql, function(row) - name = row.name; - end); + if (name == nil) then + freeswitch.consoleLog("NOTICE", "[cidlookup] caller name from contacts db is nil\n"); + else + freeswitch.consoleLog("NOTICE", "[cidlookup] caller name from contacts db: "..name.."\n"); + end - if (name == nil) then - freeswitch.consoleLog("NOTICE", "[cidlookup] caller name from contacts db is nil\n"); - else - freeswitch.consoleLog("NOTICE", "[cidlookup] caller name from contacts db: "..name.."\n"); - end +--check if there is a record, if it not then use cidlookup + if ((name == nil) or (string.len(name) == 0)) then + cidlookup_exists = api:executeString("module_exists cidlookup"); + if (cidlookup_exists == "true") then + name = api:executeString("cidlookup " .. caller); + end + end - --check if there is a record, if it doesnt, then use common cidlookup - if ((name == nil) or (string.len(name) == 0)) then - name = api:executeString("cidlookup " .. caller); - end +--set the caller id name + if ((name ~= nil) and (string.len(name) > 0)) then + freeswitch.consoleLog("NOTICE", "[cidlookup] uuid_setvar " .. uuid .. " caller_id_name " .. name); + api:executeString("uuid_setvar " .. uuid .. " caller_id_name " .. name); - freeswitch.consoleLog("NOTICE", "[cidlookup] uuid_setvar " .. uuid .. " caller_id_name " .. name); - api:executeString("uuid_setvar " .. uuid .. " caller_id_name " .. name); - - freeswitch.consoleLog("NOTICE", "[cidlookup] uuid_setvar " .. uuid .. " effective_caller_id_name " .. name); - api:executeString("uuid_setvar " .. uuid .. " effective_caller_id_name " .. name); + freeswitch.consoleLog("NOTICE", "[cidlookup] uuid_setvar " .. uuid .. " effective_caller_id_name " .. name); + api:executeString("uuid_setvar " .. uuid .. " effective_caller_id_name " .. name); + end diff --git a/resources/install/scripts/destination_caller_id.lua b/resources/install/scripts/destination_caller_id.lua index df105bd919..2980872fac 100644 --- a/resources/install/scripts/destination_caller_id.lua +++ b/resources/install/scripts/destination_caller_id.lua @@ -28,8 +28,14 @@ require "resources.functions.config"; --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); + +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end --define the trim function require "resources.functions.trim" @@ -45,11 +51,14 @@ --caller_id_number = session:getVariable("caller_id_number"); --get the destination_number - sql = [[ SELECT * FROM v_destinations - where destination_number like '1]].. outbound_area_code ..[[%']] - freeswitch.consoleLog("notice", "SQL:" .. sql .. "\n"); + sql = "SELECT destination_number FROM v_destinations where destination_number like :destination_number"; + local params = {destination_number = '1'.. outbound_area_code .. '%'}; + if (debug["sql"]) then + freeswitch.consoleLog("notice", "SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); + end + x = 0; - dbh:query(sql, function(row) + dbh:query(sql, params, function(row) destination_number = row.destination_number; --destination_caller_id_name = row.destination_caller_id_name; --destination_caller_id_number = row.destination_caller_id_number; diff --git a/resources/install/scripts/dial_string.lua b/resources/install/scripts/dial_string.lua index 5616d64778..58a7815fe5 100644 --- a/resources/install/scripts/dial_string.lua +++ b/resources/install/scripts/dial_string.lua @@ -37,8 +37,14 @@ require "resources.functions.config"; --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); + +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end if ( session:ready() ) then session:answer(); @@ -86,16 +92,18 @@ if ( session:ready() ) then if (string.len(unique_id) > 0) then sql = "SELECT * FROM v_extensions as e, v_domains as d "; sql = sql .. "WHERE e.domain_uuid = d.domain_uuid "; + local params = {unique_id = unique_id} if (extension == "true") then - sql = sql .. "AND e.extension = '" .. unique_id .."' "; - sql = sql .. "AND e.domain_uuid = '" .. domain_uuid .."' "; + sql = sql .. "AND e.extension = :unique_id "; + sql = sql .. "AND e.domain_uuid = :domain_uuid "; + params.domain_uuid = domain_uuid else - sql = sql .. "AND e.unique_id = '" .. unique_id .."' "; + sql = sql .. "AND e.unique_id = :unique_id "; end if (debug["sql"]) then - freeswitch.consoleLog("NOTICE", "sql: ".. sql .. "\n"); + freeswitch.consoleLog("NOTICE", "[dial_string] SQL: ".. sql .. "; params: " .. json.encode(params) .. "\n"); end - dbh:query(sql, function(row) + dbh:query(sql, params, function(row) db_domain_uuid = row.domain_uuid; db_extension_uuid = row.extension_uuid; db_extension = row.extension; @@ -115,13 +123,18 @@ if ( session:ready() ) then else if (db_domain_uuid ~= nil) then sql = "SELECT * FROM v_voicemails "; - sql = sql .. "WHERE domain_uuid = '" .. db_domain_uuid .."' "; + sql = sql .. "WHERE domain_uuid = :domain_uuid "; + sql = sql .. "AND voicemail_id = :voicemail_id "; + local params = {domain_uuid = db_domain_uuid}; if (tonumber(db_extension) == nil) then - sql = sql .. "AND voicemail_id = '" .. db_number_alias .."' "; + params.voicemail_id = db_number_alias; else - sql = sql .. "AND voicemail_id = '" .. db_extension .."' "; + params.voicemail_id = db_extension; end - dbh:query(sql, function(row) + if (debug["sql"]) then + freeswitch.consoleLog("NOTICE", "[dial_string] SQL: ".. sql .. "; params: " .. json.encode(params) .. "\n"); + end + dbh:query(sql, params, function(row) voicemail_password = row.voicemail_password; end); if (voicemail_password ~= caller_pin_number) then @@ -139,14 +152,20 @@ if ( session:ready() ) then dial_string = [[{sip_invite_domain=]] .. sip_from_host .. [[,presence_id=]] .. sip_from_user .. [[@]] .. sip_from_host .. [[}${sofia_contact(]] .. sip_from_user .. [[@]] .. sip_from_host .. [[)}]]; end sql = "UPDATE v_extensions SET "; - sql = sql .. "dial_string = '" .. dial_string .."', "; - sql = sql .. "dial_user = '" .. sip_from_user .."', "; - sql = sql .. "dial_domain = '" .. sip_from_host .."' "; - sql = sql .. "WHERE extension_uuid = '" .. db_extension_uuid .."' "; + sql = sql .. "dial_string = :dial_string, "; + sql = sql .. "dial_user = :dial_user, "; + sql = sql .. "dial_domain = :dial_domain "; + sql = sql .. "WHERE extension_uuid = :extension_uuid "; + local params = { + dial_string = dial_string; + dial_user = sip_from_user; + dial_domain = sip_from_host; + extension_uuid = db_extension_uuid; + }; if (debug["sql"]) then - freeswitch.consoleLog("NOTICE", "[dial_string] sql: ".. sql .. "\n"); + freeswitch.consoleLog("NOTICE", "[dial_string] SQL: ".. sql .. "; params: " .. json.encode(params) .. "\n"); end - dbh:query(sql); + dbh:query(sql, params); session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/voicemail/vm-saved.wav"); end --remove the dialstring @@ -156,11 +175,12 @@ if ( session:ready() ) then sql = sql .. "dial_string = null, "; sql = sql .. "dial_user = null, "; sql = sql .. "dial_domain = null "; - sql = sql .. "WHERE extension_uuid = '" .. db_extension_uuid .."' "; + sql = sql .. "WHERE extension_uuid = :extension_uuid "; + local params = {extension_uuid = db_extension_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("NOTICE", "[dial_string] sql: ".. sql .. "\n"); + freeswitch.consoleLog("NOTICE", "[dial_string] SQL: ".. sql .. "; params: " .. json.encode(params) .. "\n"); end - dbh:query(sql); + dbh:query(sql, params); session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/voicemail/vm-deleted.wav"); end --toggle the dial string @@ -171,11 +191,12 @@ if ( session:ready() ) then sql = sql .. "dial_string = null, "; sql = sql .. "dial_user = null, "; sql = sql .. "dial_domain = null "; - sql = sql .. "WHERE extension_uuid = '" .. db_extension_uuid .."' "; + sql = sql .. "WHERE extension_uuid = :extension_uuid "; + local params = {extension_uuid = db_extension_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("NOTICE", "[dial_string] sql: ".. sql .. "\n"); + freeswitch.consoleLog("NOTICE", "[dial_string] SQL: ".. sql .. "; params: " .. json.encode(params) .. "\n"); end - dbh:query(sql); + dbh:query(sql, params); session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/voicemail/vm-deleted.wav"); else --if the dial string is empty then set the dial string @@ -183,14 +204,20 @@ if ( session:ready() ) then dial_string = [[{sip_invite_domain=]] .. sip_from_host .. [[,presence_id=]] .. sip_from_user .. [[@]] .. sip_from_host .. [[}${sofia_contact(]] .. sip_from_user .. [[@]] .. sip_from_host .. [[)}]]; end sql = "UPDATE v_extensions SET "; - sql = sql .. "dial_string = '" .. dial_string .."', "; - sql = sql .. "dial_user = '" .. sip_from_user .."', "; - sql = sql .. "dial_domain = '" .. sip_from_host .."' "; - sql = sql .. "WHERE extension_uuid = '" .. db_extension_uuid .."' "; + sql = sql .. "dial_string = :dial_string, "; + sql = sql .. "dial_user = :dial_user, "; + sql = sql .. "dial_domain = :dial_domain "; + sql = sql .. "WHERE extension_uuid = :extension_uuid "; + local params = { + dial_string = dial_string; + dial_user = sip_from_user; + dial_domain = sip_from_host; + extension_uuid = db_extension_uuid; + }; if (debug["sql"]) then - freeswitch.consoleLog("NOTICE", "[dial_string] sql: ".. sql .. "\n"); + freeswitch.consoleLog("NOTICE", "[dial_string] SQL: ".. sql .. "; params: " .. json.encode(params) .. "\n"); end - dbh:query(sql); + dbh:query(sql, params); session:streamFile(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/voicemail/vm-saved.wav"); end end diff --git a/resources/install/scripts/directory.lua b/resources/install/scripts/directory.lua index b0e2f2bf69..45fcdcfef2 100644 --- a/resources/install/scripts/directory.lua +++ b/resources/install/scripts/directory.lua @@ -36,8 +36,14 @@ require "resources.functions.config"; --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); + +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end --include functions require "resources.functions.format_ringback" @@ -91,7 +97,7 @@ --get the domain info domain_name = session:getVariable("domain_name"); domain_uuid = session:getVariable("domain_uuid"); - + --get the timeout destination timeout_destination = session:getVariable("timeout_destination"); @@ -126,12 +132,13 @@ --get the domain_uuid if (domain_uuid == nil) then if (domain_name ~= nil) then - sql = "SELECT domain_uuid FROM v_domains "; - sql = sql .. "WHERE domain_name = '" .. domain_name .."' "; + local sql = "SELECT domain_uuid FROM v_domains "; + sql = sql .. "WHERE domain_name = :domain_name"; + local params = {domain_name = domain_name}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[conference] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[directory] SQL: " .. sql .. "; params: " .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(rows) + dbh:query(sql, params, function(rows) domain_uuid = string.lower(rows["domain_uuid"]); end); end @@ -226,16 +233,16 @@ if (row.first_name) then --play the recorded name if (storage_type == "base64") then - local Database = require "resources.functions.database"; local dbh = Database.new('system', 'base64/read') - sql = [[SELECT * FROM v_voicemails - WHERE domain_uuid = ']] .. domain_uuid ..[[' - AND voicemail_id = ']].. row.extension.. [[' ]]; + local sql = [[SELECT * FROM v_voicemails + WHERE domain_uuid = :domain_uuid + AND voicemail_id = :voicemail_id]]; + local params = {domain_uuid = domain_uuid, voicemail_id = row.extension}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[directory] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[directory] SQL: " .. sql .. "; params: " .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(field) + dbh:query(sql, params, function(field) --set the voicemail message path file_location = voicemail_dir.."/"..row.extension.."/recorded_name.wav"; @@ -327,13 +334,14 @@ end --get the extensions from the database - sql = "SELECT * FROM v_extensions WHERE domain_uuid = '" .. domain_uuid .. "' AND enabled = 'true' AND (directory_visible is null or directory_visible = 'true'); "; + local sql = "SELECT * FROM v_extensions WHERE domain_uuid = :domain_uuid AND enabled = 'true' AND (directory_visible is null or directory_visible = 'true'); "; + local params = {domain_uuid = domain_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[directory] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[directory] SQL: " .. sql .. "; params: " .. json.encode(params) .. "\n"); end x = 1; directory = {} - dbh:query(sql, function(row) + dbh:query(sql, params, function(row) --show all key value pairs --for key, val in pairs(row) do -- freeswitch.consoleLog("notice", "[directory] Key: " .. key .. " Value: " .. val .. "\n"); diff --git a/resources/install/scripts/disa.callback.loopback.lua b/resources/install/scripts/disa.callback.loopback.lua index 6692c130be..2cd2181f61 100644 --- a/resources/install/scripts/disa.callback.loopback.lua +++ b/resources/install/scripts/disa.callback.loopback.lua @@ -23,15 +23,18 @@ -- Mark J Crane -- Luis Daniel Lucio Quiroz ---debug - debug["sql"] = true; - --include config.lua require "resources.functions.config"; --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); + +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end api = freeswitch.API(); @@ -41,14 +44,14 @@ context = argv[3]; accountcode = argv[4]; t_started = os.time(); -sql = "SELECT domain_uuid FROM v_domains WHERE domain_name='"..context.."'"; +local sql = "SELECT domain_uuid FROM v_domains WHERE domain_name=:context"; +local params = {context = context}; if (debug["sql"]) then - freeswitch.consoleLog("debug", "[disa.callback] "..sql.."\n"); + freeswitch.consoleLog("debug", "[disa.callback] SQL: "..sql.."; params: " .. json.encode(params) .. "\n"); end - -status = dbh:query(sql, function(row) +dbh:query(sql, params, function(row) domain_uuid = row.domain_uuid; - end); +end); a_dialstring = "{direction=outbound,origination_caller_id_number=*3472,outbound_caller_id_number=*3472,call_timeout=30,context="..context..",domain_name="..context..",domain="..context..",accountcode="..accountcode..",domain_uuid="..domain_uuid.."}loopback/"..aleg_number.."/"..context; freeswitch.consoleLog("info", "[disa.callback] a_dialstring " .. a_dialstring .. "\n"); diff --git a/resources/install/scripts/disa.callback.lua b/resources/install/scripts/disa.callback.lua index 336e7a8da7..c215ca2059 100644 --- a/resources/install/scripts/disa.callback.lua +++ b/resources/install/scripts/disa.callback.lua @@ -23,15 +23,18 @@ -- Mark J Crane -- Luis Daniel Lucio Quiroz ---debug - debug["sql"] = false; - --include config.lua require "resources.functions.config"; --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); + +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end api = freeswitch.API(); @@ -44,14 +47,14 @@ context = argv[3]; accountcode = argv[4]; t_started = os.time(); -sql = "SELECT domain_uuid FROM v_domains WHERE domain_name='"..context.."'"; +local sql = "SELECT domain_uuid FROM v_domains WHERE domain_name=:context"; +local params = {context = context}; if (debug["sql"]) then - freeswitch.consoleLog("debug", "[disa.callback] "..sql.."\n"); + freeswitch.consoleLog("debug", "[disa.callback] SQL: "..sql.."; params: " .. json.encode(params) .. "\n"); end - -status = dbh:query(sql, function(row) +dbh:query(sql, params, function(row) domain_uuid = row.domain_uuid; - end); +end); cmd = "user_exists id ".. aleg_number .." "..context; a_user_exists = trim(api:executeString(cmd)); @@ -63,8 +66,8 @@ if (a_user_exists == "true") then extension_uuid = trim(api:executeString(cmd)); a_dialstring = "[origination_caller_id_number=*3472,outbound_caller_id_number=*3472,call_timeout=30,context="..context..",sip_invite_domain="..context..",domain_name="..context..",domain="..context..",accountcode="..accountcode..",domain_uuid="..domain_uuid.."]user/"..aleg_number.."@"..context; else - sql = [[select * from v_dialplans as d, v_dialplan_details as s - where (d.domain_uuid = ']] .. domain_uuid .. [[' or d.domain_uuid is null) + local sql = [[select * from v_dialplans as d, v_dialplan_details as s + where (d.domain_uuid = :domain_uuid or d.domain_uuid is null) and d.app_uuid = '8c914ec3-9fc0-8ab5-4cda-6c9288bdc9a3' and d.dialplan_enabled = 'true' and d.dialplan_uuid = s.dialplan_uuid @@ -79,15 +82,16 @@ else WHEN 'anti-action' THEN 3 ELSE 100 END, s.dialplan_detail_order asc ]] + local params = {domain_uuid = domain_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[disa ] sql for dialplans:" .. sql .. "\n"); + freeswitch.consoleLog("notice", "[disa ] sql for dialplans:" .. sql .. "; params: " .. json.encode(params) .. "\n"); end dialplans = {}; x = 1; - assert(dbh:query(sql, function(row) + assert(dbh:query(sql, params, function(row) dialplans[x] = row; x = x + 1; - end)); + end)); y = 0; previous_dialplan_uuid = ''; @@ -176,8 +180,8 @@ if session1:ready() and session1:answered() then extension_uuid = trim(api:executeString(cmd)); b_dialstring = "[origination_caller_id_number=*3472,outbound_caller_id_number=*3472,call_timeout=30,context="..context..",sip_invite_domain="..context..",domain_name="..context..",domain="..context..",accountcode="..accountcode..",domain_uuid="..domain_uuid.."]user/"..bleg_number.."@"..context; else - sql = [[select * from v_dialplans as d, v_dialplan_details as s - where (d.domain_uuid = ']] .. domain_uuid .. [[' or d.domain_uuid is null) + local sql = [[select * from v_dialplans as d, v_dialplan_details as s + where (d.domain_uuid = :domain_uuid or d.domain_uuid is null) and d.app_uuid = '8c914ec3-9fc0-8ab5-4cda-6c9288bdc9a3' and d.dialplan_enabled = 'true' and d.dialplan_uuid = s.dialplan_uuid @@ -192,12 +196,13 @@ if session1:ready() and session1:answered() then WHEN 'anti-action' THEN 3 ELSE 100 END, s.dialplan_detail_order asc ]] + local params = {domain_uuid = domain_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[disa ] sql for dialplans:" .. sql .. "\n"); + freeswitch.consoleLog("notice", "[disa ] sql for dialplans:" .. sql .. "; params: " .. json.encode(params) .. "\n"); end dialplans = {}; x = 1; - assert(dbh:query(sql, function(row) + assert(dbh:query(sql, params, function(row) dialplans[x] = row; x = x + 1; end)); diff --git a/resources/install/scripts/disa.plus.lua b/resources/install/scripts/disa.plus.lua index 4f92687686..7da02b87ee 100644 --- a/resources/install/scripts/disa.plus.lua +++ b/resources/install/scripts/disa.plus.lua @@ -34,8 +34,14 @@ digit_timeout = "5000"; require "resources.functions.config"; --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); + +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end api = freeswitch.API(); @@ -134,15 +140,14 @@ if ( session:ready() ) then --if pinless then look the caller number in contacts if (pinless) then -- look the caller number - sql = "select v_contacts.* from v_contacts inner join v_contact_settings s1 using (contact_uuid) where s1.contact_setting_category = 'calling card' and s1.contact_setting_subcategory='pinless' and s1.contact_setting_name='phonenumber' and s1.contact_setting_value='"..caller_id_number.."'"; - - status = dbh:query(sql, function(row) - domain_uuid = row.domain_uuid; + local sql = "select v_contacts.* from v_contacts inner join v_contact_settings s1 using (contact_uuid) where s1.contact_setting_category = 'calling card' and s1.contact_setting_subcategory='pinless' and s1.contact_setting_name='phonenumber' and s1.contact_setting_value=:caller_id_number"; + local params = {caller_id_number = caller_id_number}; + dbh:query(sql, params, function(row) + domain_uuid = row.domain_uuid; contact_uuid = row.contact_uuid; freeswitch.consoleLog("NOTICE", "[disa] domain_uuid "..row.domain_uuid.."\n"); freeswitch.consoleLog("NOTICE", "[disa] contact_uuid "..row.contact_uuid.."\n"); end); - else --else if the pin number is provided then require it @@ -156,6 +161,7 @@ if ( session:ready() ) then pin_digits = session:playAndGetDigits(pin_min_length, pin_max_length, max_tries, digit_timeout, "#", sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/"..sound_pin, "", "\\d+"); freeswitch.consoleLog("notice", "[disa] pig_digits "..pin_digits.."\n"); + local sql, params; if (pin_number) then --pin number is fixed freeswitch.consoleLog("notice", "[disa] pin_number "..pin_number.."\n"); @@ -168,18 +174,20 @@ if ( session:ready() ) then session:hangup("NORMAL_CLEARING"); return; end - sql = "select v_contacts.* from v_contacts inner join v_contact_settings s1 using (contact_uuid) where s1.contact_setting_category = 'calling card' and s1.contact_setting_subcategory='authentication' and s1.contact_setting_name='username' and s1.contact_setting_value='"..reference_number.."'"; + sql = "select v_contacts.* from v_contacts inner join v_contact_settings s1 using (contact_uuid) where s1.contact_setting_category = 'calling card' and s1.contact_setting_subcategory='authentication' and s1.contact_setting_name='username' and s1.contact_setting_value=:reference_number"; + params = {reference_number = reference_number}; else - sql = "select v_contacts.* from v_contacts inner join v_contact_settings s1 using (contact_uuid) inner join v_contact_settings s2 using (contact_uuid) where s1.contact_setting_category = 'calling card' and s1.contact_setting_subcategory='authentication' and s1.contact_setting_name='username' and s1.contact_setting_value='"..reference_number.."' and s2.contact_setting_category='calling card' and s2.contact_setting_subcategory='authentication' and s2.contact_setting_name='password' and s2.contact_setting_value='"..pin_digits.."'"; + sql = "select v_contacts.* from v_contacts inner join v_contact_settings s1 using (contact_uuid) inner join v_contact_settings s2 using (contact_uuid) where s1.contact_setting_category = 'calling card' and s1.contact_setting_subcategory='authentication' and s1.contact_setting_name='username' and s1.contact_setting_value=:reference_number and s2.contact_setting_category='calling card' and s2.contact_setting_subcategory='authentication' and s2.contact_setting_name='password' and s2.contact_setting_value=:pin_digits"; + params = {reference_number = reference_number, pin_digits = pin_digits}; end -- look in db for correct pin number if (debug["sql"]) then - freeswitch.consoleLog("notice", "[disa] "..sql.."\n"); + freeswitch.consoleLog("notice", "[disa] SQL: "..sql.."; params: " .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(row) - domain_uuid = row.domain_uuid; + dbh:query(sql, params, function(row) + domain_uuid = row.domain_uuid; contact_uuid = row.contact_uuid; freeswitch.consoleLog("NOTICE", "[disa] domain_uuid "..row.domain_uuid.."\n"); freeswitch.consoleLog("NOTICE", "[disa] contact_uuid "..row.contact_uuid.."\n"); diff --git a/resources/install/scripts/do_not_disturb.lua b/resources/install/scripts/do_not_disturb.lua index 9cf853de80..25d62957fe 100644 --- a/resources/install/scripts/do_not_disturb.lua +++ b/resources/install/scripts/do_not_disturb.lua @@ -16,7 +16,7 @@ -- -- The Initial Developer of the Original Code is -- Mark J Crane --- Copyright (C) 2010-2014 +-- Copyright (C) 2010-2016 -- the Initial Developer. All Rights Reserved. -- -- Contributor(s): @@ -70,25 +70,42 @@ session:sleep(1000); --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); + + --include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end --determine whether to update the dial string - sql = "select * from v_extensions "; - sql = sql .. "where domain_uuid = '"..domain_uuid.."' "; - sql = sql .. "and extension_uuid = '"..extension_uuid.."' "; + local sql = "select * from v_extensions "; + sql = sql .. "where domain_uuid = :domain_uuid "; + sql = sql .. "and extension_uuid = :extension_uuid "; + local params = {domain_uuid = domain_uuid, extension_uuid = extension_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[do_not_disturb] "..sql.."\n"); + freeswitch.consoleLog("notice", "[do_not_disturb] " .. sql .. "; params:" .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(row) + dbh:query(sql, params, function(row) extension = row.extension; number_alias = row.number_alias or ''; accountcode = row.accountcode; follow_me_uuid = row.follow_me_uuid; + do_not_disturb = row.do_not_disturb; --freeswitch.consoleLog("NOTICE", "[do_not_disturb] extension "..row.extension.."\n"); --freeswitch.consoleLog("NOTICE", "[do_not_disturb] accountcode "..row.accountcode.."\n"); end); + --toggle do not disturb + if (enabled == "toggle") then + if (do_not_disturb == "true") then + enabled = "false"; + else + enabled = "true"; + end + end + --set the dial string if (enabled == "true") then local user = (number_alias and #number_alias > 0) and number_alias or extension; @@ -114,43 +131,46 @@ --disable follow me if (follow_me_uuid ~= nil) then if (string.len(follow_me_uuid) > 0 and enabled == "true") then - sql = "update v_follow_me set "; + local sql = "update v_follow_me set "; sql = sql .. "follow_me_enabled = 'false' "; - sql = sql .. "where domain_uuid = '"..domain_uuid.."' "; - sql = sql .. "and follow_me_uuid = '"..follow_me_uuid.."' "; + sql = sql .. "where domain_uuid = :domain_uuid "; + sql = sql .. "and follow_me_uuid = :follow_me_uuid "; + local params = {domain_uuid = domain_uuid, follow_me_uuid = follow_me_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[do_not_disturb] "..sql.."\n"); + freeswitch.consoleLog("notice", "[do_not_disturb] "..sql.."; params:" .. json.encode(params) .. "\n"); end - dbh:query(sql); + dbh:query(sql, params); end end --update the extension sql = "update v_extensions set "; if (enabled == "true") then - sql = sql .. "dial_string = '"..dial_string.."', "; + sql = sql .. "dial_string = :dial_string, "; sql = sql .. "do_not_disturb = 'true', "; else sql = sql .. "dial_string = null, "; sql = sql .. "do_not_disturb = 'false', "; end sql = sql .. "forward_all_enabled = 'false' "; - sql = sql .. "where domain_uuid = '"..domain_uuid.."' "; - sql = sql .. "and extension_uuid = '"..extension_uuid.."' "; + sql = sql .. "where domain_uuid = :domain_uuid "; + sql = sql .. "and extension_uuid = :extension_uuid "; + local params = {dial_string = dial_string, domain_uuid = domain_uuid, extension_uuid = extension_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[do_not_disturb] "..sql.."\n"); + freeswitch.consoleLog("notice", "[do_not_disturb] "..sql.."; params:" .. json.encode(params) .. "\n"); end - dbh:query(sql); + dbh:query(sql, params); --determine whether to update the dial string sql = "select * from v_extension_users as e, v_users as u "; - sql = sql .. "where e.extension_uuid = '"..extension_uuid.."' "; + sql = sql .. "where e.extension_uuid = :extension_uuid "; sql = sql .. "and e.user_uuid = u.user_uuid "; - sql = sql .. "and e.domain_uuid = '"..domain_uuid.."' "; + sql = sql .. "and e.domain_uuid = :domain_uuid "; + local params = {domain_uuid = domain_uuid, extension_uuid = extension_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[do_not_disturb] "..sql.."\n"); + freeswitch.consoleLog("notice", "[do_not_disturb] "..sql.."; params:" .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(row) + dbh:query(sql, params, function(row) --update the call center status if (enabled == "true") then user_status = "Logged Out"; @@ -163,14 +183,15 @@ else user_status = "Available"; end - sql = "update v_users set "; - sql = sql .. "user_status = '"..user_status.."' "; - sql = sql .. "where domain_uuid = '"..domain_uuid.."' "; - sql = sql .. "and user_uuid = '"..row.user_uuid.."' "; + local sql = "update v_users set "; + sql = sql .. "user_status = :user_status "; + sql = sql .. "where domain_uuid = :domain_uuid "; + sql = sql .. "and user_uuid = :user_uuid "; + local params = {user_status = user_status, domain_uuid = domain_uuid, user_uuid = row.user_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[do_not_disturb] "..sql.."\n"); + freeswitch.consoleLog("notice", "[do_not_disturb] "..sql.."; params:" .. json.encode(params) .. "\n"); end - dbh:query(sql); + dbh:query(sql, params); end); --clear the cache diff --git a/resources/install/scripts/eavesdrop.lua b/resources/install/scripts/eavesdrop.lua index 9799795fd9..9c70d7bae2 100644 --- a/resources/install/scripts/eavesdrop.lua +++ b/resources/install/scripts/eavesdrop.lua @@ -36,14 +36,13 @@ require "resources.functions.file_exists"; --connect to the database - if (file_exists(database_dir.."/core.db")) then - --dbh = freeswitch.Dbh("core:core"); -- when using sqlite - dbh = freeswitch.Dbh("sqlite://"..database_dir.."/core.db"); - freeswitch.consoleLog("NOTICE", "[eavesdrop] using core.db\n"); - else - require "resources.functions.database_handle"; - dbh = database_handle('switch'); - freeswitch.consoleLog("NOTICE", "[eavesdrop] using the database\n"); + local Database = require "resources.functions.database" + local dbh = Database.new('switch') + +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" end --exits the script if we didn't connect properly @@ -110,9 +109,12 @@ --check the database to get the uuid to eavesdrop on if (session:ready()) then - sql = "select uuid from channels where presence_id = '"..extension.."@"..domain_name.."' "; - freeswitch.consoleLog("NOTICE", "[eavesdrop] sql "..sql.."\n"); - dbh:query(sql, function(result) + local sql = "select uuid from channels where presence_id = :presence_id "; + local params = {presence_id = extension.."@"..domain_name}; + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[eavesdrop] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); + end + dbh:query(sql, params, function(result) for key, val in pairs(result) do freeswitch.consoleLog("NOTICE", "[eavesdrop] result "..key.." "..val.."\n"); end diff --git a/resources/install/scripts/extension_queue.lua b/resources/install/scripts/extension_queue.lua index 12d3a96269..6cf2806567 100644 --- a/resources/install/scripts/extension_queue.lua +++ b/resources/install/scripts/extension_queue.lua @@ -26,10 +26,6 @@ --include config.lua require "resources.functions.config"; ---connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); - if (session:ready()) then fifo_simo = session:getVariable("fifo_simo"); if (not fifo_simo) then fifo_simo = '1'; end diff --git a/resources/install/scripts/fax_retry.lua b/resources/install/scripts/fax_retry.lua index 51701c506d..9e06257b29 100644 --- a/resources/install/scripts/fax_retry.lua +++ b/resources/install/scripts/fax_retry.lua @@ -34,8 +34,14 @@ require "resources.functions.config"; --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); + +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end --define the explode function require "resources.functions.explode"; @@ -117,9 +123,9 @@ --get the domain_uuid using the domain name required for multi-tenant if (domain_uuid == nil and domain_name ~= nil) then - sql = "SELECT domain_uuid FROM v_domains "; - sql = sql .. "WHERE domain_name = '" .. domain_name .. "' "; - status = dbh:query(sql, function(rows) + local sql = "SELECT domain_uuid FROM v_domains "; + sql = sql .. "WHERE domain_name = :domain_name "; + dbh:query(sql, {domain_name = domain_name}, function(rows) domain_uuid = rows["domain_uuid"]; end); end @@ -152,10 +158,11 @@ --get the domain_uuid using the domain name required for multi-tenant if (domain_uuid ~= nil and fax_extension ~= nil) then - sql = "SELECT fax_uuid FROM v_fax "; - sql = sql .. "WHERE domain_uuid = '" .. domain_uuid .. "' "; - sql = sql .. "AND fax_extension = '" .. fax_extension .. "' "; - status = dbh:query(sql, function(rows) + local sql = "SELECT fax_uuid FROM v_fax "; + sql = sql .. "WHERE domain_uuid = :domain_uuid "; + sql = sql .. "AND fax_extension = :fax_extension "; + local params = {domain_uuid = domain_uuid, fax_extension = fax_extension} + dbh:query(sql, params, function(rows) fax_uuid = rows["fax_uuid"]; end); end @@ -207,71 +214,88 @@ sql = sql .. ") "; sql = sql .. "values "; sql = sql .. "("; - sql = sql .. "'"..uuid.."', "; - sql = sql .. "'"..domain_uuid.."', "; + sql = sql .. ":uuid, "; + sql = sql .. ":domain_uuid, "; if (fax_uuid ~= nil) then - sql = sql .. "'"..fax_uuid.."', "; + sql = sql .. ":fax_uuid, "; end - sql = sql .. "'"..fax_success.."', "; - sql = sql .. "'"..fax_result_code .."', "; - sql = sql .. "'"..fax_result_text.."', "; - sql = sql .. "'"..fax_file.."', "; + sql = sql .. ":fax_success, "; + sql = sql .. ":fax_result_code, "; + sql = sql .. ":fax_result_text, "; + sql = sql .. ":fax_file, "; if (fax_ecm_used ~= nil) then - sql = sql .. "'"..fax_ecm_used.."', "; + sql = sql .. ":fax_ecm_used, "; end if (fax_local_station_id ~= nil) then - sql = sql .. "'"..fax_local_station_id.."', "; - end - if (fax_document_transferred_pages == nil) then - sql = sql .. "'0', "; - else - sql = sql .. "'"..fax_document_transferred_pages.."', "; - end - if (fax_document_total_pages == nil) then - sql = sql .. "'0', "; - else - sql = sql .. "'"..fax_document_total_pages.."', "; + sql = sql .. ":fax_local_station_id, "; end + sql = sql .. ":fax_document_transferred_pages, "; + sql = sql .. ":fax_document_total_pages, "; if (fax_image_resolution ~= nil) then - sql = sql .. "'"..fax_image_resolution.."', "; + sql = sql .. ":fax_image_resolution, "; end if (fax_image_size ~= nil) then - sql = sql .. "'"..fax_image_size.."', "; + sql = sql .. ":fax_image_size, "; end if (fax_bad_rows ~= nil) then - sql = sql .. "'"..fax_bad_rows.."', "; + sql = sql .. ":fax_bad_rows, "; end if (fax_transfer_rate ~= nil) then - sql = sql .. "'"..fax_transfer_rate.."', "; + sql = sql .. ":fax_transfer_rate, "; end if (fax_retry_attempts ~= nil) then - sql = sql .. "'"..fax_retry_attempts.."', "; + sql = sql .. ":fax_retry_attempts, "; end if (fax_retry_limit ~= nil) then - sql = sql .. "'"..fax_retry_limit.."', "; + sql = sql .. ":fax_retry_limit, "; end if (fax_retry_sleep ~= nil) then - sql = sql .. "'"..fax_retry_sleep.."', "; + sql = sql .. ":fax_retry_sleep, "; end - sql = sql .. "'"..fax_uri.."', "; + sql = sql .. ":fax_uri, "; if (database["type"] == "sqlite") then - sql = sql .. "'"..os.date("%Y-%m-%d %X").."', "; + sql = sql .. ":fax_date, "; else sql = sql .. "now(), "; end - sql = sql .. "'"..os.time().."' "; + sql = sql .. ":fax_time "; sql = sql .. ")"; - --if (debug["sql"]) then - freeswitch.consoleLog("notice", "[FAX] retry: "..sql.."\n"); - --end - dbh:query(sql); + + local params = { + uuid = uuid; + domain_uuid = domain_uuid; + fax_uuid = fax_uuid; + fax_success = fax_success; + fax_result_code = fax_result_code; + fax_result_text = fax_result_text; + fax_file = fax_file; + fax_ecm_used = fax_ecm_used; + fax_local_station_id = fax_local_station_id; + fax_document_transferred_pages = fax_document_transferred_pages or '0'; + fax_document_total_pages = fax_document_total_pages or '0'; + fax_image_resolution = fax_image_resolution; + fax_image_size = fax_image_size; + fax_bad_rows = fax_bad_rows; + fax_transfer_rate = fax_transfer_rate; + fax_retry_attempts = fax_retry_attempts; + fax_retry_limit = fax_retry_limit; + fax_retry_sleep = fax_retry_sleep; + fax_uri = fax_uri; + fax_date = os.date("%Y-%m-%d %X"); + fax_time = os.time(); + }; + + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[FAX] retry: " .. sql .. "; params:" .. json.encode(params) .. "\n"); + end + dbh:query(sql, params); --for email email_address = env:getHeader("mailto_address"); --email_address = api:execute("system", "/bin/echo -n "..email_address.." | /bin/sed -e s/\,/\\\\,/g"); - --if (not email_address) then - -- email_address = ''; - --end + if (not email_address) then + email_address = ''; + end email_address = email_address:gsub(",", "\\,"); from_address = env:getHeader("mailfrom_address"); if (from_address == nil) then @@ -292,6 +316,7 @@ end end + local fax_base64 if (storage_type == "base64") then --include the file io local file = require "resources.functions.file" @@ -322,39 +347,52 @@ table.insert(sql, ") "); table.insert(sql, "values "); table.insert(sql, "("); - table.insert(sql, "'" .. uuid .. "', "); - table.insert(sql, "'" .. fax_uuid .. "', "); + table.insert(sql, ":uuid, "); + table.insert(sql, ":fax_uuid, "); table.insert(sql, "'tx', "); if (sip_to_user ~= nil) then - table.insert(sql, "'" .. sip_to_user .. "', "); + table.insert(sql, ":sip_to_user, "); end table.insert(sql, "'tif', "); - fax_file = string.gsub(fax_file, '/temp/', '/sent/'); - table.insert(sql, "'" .. fax_file .. "', "); - table.insert(sql, "'" .. origination_caller_id_name .. "', "); - table.insert(sql, "'" .. origination_caller_id_number .. "', "); + table.insert(sql, ":fax_file, "); + table.insert(sql, ":origination_caller_id_name, "); + table.insert(sql, ":origination_caller_id_number, "); if (database["type"] == "sqlite") then - table.insert(sql, "'"..os.date("%Y-%m-%d %X").."', "); + table.insert(sql, ":fax_date, "); else table.insert(sql, "now(), "); end - table.insert(sql, "'" .. os.time() .. "', "); + table.insert(sql, ":fax_time, "); if (storage_type == "base64") then - table.insert(sql, "'" .. fax_base64 .. "', "); + table.insert(sql, ":fax_base64, "); end - table.insert(sql, "'" .. domain_uuid .. "'"); + table.insert(sql, ":domain_uuid "); table.insert(sql, ")"); + sql = table.concat(sql, "\n"); - --if (debug["sql"]) then - freeswitch.consoleLog("notice", "[FAX] SQL: " .. sql .. "\n"); - --end + + local params = { + uuid = uuid; + fax_uuid = fax_uuid; + sip_to_user = sip_to_user; + fax_file = string.gsub(fax_file, '/temp/', '/sent/'); + origination_caller_id_name = origination_caller_id_name; + origination_caller_id_number = origination_caller_id_number; + fax_date = os.date("%Y-%m-%d %X"); + fax_time = os.time(); + fax_base64 = fax_base64; + domain_uuid = domain_uuid; + } + + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[FAX] SQL: " .. sql .. "; params:" .. json.encode(params) .. "\n"); + end if (storage_type == "base64") then - local Database = require "resources.functions.database" local dbh = Database.new('system', 'base64'); - dbh:query(sql); + dbh:query(sql, params); dbh:release(); else - result = dbh:query(sql); + dbh:query(sql, params); end end end diff --git a/resources/install/scripts/follow_me.lua b/resources/install/scripts/follow_me.lua index ee1a267672..5dfcad5304 100644 --- a/resources/install/scripts/follow_me.lua +++ b/resources/install/scripts/follow_me.lua @@ -32,6 +32,10 @@ local log = require "resources.functions.log".follow_me local cache = require "resources.functions.cache" local Database = require "resources.functions.database" + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end --check if the session is ready if not session:ready() then return end @@ -62,13 +66,14 @@ --determine whether to update the dial string local sql = "select extension, number_alias, accountcode, follow_me_uuid "; sql = sql .. "from v_extensions "; - sql = sql .. "where domain_uuid = '"..domain_uuid.."' "; - sql = sql .. "and extension_uuid = '"..extension_uuid.."' "; + sql = sql .. "where domain_uuid = :domain_uuid "; + sql = sql .. "and extension_uuid = :extension_uuid "; + local params = {domain_uuid=domain_uuid, extension_uuid=extension_uuid}; if (debug["sql"]) then - log.notice(sql); + log.notice("SQL: %s; params: %s", sql, json.encode(params)); end - local row = dbh:first_row(sql) + local row = dbh:first_row(sql, params) if not row then return end local extension = row.extension; @@ -79,13 +84,14 @@ --determine whether to update the dial string sql = "select follow_me_enabled, call_prompt, cid_name_prefix, cid_number_prefix, dial_string " sql = sql .. "from v_follow_me "; - sql = sql .. "where domain_uuid = '"..domain_uuid.."' "; - sql = sql .. "and follow_me_uuid = '"..follow_me_uuid.."' "; + sql = sql .. "where domain_uuid = :domain_uuid "; + sql = sql .. "and follow_me_uuid = :follow_me_uuid "; + local params = {domain_uuid=domain_uuid, follow_me_uuid=follow_me_uuid}; if (debug["sql"]) then - log.notice(sql); + log.notice("SQL: %s; params: %s", sql, json.encode(params)); end - row = dbh:first_row(sql) + row = dbh:first_row(sql, params) if not row then return end local enabled = row.follow_me_enabled; @@ -123,28 +129,30 @@ else sql = sql .. "follow_me_enabled = 'true' "; end - sql = sql .. "where domain_uuid = '"..domain_uuid.."' "; - sql = sql .. "and follow_me_uuid = '"..follow_me_uuid.."' "; + sql = sql .. "where domain_uuid = :domain_uuid "; + sql = sql .. "and follow_me_uuid = :follow_me_uuid "; + local params = {domain_uuid=domain_uuid, follow_me_uuid=follow_me_uuid}; if (debug["sql"]) then - log.notice(sql); + log.notice("SQL: %s; params: %s", sql, json.encode(params)); end - dbh:query(sql); + dbh:query(sql, params); --update the extension sql = "update v_extensions set "; if (enabled == "true") then sql = sql .. "dial_string = null, "; else - sql = sql .. "dial_string = '"..dial_string:gsub("'", "''").."', "; + sql = sql .. "dial_string = :dial_string, "; end sql = sql .. "do_not_disturb = 'false', "; sql = sql .. "forward_all_enabled= 'false' "; - sql = sql .. "where domain_uuid = '"..domain_uuid.."' "; - sql = sql .. "and extension_uuid = '"..extension_uuid.."' "; + sql = sql .. "where domain_uuid = :domain_uuid "; + sql = sql .. "and extension_uuid = :extension_uuid "; + local params = {domain_uuid=domain_uuid, extension_uuid=extension_uuid, dial_string = dial_string}; if (debug["sql"]) then - log.notice(sql); + log.notice("SQL: %s; params: %s", sql, json.encode(params)); end - dbh:query(sql); + dbh:query(sql, params); --clear the cache if (extension ~= nil) and cache.support() then diff --git a/resources/install/scripts/intercept.lua b/resources/install/scripts/intercept.lua index 689dc79b9b..6e412de0e7 100644 --- a/resources/install/scripts/intercept.lua +++ b/resources/install/scripts/intercept.lua @@ -30,9 +30,6 @@ -- we can use any number because other box should check sip_h_X_*** headers first local pickup_number = '*8' -- extension and '**' or '*8' ---set the debug options - debug["sql"] = false; - --include config.lua require "resources.functions.config"; @@ -50,6 +47,12 @@ --include database class local Database = require "resources.functions.database" +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end + --get the hostname local hostname = trim(api:execute("switchname", "")); @@ -165,34 +168,40 @@ --get the call groups the extension is a member of local sql = "SELECT call_group FROM v_extensions "; - sql = sql .. "WHERE domain_uuid = '"..domain_uuid.."' "; - sql = sql .. "AND (extension = '"..caller_id_number.."'"; - sql = sql .. "OR number_alias = '"..caller_id_number.."')"; + sql = sql .. "WHERE domain_uuid = :domain_uuid "; + sql = sql .. "AND (extension = :caller_id_number "; + sql = sql .. "OR number_alias = :caller_id_number)"; sql = sql .. "limit 1"; - local call_group = dbh:first_value(sql) or '' + local params = {domain_uuid = domain_uuid, caller_id_number = caller_id_number}; + if (debug["sql"]) then + log.noticef("SQL: %s; params: %s", sql, json.encode(params)); + end + local call_group = dbh:first_value(sql, params) or '' log.noticef("call_group: `%s`", call_group); call_groups = explode(",", call_group); + params = {domain_uuid = domain_uuid}; + --get the extensions in the call groups sql = "SELECT extension, number_alias FROM v_extensions "; - sql = sql .. "WHERE domain_uuid = '"..domain_uuid.."' "; + sql = sql .. "WHERE domain_uuid = :domain_uuid "; sql = sql .. "AND ("; for key,call_group in ipairs(call_groups) do - if (key > 1) then - sql = sql .. "OR "; - end - if (#call_group > 0) then - sql = sql .. "call_group like '%"..call_group.."%' "; + if key > 1 then sql = sql .. " OR " end + if #call_group == 0 then + sql = sql .. "call_group = '' or call_group is NULL"; else - sql = sql .. "call_group = '' "; + local param_name = "call_group_" .. tostring(key) + sql = sql .. "call_group like :" .. param_name; + params[param_name] = '%' .. call_group .. '%'; end end sql = sql .. ") "; if (debug["sql"]) then - log.notice("sql "..sql); + log.noticef("SQL: %s; params: %s", sql, json.encode(params)); end local extensions = {} - dbh:query(sql, function(row) + dbh:query(sql, params, function(row) local member = row.extension if row.number_alias and #row.number_alias > 0 then member = row.number_alias @@ -246,14 +255,7 @@ end --connect to FS database - --local dbh = Database.new('switch') - if (file_exists(database_dir.."/core.db")) then - --dbh = freeswitch.Dbh("core:core"); -- when using sqlite - dbh = freeswitch.Dbh("sqlite://"..database_dir.."/core.db"); - else - dofile(scripts_dir.."/resources/functions/database_handle.lua"); - dbh = database_handle('switch'); - end + local dbh = Database.new('switch') --check the database to get the uuid of a ringing call call_hostname = ""; @@ -276,18 +278,21 @@ sql = sql .. ")" end - sql = sql .. "AND (1<>1 "; + sql = sql .. "AND (1<>1"; + local params = {}; for key,extension in pairs(extensions) do - sql = sql .. "OR presence_id = '"..extension.."@"..domain_name.."' "; + local param_name = "presence_id_" .. tostring(key); + sql = sql .. " OR presence_id = :" .. param_name; + params[param_name] = extension.."@"..domain_name; end sql = sql .. ") "; sql = sql .. "and call_uuid is not null "; sql = sql .. "limit 1 "; if (debug["sql"]) then - log.notice("sql "..sql); + log.noticef("SQL: %s; params: %s", sql, json.encode(params)); end local is_child - dbh:query(sql, function(row) + dbh:query(sql, params, function(row) -- for key, val in pairs(row) do -- log.notice("row "..key.." "..val); -- end diff --git a/resources/install/scripts/ivr_menu.lua b/resources/install/scripts/ivr_menu.lua index 654df3bdb8..21fc8f38e9 100644 --- a/resources/install/scripts/ivr_menu.lua +++ b/resources/install/scripts/ivr_menu.lua @@ -40,6 +40,12 @@ --get logger local log = require "resources.functions.log".ivr_menu +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end + --include functions require "resources.functions.format_ringback" require "resources.functions.split" @@ -98,12 +104,13 @@ --get the ivr menu from the database sql = [[SELECT * FROM v_ivr_menus - WHERE ivr_menu_uuid = ']] .. ivr_menu_uuid ..[[' + WHERE ivr_menu_uuid = :ivr_menu_uuid AND ivr_menu_enabled = 'true' ]]; + local params = {ivr_menu_uuid = ivr_menu_uuid}; if (debug["sql"]) then - log.notice("SQL: " .. sql); + log.notice("SQL: " .. sql .. "; params: " .. json.encode(params)); end - dbh:query(sql, function(row) + dbh:query(sql, params, function(row) domain_uuid = row["domain_uuid"]; ivr_menu_name = row["ivr_menu_name"]; --ivr_menu_extension = row["ivr_menu_extension"]; @@ -185,15 +192,17 @@ return full_path end - local sql = [[SELECT * FROM v_recordings WHERE domain_uuid = ']]..domain_uuid.. - [['AND recording_filename = ']]..file_name..[[' ]]; + local sql = "SELECT * FROM v_recordings WHERE domain_uuid = :domain_uuid " + .. "AND recording_filename = :file_name"; + + local params = {domain_uuid = domain_uuid, file_name = file_name}; if (debug["sql"]) then - log.notice("SQL: "..sql); + log.notice("SQL: " .. sql .. "; params: " .. json.encode(params)); end local is_base64 - dbh:query(sql, function(row) + dbh:query(sql, params, function(row) if #row.recording_base64 > 32 then --include the file io local file = require "resources.functions.file" @@ -323,9 +332,12 @@ end --get the ivr menu options - sql = [[SELECT * FROM v_ivr_menu_options WHERE ivr_menu_uuid = ']] .. ivr_menu_uuid ..[[' ORDER BY ivr_menu_option_order asc ]]; + local sql = "SELECT * FROM v_ivr_menu_options " + .. "WHERE ivr_menu_uuid = :ivr_menu_uuid " + .. "ORDER BY ivr_menu_option_order asc "; + local params = {ivr_menu_uuid = ivr_menu_uuid}; if (debug["sql"]) then - log.notice("SQL: " .. sql); + log.notice("SQL: " .. sql .. "; params: " .. json.encode(params)); end --connect to the database @@ -333,7 +345,7 @@ --select actions to execute local actions = {} - dbh:query(sql, function(row) + dbh:query(sql, params, function(row) -- declare vars local action, script, data diff --git a/resources/install/scripts/pin_number.lua b/resources/install/scripts/pin_number.lua index 4858b68e16..3700850094 100644 --- a/resources/install/scripts/pin_number.lua +++ b/resources/install/scripts/pin_number.lua @@ -45,9 +45,12 @@ sounds_dir = session:getVariable("sounds_dir"); --connect to the database - if (pin_number == "database") then - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); + + --include json library + if (debug["sql"]) then + json = require "resources.functions.lunajson" end end @@ -66,12 +69,12 @@ --get the domain_name domain_name = session:getVariable("domain_name"); --get the domain_uuid using the domain_name - sql = [[SELECT domain_name FROM v_domains - WHERE domain_name = ']] .. domain_name ..[[' ]]; + local sql = "SELECT domain_name FROM v_domains WHERE domain_name = :domain_name"; + local params = {domain_name = domain_name}; if (debug["sql"]) then - freeswitch.consoleLog("NOTICE", "SQL: "..sql.."\n"); + freeswitch.consoleLog("NOTICE", "[pin_number] SQL: "..sql.."; params: " .. json.encode(params) .. "\n"); end - dbh:query(sql, function(row) + dbh:query(sql, params, function(row) domain_uuid = row["domain_uuid"]; end); end @@ -83,15 +86,16 @@ --validate the user pin number if (pin_number == "database") then - sql = [[SELECT * FROM v_pin_numbers - WHERE pin_number = ']] .. digits ..[[' - AND domain_uuid = ']] .. domain_uuid .. [[' + local sql = [[SELECT * FROM v_pin_numbers + WHERE pin_number = :digits + AND domain_uuid = :domain_uuid AND enabled = 'true' ]]; + local params = {digits = digits, domain_uuid = domain_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("NOTICE", "SQL: "..sql.."\n"); + freeswitch.consoleLog("NOTICE", "[pin_number] SQL: "..sql.."; params: " .. json.encode(params) .. "\n"); end auth = false; - dbh:query(sql, function(row) + dbh:query(sql, params, function(row) --get the values from the database accountcode = row["accountcode"]; --set the variable to true diff --git a/resources/install/scripts/recordings.lua b/resources/install/scripts/recordings.lua index 7b44bec510..927d52ab26 100644 --- a/resources/install/scripts/recordings.lua +++ b/resources/install/scripts/recordings.lua @@ -37,8 +37,14 @@ require "resources.functions.config"; --connect to the database - require "resources.functions.database_handle"; - dbh = database_handle('system'); + local Database = require "resources.functions.database"; + dbh = Database.new('system'); + +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end --get the domain_uuid domain_uuid = session:getVariable("domain_uuid"); @@ -152,9 +158,9 @@ --delete the previous recording sql = "delete from v_recordings "; - sql = sql .. "where domain_uuid = '".. domain_uuid .. "' "; - sql = sql .. "and recording_filename = '".. recording_name .."'"; - dbh:query(sql); + sql = sql .. "where domain_uuid = :domain_uuid "; + sql = sql .. "and recording_filename = :recording_name"; + dbh:query(sql, {domain_uuid = domain_uuid, recording_name = recording_name}); --get a new uuid recording_uuid = api:execute("create_uuid"); @@ -173,25 +179,34 @@ table.insert(array, ") "); table.insert(array, "VALUES "); table.insert(array, "( "); - table.insert(array, "'"..recording_uuid.."', "); - table.insert(array, "'"..domain_uuid.."', "); - table.insert(array, "'"..recording_name.."', "); + table.insert(array, ":recording_uuid, "); + table.insert(array, ":domain_uuid, "); + table.insert(array, ":recording_name, "); if (storage_type == "base64") then - table.insert(array, "'"..recording_base64.."', "); + table.insert(array, ":recording_base64, "); end - table.insert(array, "'"..recording_name.."' "); + table.insert(array, ":recording_name "); table.insert(array, ") "); sql = table.concat(array, "\n"); + + local params = { + recording_uuid = recording_uuid; + domain_uuid = domain_uuid; + recording_name = recording_name; + recording_base64 = recording_base64; + }; + if (debug["sql"]) then - freeswitch.consoleLog("notice", "[recording] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[recording] SQL: " .. sql .. "; params: " .. json.encode(params) .. "\n"); end + if (storage_type == "base64") then local Database = require "resources.functions.database" local dbh = Database.new('system', 'base64'); - dbh:query(sql); + dbh:query(sql, params); dbh:release(); else - dbh:query(sql); + dbh:query(sql, params); end --preview the recording diff --git a/resources/install/scripts/resources/functions/database.lua b/resources/install/scripts/resources/functions/database.lua index 35c4e1c87f..2f370e4881 100644 --- a/resources/install/scripts/resources/functions/database.lua +++ b/resources/install/scripts/resources/functions/database.lua @@ -19,6 +19,54 @@ BACKEND.main = BACKEND.main or 'native' local unpack = unpack or table.unpack +----------------------------------------------------------- + +local NULL, DEFAULT = {}, {} + +local param_pattern = "[:]([^%d%s][%a%d_]+)" + +-- +-- Substitude named parameters to query +-- +-- @tparam string sql query text +-- @tparam table params values for parameters +-- @treturn[1] string new sql query +-- @treturn[2] nil +-- @treturn[2] string error message +-- +local function apply_params(db, sql, params) + params = params or {} + + local err + + local str = string.gsub(sql, param_pattern, function(param) + local v, t = params[param], type(params[param]) + if "string" == t then return db:quote(v) end + if "number" == t then return tostring(v) end + if "boolean" == t then return v and '1' or '0' end + if NULL == v then return 'NULL' end + if DEFAULT == v then return 'DEFAULT' end + err = "undefined parameter: " .. param + end) + + if err then return nil, err end + + return str +end + +local sql_escape + +if freeswitch then + local api = require "resources.functions.api" + sql_escape = function(str) + return api:execute('sql_escape', str) + end +else + sql_escape = function(str) + return (string.gsub(str, "'", "''")) + end +end + ----------------------------------------------------------- local installed_classes = {} local default_backend = FsDatabase @@ -31,6 +79,10 @@ local function new_database(backend, backend_name) Database.__base = backend or default_backend Database = setmetatable(Database, Database.__base) + Database.NULL = NULL + + Database.DEFAULT = NULL + function Database.new(...) local self = Database.__base.new(...) setmetatable(self, Database) @@ -40,10 +92,55 @@ local function new_database(backend, backend_name) function Database:backend_name() return backend_name end - - function Database:first_row(sql) + + function Database:_apply_params(sql, params) + return apply_params(self, sql, params) + end + + function Database:query(sql, ...) + local params, callback + + local argc = select('#', ...) + + if argc > 0 then + local p = select(argc, ...) + if (p == nil) or (type(p) == 'function') then + callback = p + argc = argc - 1 + end + end + + if argc > 0 then + local p = select(argc, ...) + if (p == nil) or (type(p) == 'table') then + params = p + argc = argc - 1 + end + end + + assert(argc == 0, 'invalid argument #' .. tostring(argc)) + + if params then + -- backend supports parameters natively + if self.__base.parameter_query then + return self.__base.parameter_query(self, sql, params, callback) + end + + -- use emulation of parametes + local err + sql, err = self:_apply_params(sql, params) + if not sql then + log.errf('can not bind parameter: %s', tostring(err)) + return nil, err + end + end + + return self.__base.query(self, sql, callback) + end + + function Database:first_row(sql, params) local result - local ok, err = self:query(sql, function(row) + local ok, err = self:query(sql, params, function(row) result = row return 1 end) @@ -51,21 +148,33 @@ local function new_database(backend, backend_name) return result end - function Database:first_value(sql) - local result, err = self:first_row(sql) + function Database:first_value(sql, params) + local result, err = self:first_row(sql, params) if not result then return nil, err end local k, v = next(result) return v end function Database:first(sql, ...) - local result, err = self:first_row(sql) - if not result then return nil, err end - local t, n = {}, select('#', ...) - for i = 1, n do - t[i] = result[(select(i, ...))] + local t = type((...)) + local has_params = (t == 'nil') or (t == 'table') + + local result, err + if has_params then + result, err = self:first_row(sql, (...)) + else + result, err = self:first_row(sql) end - return unpack(t, 1, n) + + if not result then return nil, err end + + local t, n, c = {}, select('#', ...), 0 + for i = (has_params and 2 or 1), n do + c = c + 1 + t[c] = result[(select(i, ...))] + end + + return unpack(t, 1, c) end function Database:fetch_all(sql) @@ -78,7 +187,7 @@ local function new_database(backend, backend_name) end function Database:escape(str) - return (string.gsub(str, "'", "''")) + return sql_escape(str) end function Database:quote(str) @@ -176,6 +285,46 @@ local function new_database(backend, backend_name) db:release() assert(not db:connected()) + local db = Database.new(...) + + assert(db:connected()) + + -- test substitude parameters + t = assert(db:first_row('select :p1 as p1, :p2 as p2', {p1 = 'hello', p2 = 'world'})) + assert(t.p1 == 'hello') + assert(t.p2 == 'world') + + -- test escape string + -- `sql_escape` on freeswitch do `trim` + if not freeswitch then + -- test no trim value + local v = " hello " + a = assert(db:first_value('select :p1', {p1 = v})) + assert(a == v) + + -- test newline + -- On Windows with pgsql it replace `\n` to `\r\n`) + local v = "\r\nhello\r\nworld\r\n" + a = assert(db:first_value('select :p1', {p1 = v})) + assert(a == v, string.format('%q', tostring(a))) + end + + -- test backslash + local v = "\\hello\\world\\" + a = assert(db:first_value('select :p1', {p1 = v})) + assert(a == v, string.format('%q', tostring(a))) + + -- test single quote + local v = "'hello''world'''" + a = assert(db:first_value('select :p1', {p1 = v})) + assert(a == v, string.format('%q', tostring(a))) + + -- test empty string + local v = "" + a = assert(db:first_value('select :p1', {p1 = v})) + assert(a == v, string.format('%q', tostring(a))) + + db:release() log.info('self_test Database - pass') end diff --git a/resources/install/scripts/resources/functions/lazy_settings.lua b/resources/install/scripts/resources/functions/lazy_settings.lua index f0ecf4f3ef..ac6d7b73a0 100644 --- a/resources/install/scripts/resources/functions/lazy_settings.lua +++ b/resources/install/scripts/resources/functions/lazy_settings.lua @@ -105,15 +105,21 @@ function Settings:_load(category, subcategory, name) if domain_uuid then local sql = "SELECT domain_setting_uuid,domain_setting_category,domain_setting_subcategory,domain_setting_name,domain_setting_value " sql = sql .. "FROM v_domain_settings "; - sql = sql .. "WHERE domain_uuid = '" .. domain_uuid .. "'"; + sql = sql .. "WHERE domain_uuid = :domain_uuid "; sql = sql .. "AND domain_setting_enabled = 'true' "; - sql = sql .. "AND domain_setting_category = '" .. category .."'"; - sql = sql .. "AND domain_setting_subcategory = '" .. subcategory .. "'"; - sql = sql .. "AND domain_setting_name = '" .. name .. "'"; + sql = sql .. "AND domain_setting_category = :category "; + sql = sql .. "AND domain_setting_subcategory = :subcategory "; + sql = sql .. "AND domain_setting_name = :name "; sql = sql .. "AND domain_setting_value is not null "; sql = sql .. "ORDER BY domain_setting_category, domain_setting_subcategory ASC "; + local params = { + domain_uuid = domain_uuid, + category = category, + subcategory = subcategory, + name = name, + }; - db:query(sql, function(row) + db:query(sql, params, function(row) found = true; self:set( row.domain_setting_category, @@ -129,13 +135,18 @@ function Settings:_load(category, subcategory, name) local sql = "SELECT default_setting_uuid,default_setting_category,default_setting_subcategory,default_setting_name,default_setting_value " sql = sql .. "FROM v_default_settings "; sql = sql .. "WHERE default_setting_enabled = 'true' "; - sql = sql .. "AND default_setting_category = '" .. category .."'"; - sql = sql .. "AND default_setting_subcategory = '" .. subcategory .. "'"; - sql = sql .. "AND default_setting_name = '" .. name .. "'"; + sql = sql .. "AND default_setting_category = :category "; + sql = sql .. "AND default_setting_subcategory = :subcategory "; + sql = sql .. "AND default_setting_name = :name "; sql = sql .. "AND default_setting_value is not null "; sql = sql .. "ORDER BY default_setting_category, default_setting_subcategory ASC"; + local params = { + category = category, + subcategory = subcategory, + name = name, + }; - db:query(sql, function(row) + db:query(sql, params, function(row) found = true; self:set( row.default_setting_category, diff --git a/resources/install/scripts/resources/functions/lunajson.lua b/resources/install/scripts/resources/functions/lunajson.lua new file mode 100644 index 0000000000..c0113ed92c --- /dev/null +++ b/resources/install/scripts/resources/functions/lunajson.lua @@ -0,0 +1,11 @@ +local newdecoder = require 'resources.functions.lunajson.decoder' +local newencoder = require 'resources.functions.lunajson.encoder' +local sax = require 'resources.functions.lunajson.sax' +-- If you need multiple contexts of decoder and/or encoder, +-- you can require lunajson.decoder and/or lunajson.encoder directly. +return { + decode = newdecoder(), + encode = newencoder(), + newparser = sax.newparser, + newfileparser = sax.newfileparser, +} diff --git a/resources/install/scripts/resources/functions/lunajson/_str_lib.lua b/resources/install/scripts/resources/functions/lunajson/_str_lib.lua new file mode 100644 index 0000000000..479e3054e3 --- /dev/null +++ b/resources/install/scripts/resources/functions/lunajson/_str_lib.lua @@ -0,0 +1,86 @@ +local inf = math.huge +local byte, char, sub = string.byte, string.char, string.sub +local setmetatable = setmetatable +local floor = math.floor + +local _ENV = nil + +local hextbl = { + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, inf, inf, inf, inf, inf, inf, + inf, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, inf, inf, inf, inf, inf, inf, inf, inf, inf, + inf, inf, inf, inf, inf, inf, inf, inf, inf, inf, inf, inf, inf, inf, inf, inf, + inf, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, inf, inf, inf, inf, inf, inf, inf, inf, inf, +} +hextbl.__index = function() + return inf +end +setmetatable(hextbl, hextbl) + +return function(myerror) + local escapetbl = { + ['"'] = '"', + ['\\'] = '\\', + ['/'] = '/', + ['b'] = '\b', + ['f'] = '\f', + ['n'] = '\n', + ['r'] = '\r', + ['t'] = '\t' + } + escapetbl.__index = function() + myerror("invalid escape sequence") + end + setmetatable(escapetbl, escapetbl) + + local surrogateprev = 0 + + local function subst(ch, rest) + -- 0.000003814697265625 = 2^-18 + -- 0.000244140625 = 2^-12 + -- 0.015625 = 2^-6 + local u8 + if ch == 'u' then + local c1, c2, c3, c4 = byte(rest, 1, 4) + local ucode = hextbl[c1-47] * 0x1000 + hextbl[c2-47] * 0x100 + hextbl[c3-47] * 0x10 + hextbl[c4-47] + if ucode == inf then + myerror("invalid unicode charcode") + end + rest = sub(rest, 5) + if ucode < 0x80 then -- 1byte + u8 = char(ucode) + elseif ucode < 0x800 then -- 2byte + u8 = char(0xC0 + floor(ucode * 0.015625), 0x80 + ucode % 0x40) + elseif ucode < 0xD800 or 0xE000 <= ucode then -- 3byte + u8 = char(0xE0 + floor(ucode * 0.000244140625), 0x80 + floor(ucode * 0.015625) % 0x40, 0x80 + ucode % 0x40) + elseif 0xD800 <= ucode and ucode < 0xDC00 then -- surrogate pair 1st + if surrogateprev == 0 then + surrogateprev = ucode + if rest == '' then + return '' + end + end + else -- surrogate pair 2nd + if surrogateprev == 0 then + surrogateprev = 1 + else + ucode = 0x10000 + (surrogateprev - 0xD800) * 0x400 + (ucode - 0xDC00) + surrogateprev = 0 + u8 = char(0xF0 + floor(ucode * 0.000003814697265625), 0x80 + floor(ucode * 0.000244140625) % 0x40, 0x80 + floor(ucode * 0.015625) % 0x40, 0x80 + ucode % 0x40) + end + end + end + if surrogateprev ~= 0 then + myerror("invalid surrogate pair") + end + return (u8 or escapetbl[ch]) .. rest + end + + local function surrogateok() + return surrogateprev == 0 + end + + return { + subst = subst, + surrogateok = surrogateok + } +end diff --git a/resources/install/scripts/resources/functions/lunajson/_str_lib_lua53.lua b/resources/install/scripts/resources/functions/lunajson/_str_lib_lua53.lua new file mode 100644 index 0000000000..e0bf9269d3 --- /dev/null +++ b/resources/install/scripts/resources/functions/lunajson/_str_lib_lua53.lua @@ -0,0 +1,83 @@ +local inf = math.huge +local byte, char, sub = string.byte, string.char, string.sub +local setmetatable = setmetatable + +local _ENV = nil + +local hextbl = { + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, inf, inf, inf, inf, inf, inf, + inf, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, inf, inf, inf, inf, inf, inf, inf, inf, inf, + inf, inf, inf, inf, inf, inf, inf, inf, inf, inf, inf, inf, inf, inf, inf, inf, + inf, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, inf, inf, inf, inf, inf, inf, inf, inf, inf, +} +hextbl.__index = function() + return inf +end +setmetatable(hextbl, hextbl) + +return function(myerror) + local escapetbl = { + ['"'] = '"', + ['\\'] = '\\', + ['/'] = '/', + ['b'] = '\b', + ['f'] = '\f', + ['n'] = '\n', + ['r'] = '\r', + ['t'] = '\t' + } + escapetbl.__index = function() + myerror("invalid escape sequence") + end + setmetatable(escapetbl, escapetbl) + + local surrogateprev = 0 + + local function subst(ch, rest) + local u8 + if ch == 'u' then + local c1, c2, c3, c4 = byte(rest, 1, 4) + -- multiplications should not be lshift since cn may be inf + local ucode = hextbl[c1-47] * 0x1000 + hextbl[c2-47] * 0x100 + hextbl[c3-47] * 0x10 + hextbl[c4-47] + if ucode == inf then + myerror("invalid unicode charcode") + end + rest = sub(rest, 5) + if ucode < 0x80 then -- 1byte + u8 = char(ucode) + elseif ucode < 0x800 then -- 2byte + u8 = char(0xC0 + (ucode >> 6), 0x80 + (ucode & 0x3F)) + elseif ucode < 0xD800 or 0xE000 <= ucode then -- 3byte + u8 = char(0xE0 + (ucode >> 12), 0x80 + (ucode >> 6 & 0x3F), 0x80 + (ucode & 0x3F)) + elseif 0xD800 <= ucode and ucode < 0xDC00 then -- surrogate pair 1st + if surrogateprev == 0 then + surrogateprev = ucode + if rest == '' then + return '' + end + end + else -- surrogate pair 2nd + if surrogateprev == 0 then + surrogateprev = 1 + else + ucode = 0x10000 + (surrogateprev - 0xD800 << 10) + (ucode - 0xDC00) + surrogateprev = 0 + u8 = char(0xF0 + (ucode >> 18), 0x80 + (ucode >> 12 & 0x3F), 0x80 + (ucode >> 6 & 0x3F), 0x80 + (ucode & 0x3F)) + end + end + end + if surrogateprev ~= 0 then + myerror("invalid surrogate pair") + end + return (u8 or escapetbl[ch]) .. rest + end + + local function surrogateok() + return surrogateprev == 0 + end + + return { + subst = subst, + surrogateok = surrogateok + } +end diff --git a/resources/install/scripts/resources/functions/lunajson/decoder.lua b/resources/install/scripts/resources/functions/lunajson/decoder.lua new file mode 100644 index 0000000000..f4fb5e6bd7 --- /dev/null +++ b/resources/install/scripts/resources/functions/lunajson/decoder.lua @@ -0,0 +1,364 @@ +local error = error +local byte, char, find, gsub, match, sub = string.byte, string.char, string.find, string.gsub, string.match, string.sub +local tonumber = tonumber +local tostring, setmetatable = tostring, setmetatable + +-- The function that interprets JSON strings is separated into another file so as to +-- use bitwise operation to speedup unicode codepoints processing on Lua 5.3. +local genstrlib +if _VERSION == "Lua 5.3" then + genstrlib = require 'resources.functions.lunajson._str_lib_lua53' +else + genstrlib = require 'resources.functions.lunajson._str_lib' +end + +local _ENV = nil + +local function newdecoder() + local json, pos, nullv, arraylen + + -- `f` is the temporary for dispatcher[c] and + -- the dummy for the first return value of `find` + local dispatcher, f + + --[[ + Helper + --]] + local function decodeerror(errmsg) + error("parse error at " .. pos .. ": " .. errmsg) + end + + --[[ + Invalid + --]] + local function f_err() + decodeerror('invalid value') + end + + --[[ + Constants + --]] + -- null + local function f_nul() + if sub(json, pos, pos+2) == 'ull' then + pos = pos+3 + return nullv + end + decodeerror('invalid value') + end + + -- false + local function f_fls() + if sub(json, pos, pos+3) == 'alse' then + pos = pos+4 + return false + end + decodeerror('invalid value') + end + + -- true + local function f_tru() + if sub(json, pos, pos+2) == 'rue' then + pos = pos+3 + return true + end + decodeerror('invalid value') + end + + --[[ + Numbers + Conceptually, the longest prefix that matches to `-?(0|[1-9][0-9]*)(\.[0-9]*)?([eE][+-]?[0-9]*)?` + (in regexp) is captured as a number and its conformance to the JSON spec is checked. + --]] + -- deal with non-standard locales + local radixmark = match(tostring(0.5), '[^0-9]') + local fixedtonumber = tonumber + if radixmark ~= '.' then + if find(radixmark, '%W') then + radixmark = '%' .. radixmark + end + fixedtonumber = function(s) + return tonumber(gsub(s, '.', radixmark)) + end + end + + local function error_number() + decodeerror('invalid number') + end + + -- `0(\.[0-9]*)?([eE][+-]?[0-9]*)?` + local function f_zro(mns) + local postmp = pos + local num + local c = byte(json, postmp) + if not c then + return error_number() + end + + if c == 0x2E then -- is this `.`? + num = match(json, '^.[0-9]*', pos) -- skipping 0 + local numlen = #num + if numlen == 1 then + return error_number() + end + postmp = pos + numlen + c = byte(json, postmp) + end + + if c == 0x45 or c == 0x65 then -- is this e or E? + local numexp = match(json, '^[^eE]*[eE][-+]?[0-9]+', pos) + if not numexp then + return error_number() + end + if num then -- since `0e.*` is always 0.0, ignore those + num = numexp + end + postmp = pos + #numexp + end + + pos = postmp + if num then + num = fixedtonumber(num) + else + num = 0.0 + end + if mns then + num = -num + end + return num + end + + -- `[1-9][0-9]*(\.[0-9]*)?([eE][+-]?[0-9]*)?` + local function f_num(mns) + pos = pos-1 + local num = match(json, '^.[0-9]*%.?[0-9]*', pos) + if byte(num, -1) == 0x2E then + return error_number() + end + local postmp = pos + #num + local c = byte(json, postmp) + + if c == 0x45 or c == 0x65 then -- e or E? + num = match(json, '^[^eE]*[eE][-+]?[0-9]+', pos) + if not num then + return error_number() + end + postmp = pos + #num + end + + pos = postmp + num = fixedtonumber(num)-0.0 + if mns then + num = -num + end + return num + end + + -- skip minus sign + local function f_mns() + local c = byte(json, pos) + if c then + pos = pos+1 + if c > 0x30 then + if c < 0x3A then + return f_num(true) + end + else + if c > 0x2F then + return f_zro(true) + end + end + end + decodeerror('invalid number') + end + + --[[ + Strings + --]] + local f_str_lib = genstrlib(decodeerror) + local f_str_surrogateok = f_str_lib.surrogateok -- whether codepoints for surrogate pair are correctly paired + local f_str_subst = f_str_lib.subst -- the function passed to gsub that interprets escapes + + -- caching interpreted keys for speed + local f_str_keycache = setmetatable({}, {__mode="v"}) + + local function f_str(iskey) + local newpos = pos-2 + local pos2 = pos + local c1, c2 + repeat + newpos = find(json, '"', pos2, true) -- search '"' + if not newpos then + decodeerror("unterminated string") + end + pos2 = newpos+1 + while true do -- skip preceding '\\'s + c1, c2 = byte(json, newpos-2, newpos-1) + if c2 ~= 0x5C or c1 ~= 0x5C then + break + end + newpos = newpos-2 + end + until c2 ~= 0x5C -- check '"' is not preceded by '\' + + local str = sub(json, pos, pos2-2) + pos = pos2 + + if iskey then -- check key cache + local str2 = f_str_keycache[str] + if str2 then + return str2 + end + end + local str2 = str + if find(str2, '\\', 1, true) then -- check if backslash occurs + str2 = gsub(str2, '\\(.)([^\\]*)', f_str_subst) -- interpret escapes + if not f_str_surrogateok() then + decodeerror("invalid surrogate pair") + end + end + if iskey then -- commit key cache + f_str_keycache[str] = str2 + end + return str2 + end + + --[[ + Arrays, Objects + --]] + -- array + local function f_ary() + local ary = {} + + f, pos = find(json, '^[ \n\r\t]*', pos) + pos = pos+1 + + local i = 0 + if byte(json, pos) ~= 0x5D then -- check closing bracket ']', that consists an empty array + local newpos = pos-1 + repeat + i = i+1 + f = dispatcher[byte(json,newpos+1)] -- parse value + pos = newpos+2 + ary[i] = f() + f, newpos = find(json, '^[ \n\r\t]*,[ \n\r\t]*', pos) -- check comma + until not newpos + + f, newpos = find(json, '^[ \n\r\t]*%]', pos) -- check closing bracket + if not newpos then + decodeerror("no closing bracket of an array") + end + pos = newpos + end + + pos = pos+1 + if arraylen then -- commit the length of the array if `arraylen` is set + ary[0] = i + end + return ary + end + + -- objects + local function f_obj() + local obj = {} + + f, pos = find(json, '^[ \n\r\t]*', pos) + pos = pos+1 + if byte(json, pos) ~= 0x7D then -- check the closing bracket '}', that consists an empty object + local newpos = pos-1 + + repeat + pos = newpos+1 + if byte(json, pos) ~= 0x22 then -- check '"' + decodeerror("not key") + end + pos = pos+1 + local key = f_str(true) -- parse key + + -- optimized for compact json + -- c1, c2 == ':', or + -- c1, c2, c3 == ':', ' ', + f = f_err + do + local c1, c2, c3 = byte(json, pos, pos+3) + if c1 == 0x3A then + newpos = pos + if c2 == 0x20 then + newpos = newpos+1 + c2 = c3 + end + f = dispatcher[c2] + end + end + if f == f_err then -- read a colon and arbitrary number of spaces + f, newpos = find(json, '^[ \n\r\t]*:[ \n\r\t]*', pos) + if not newpos then + decodeerror("no colon after a key") + end + end + f = dispatcher[byte(json, newpos+1)] -- parse value + pos = newpos+2 + obj[key] = f() + f, newpos = find(json, '^[ \n\r\t]*,[ \n\r\t]*', pos) + until not newpos + + f, newpos = find(json, '^[ \n\r\t]*}', pos) + if not newpos then + decodeerror("no closing bracket of an object") + end + pos = newpos + end + + pos = pos+1 + return obj + end + + --[[ + The jump table to dispatch a parser for a value, indexed by the code of the value's first char. + Nil key means the end of json. + --]] + dispatcher = { + f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, + f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, + f_err, f_err, f_str, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_mns, f_err, f_err, + f_zro, f_num, f_num, f_num, f_num, f_num, f_num, f_num, f_num, f_num, f_err, f_err, f_err, f_err, f_err, f_err, + f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, + f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_ary, f_err, f_err, f_err, f_err, + f_err, f_err, f_err, f_err, f_err, f_err, f_fls, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_nul, f_err, + f_err, f_err, f_err, f_err, f_tru, f_err, f_err, f_err, f_err, f_err, f_err, f_obj, f_err, f_err, f_err, f_err, + } + dispatcher[0] = f_err + dispatcher.__index = function() + decodeerror("unexpected termination") + end + setmetatable(dispatcher, dispatcher) + + --[[ + run decoder + --]] + local function decode(json_, pos_, nullv_, arraylen_) + json, pos, nullv, arraylen = json_, pos_, nullv_, arraylen_ + + pos = pos or 1 + f, pos = find(json, '^[ \n\r\t]*', pos) + pos = pos+1 + + f = dispatcher[byte(json, pos)] + pos = pos+1 + local v = f() + + if pos_ then + return v, pos + else + f, pos = find(json, '^[ \n\r\t]*', pos) + if pos ~= #json then + error('json ended') + end + return v + end + end + + return decode +end + +return newdecoder diff --git a/resources/install/scripts/resources/functions/lunajson/encoder.lua b/resources/install/scripts/resources/functions/lunajson/encoder.lua new file mode 100644 index 0000000000..aae06af698 --- /dev/null +++ b/resources/install/scripts/resources/functions/lunajson/encoder.lua @@ -0,0 +1,184 @@ +local error = error +local byte, find, format, gsub, match = string.byte, string.find, string.format, string.gsub, string.match +local concat = table.concat +local tostring = tostring +local pairs, type = pairs, type +local setmetatable = setmetatable +local huge, tiny = 1/0, -1/0 + +local f_string_pat +if _VERSION == "Lua 5.1" then + -- use the cluttered pattern because lua 5.1 does not handle \0 in a pattern correctly + f_string_pat = '[^ -!#-[%]^-\255]' +else + f_string_pat = '[\0-\31"\\]' +end + +local _ENV = nil + +local function newencoder() + local v, nullv + local i, builder, visited + + local function f_tostring(v) + builder[i] = tostring(v) + i = i+1 + end + + local radixmark = match(tostring(0.5), '[^0-9]') + local delimmark = match(tostring(12345.12345), '[^0-9' .. radixmark .. ']') + if radixmark == '.' then + radixmark = nil + end + + local radixordelim + if radixmark or delimmark then + radixordelim = true + if radixmark and find(radixmark, '%W') then + radixmark = '%' .. radixmark + end + if delimmark and find(delimmark, '%W') then + delimmark = '%' .. delimmark + end + end + + local f_number = function(n) + if tiny < n and n < huge then + local s = format("%.17g", n) + if radixordelim then + if delimmark then + s = gsub(s, delimmark, '') + end + if radixmark then + s = gsub(s, radixmark, '.') + end + end + builder[i] = s + i = i+1 + return + end + error('invalid number') + end + + local doencode + + local f_string_subst = { + ['"'] = '\\"', + ['\\'] = '\\\\', + ['\b'] = '\\b', + ['\f'] = '\\f', + ['\n'] = '\\n', + ['\r'] = '\\r', + ['\t'] = '\\t', + __index = function(_, c) + return format('\\u00%02X', byte(c)) + end + } + setmetatable(f_string_subst, f_string_subst) + + local function f_string(s) + builder[i] = '"' + if find(s, f_string_pat) then + s = gsub(s, f_string_pat, f_string_subst) + end + builder[i+1] = s + builder[i+2] = '"' + i = i+3 + end + + local function f_table(o) + if visited[o] then + error("loop detected") + end + visited[o] = true + + local tmp = o[0] + if type(tmp) == 'number' then -- arraylen available + builder[i] = '[' + i = i+1 + for j = 1, tmp do + doencode(o[j]) + builder[i] = ',' + i = i+1 + end + if tmp > 0 then + i = i-1 + end + builder[i] = ']' + + else + tmp = o[1] + if tmp ~= nil then -- detected as array + builder[i] = '[' + i = i+1 + local j = 2 + repeat + doencode(tmp) + tmp = o[j] + if tmp == nil then + break + end + j = j+1 + builder[i] = ',' + i = i+1 + until false + builder[i] = ']' + + else -- detected as object + builder[i] = '{' + i = i+1 + local tmp = i + for k, v in pairs(o) do + if type(k) ~= 'string' then + error("non-string key") + end + f_string(k) + builder[i] = ':' + i = i+1 + doencode(v) + builder[i] = ',' + i = i+1 + end + if i > tmp then + i = i-1 + end + builder[i] = '}' + end + end + + i = i+1 + visited[o] = nil + end + + local dispatcher = { + boolean = f_tostring, + number = f_number, + string = f_string, + table = f_table, + __index = function() + error("invalid type value") + end + } + setmetatable(dispatcher, dispatcher) + + function doencode(v) + if v == nullv then + builder[i] = 'null' + i = i+1 + return + end + return dispatcher[type(v)](v) + end + + local function encode(v_, nullv_) + v, nullv = v_, nullv_ + i, builder, visited = 1, {}, {} + + doencode(v) + return concat(builder) + end + + return encode +end + +return newencoder diff --git a/resources/install/scripts/resources/functions/lunajson/sax.lua b/resources/install/scripts/resources/functions/lunajson/sax.lua new file mode 100644 index 0000000000..d69603d663 --- /dev/null +++ b/resources/install/scripts/resources/functions/lunajson/sax.lua @@ -0,0 +1,525 @@ +local error = error +local byte, char, find, gsub, match, sub = string.byte, string.char, string.find, string.gsub, string.match, string.sub +local tonumber = tonumber +local tostring, type, unpack = tostring, type, table.unpack or unpack + +-- The function that interprets JSON strings is separated into another file so as to +-- use bitwise operation to speedup unicode codepoints processing on Lua 5.3. +local genstrlib +if _VERSION == "Lua 5.3" then + genstrlib = require 'resources.functions.lunajson._str_lib_lua53' +else + genstrlib = require 'resources.functions.lunajson._str_lib' +end + +local _ENV = nil + +local function nop() end + +local function newparser(src, saxtbl) + local json, jsonnxt + local jsonlen, pos, acc = 0, 1, 0 + + -- `f` is the temporary for dispatcher[c] and + -- the dummy for the first return value of `find` + local dispatcher, f + + -- initialize + if type(src) == 'string' then + json = src + jsonlen = #json + jsonnxt = function() + json = '' + jsonlen = 0 + jsonnxt = nop + end + else + jsonnxt = function() + acc = acc + jsonlen + pos = 1 + repeat + json = src() + if not json then + json = '' + jsonlen = 0 + jsonnxt = nop + return + end + jsonlen = #json + until jsonlen > 0 + end + jsonnxt() + end + + local sax_startobject = saxtbl.startobject or nop + local sax_key = saxtbl.key or nop + local sax_endobject = saxtbl.endobject or nop + local sax_startarray = saxtbl.startarray or nop + local sax_endarray = saxtbl.endarray or nop + local sax_string = saxtbl.string or nop + local sax_number = saxtbl.number or nop + local sax_boolean = saxtbl.boolean or nop + local sax_null = saxtbl.null or nop + + --[[ + Helper + --]] + local function tryc() + local c = byte(json, pos) + if not c then + jsonnxt() + c = byte(json, pos) + end + return c + end + + local function parseerror(errmsg) + error("parse error at " .. acc + pos .. ": " .. errmsg) + end + + local function tellc() + return tryc() or parseerror("unexpected termination") + end + + local function spaces() -- skip spaces and prepare the next char + while true do + f, pos = find(json, '^[ \n\r\t]*', pos) + if pos ~= jsonlen then + pos = pos+1 + return + end + if jsonlen == 0 then + parseerror("unexpected termination") + end + jsonnxt() + end + end + + --[[ + Invalid + --]] + local function f_err() + parseerror('invalid value') + end + + --[[ + Constants + --]] + -- fallback slow constants parser + local function generic_constant(target, targetlen, ret, sax_f) + for i = 1, targetlen do + local c = tellc() + if byte(target, i) ~= c then + parseerror("invalid char") + end + pos = pos+1 + end + return sax_f(ret) + end + + -- null + local function f_nul() + if sub(json, pos, pos+2) == 'ull' then + pos = pos+3 + return sax_null(nil) + end + return generic_constant('ull', 3, nil, sax_null) + end + + -- false + local function f_fls() + if sub(json, pos, pos+3) == 'alse' then + pos = pos+4 + return sax_boolean(false) + end + return generic_constant('alse', 4, false, sax_boolean) + end + + -- true + local function f_tru() + if sub(json, pos, pos+2) == 'rue' then + pos = pos+3 + return sax_boolean(true) + end + return generic_constant('rue', 3, true, sax_boolean) + end + + --[[ + Numbers + Conceptually, the longest prefix that matches to `(0|[1-9][0-9]*)(\.[0-9]*)?([eE][+-]?[0-9]*)?` + (in regexp) is captured as a number and its conformance to the JSON spec is checked. + --]] + -- deal with non-standard locales + local radixmark = match(tostring(0.5), '[^0-9]') + local fixedtonumber = tonumber + if radixmark ~= '.' then -- deals with non-standard locales + if find(radixmark, '%W') then + radixmark = '%' .. radixmark + end + fixedtonumber = function(s) + return tonumber(gsub(s, '.', radixmark)) + end + end + + -- fallback slow parser + local function generic_number(mns) + local buf = {} + local i = 1 + + local c = byte(json, pos) + pos = pos+1 + + local function nxt() + buf[i] = c + i = i+1 + c = tryc() + pos = pos+1 + end + + if c == 0x30 then + nxt() + else + repeat nxt() until not (c and 0x30 <= c and c < 0x3A) + end + if c == 0x2E then + nxt() + if not (c and 0x30 <= c and c < 0x3A) then + parseerror('invalid number') + end + repeat nxt() until not (c and 0x30 <= c and c < 0x3A) + end + if c == 0x45 or c == 0x65 then + nxt() + if c == 0x2B or c == 0x2D then + nxt() + end + if not (c and 0x30 <= c and c < 0x3A) then + parseerror('invalid number') + end + repeat nxt() until not (c and 0x30 <= c and c < 0x3A) + end + pos = pos-1 + + local num = char(unpack(buf)) + num = fixedtonumber(num)-0.0 + if mns then + num = -num + end + return sax_number(num) + end + + -- `0(\.[0-9]*)?([eE][+-]?[0-9]*)?` + local function f_zro(mns) + local postmp = pos + local num + local c = byte(json, postmp) + + if c == 0x2E then -- is this `.`? + num = match(json, '^.[0-9]*', pos) -- skipping 0 + local numlen = #num + if numlen == 1 then + pos = pos-1 + return generic_number(mns) + end + postmp = pos + numlen + c = byte(json, postmp) + end + + if c == 0x45 or c == 0x65 then -- is this e or E? + local numexp = match(json, '^[^eE]*[eE][-+]?[0-9]+', pos) + if not numexp then + pos = pos-1 + return generic_number(mns) + end + if num then -- since `0e.*` is always 0.0, ignore those + num = numexp + end + postmp = pos + #numexp + end + + if postmp > jsonlen then + pos = pos-1 + return generic_number(mns) + end + pos = postmp + if num then + num = fixedtonumber(num) + else + num = 0.0 + end + if mns then + num = -num + end + return sax_number(num) + end + + -- `[1-9][0-9]*(\.[0-9]*)?([eE][+-]?[0-9]*)?` + local function f_num(mns) + pos = pos-1 + local num = match(json, '^.[0-9]*%.?[0-9]*', pos) + if byte(num, -1) == 0x2E then + return generic_number(mns) + end + local postmp = pos + #num + local c = byte(json, postmp) + + if c == 0x45 or c == 0x65 then -- e or E? + num = match(json, '^[^eE]*[eE][-+]?[0-9]+', pos) + if not num then + return generic_number(mns) + end + postmp = pos + #num + end + + if postmp > jsonlen then + return generic_number(mns) + end + pos = postmp + num = fixedtonumber(num)-0.0 + if mns then + num = -num + end + return sax_number(num) + end + + -- skip minus sign + local function f_mns() + local c = byte(json, pos) or tellc() + if c then + pos = pos+1 + if c > 0x30 then + if c < 0x3A then + return f_num(true) + end + else + if c > 0x2F then + return f_zro(true) + end + end + end + parseerror("invalid number") + end + + --[[ + Strings + --]] + local f_str_lib = genstrlib(parseerror) + local f_str_surrogateok = f_str_lib.surrogateok -- whether codepoints for surrogate pair are correctly paired + local f_str_subst = f_str_lib.subst -- the function passed to gsub that interprets escapes + + local function f_str(iskey) + local pos2 = pos + local newpos + local str = '' + local bs + while true do + while true do -- search '\' or '"' + newpos = find(json, '[\\"]', pos2) + if newpos then + break + end + str = str .. sub(json, pos, jsonlen) + if pos2 == jsonlen+2 then + pos2 = 2 + else + pos2 = 1 + end + jsonnxt() + end + if byte(json, newpos) == 0x22 then -- break if '"' + break + end + pos2 = newpos+2 -- skip '\' + bs = true -- remember that backslash occurs + end + str = str .. sub(json, pos, newpos-1) + pos = newpos+1 + + if bs then -- check if backslash occurs + str = gsub(str, '\\(.)([^\\]*)', f_str_subst) -- interpret escapes + if not f_str_surrogateok() then + parseerror("invalid surrogate pair") + end + end + + if iskey then + return sax_key(str) + end + return sax_string(str) + end + + --[[ + Arrays, Objects + --]] + -- arrays + local function f_ary() + sax_startarray() + spaces() + if byte(json, pos) ~= 0x5D then -- check the closing bracket ']', that consists an empty array + local newpos + while true do + f = dispatcher[byte(json, pos)] -- parse value + pos = pos+1 + f() + f, newpos = find(json, '^[ \n\r\t]*,[ \n\r\t]*', pos) -- check comma + if not newpos then + f, newpos = find(json, '^[ \n\r\t]*%]', pos) -- check closing bracket + if newpos then + pos = newpos + break + end + spaces() -- since the current chunk can be ended, skip spaces toward following chunks + local c = byte(json, pos) + if c == 0x2C then -- check comma again + pos = pos+1 + spaces() + newpos = pos-1 + elseif c == 0x5D then -- check closing bracket again + break + else + parseerror("no closing bracket of an array") + end + end + pos = newpos+1 + if pos > jsonlen then + spaces() + end + end + end + pos = pos+1 + return sax_endarray() + end + + -- objects + local function f_obj() + sax_startobject() + spaces() + if byte(json, pos) ~= 0x7D then -- check the closing bracket `}`, that consists an empty object + local newpos + while true do + if byte(json, pos) ~= 0x22 then + parseerror("not key") + end + pos = pos+1 + f_str(true) + f, newpos = find(json, '^[ \n\r\t]*:[ \n\r\t]*', pos) -- check colon + if not newpos then + spaces() -- since the current chunk can be ended, skip spaces toward following chunks + if byte(json, pos) ~= 0x3A then -- check colon again + parseerror("no colon after a key") + end + pos = pos+1 + spaces() + newpos = pos-1 + end + pos = newpos+1 + if pos > jsonlen then + spaces() + end + f = dispatcher[byte(json, pos)] -- parse value + pos = pos+1 + f() + f, newpos = find(json, '^[ \n\r\t]*,[ \n\r\t]*', pos) -- check comma + if not newpos then + f, newpos = find(json, '^[ \n\r\t]*}', pos) -- check closing bracket + if newpos then + pos = newpos + break + end + spaces() -- since the current chunk can be ended, skip spaces toward following chunks + local c = byte(json, pos) + if c == 0x2C then -- check comma again + pos = pos+1 + spaces() + newpos = pos-1 + elseif c == 0x7D then -- check closing bracket again + break + else + parseerror("no closing bracket of an object") + end + end + pos = newpos+1 + if pos > jsonlen then + spaces() + end + end + end + pos = pos+1 + return sax_endobject() + end + + --[[ + The jump table to dispatch a parser for a value, indexed by the code of the value's first char. + Key should be non-nil. + --]] + dispatcher = { + f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, + f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, + f_err, f_err, f_str, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_mns, f_err, f_err, + f_zro, f_num, f_num, f_num, f_num, f_num, f_num, f_num, f_num, f_num, f_err, f_err, f_err, f_err, f_err, f_err, + f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, + f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_ary, f_err, f_err, f_err, f_err, + f_err, f_err, f_err, f_err, f_err, f_err, f_fls, f_err, f_err, f_err, f_err, f_err, f_err, f_err, f_nul, f_err, + f_err, f_err, f_err, f_err, f_tru, f_err, f_err, f_err, f_err, f_err, f_err, f_obj, f_err, f_err, f_err, f_err, + } + dispatcher[0] = f_err + + --[[ + public funcitons + --]] + local function run() + spaces() + f = dispatcher[byte(json, pos)] + pos = pos+1 + f() + end + + local function read(n) + if n < 0 then + error("the argument must be non-negative") + end + local pos2 = (pos-1) + n + local str = sub(json, pos, pos2) + while pos2 > jsonlen and jsonlen ~= 0 do + jsonnxt() + pos2 = pos2 - (jsonlen - (pos-1)) + str = str .. sub(json, pos, pos2) + end + if jsonlen ~= 0 then + pos = pos2+1 + end + return str + end + + local function tellpos() + return acc + pos + end + + return { + run = run, + tryc = tryc, + read = read, + tellpos = tellpos, + } +end + +local function newfileparser(fn, saxtbl) + local fp = io.open(fn) + local function gen() + local s + if fp then + s = fp:read(8192) + if not s then + fp:close() + fp = nil + end + end + return s + end + return newparser(gen, saxtbl) +end + +return { + newparser = newparser, + newfileparser = newfileparser +} diff --git a/resources/install/scripts/resources/functions/route_to_bridge.lua b/resources/install/scripts/resources/functions/route_to_bridge.lua index f7098a8b7d..71834de07b 100644 --- a/resources/install/scripts/resources/functions/route_to_bridge.lua +++ b/resources/install/scripts/resources/functions/route_to_bridge.lua @@ -35,7 +35,7 @@ end local select_routes_sql = [[ select * from v_dialplans -where (domain_uuid = '%s' or domain_uuid is null) +where (domain_uuid = :domain_uuid or domain_uuid is null) and app_uuid = '8c914ec3-9fc0-8ab5-4cda-6c9288bdc9a3' and dialplan_enabled = 'true' order by dialplan_order asc @@ -43,7 +43,7 @@ order by dialplan_order asc local select_extensions_sql = [[ select * from v_dialplan_details -where dialplan_uuid = '%s' +where dialplan_uuid = :dialplan_uuid order by dialplan_detail_group asc, dialplan_detail_order asc ]] @@ -239,9 +239,11 @@ end local function outbound_route_to_bridge(dbh, domain_uuid, fields) local actions, dial_string = {} - dbh:query(select_routes_sql:format(domain_uuid), function(route) + local params = {} + dbh:query(select_routes_sql, {domain_uuid=domain_uuid}, function(route) local extension = {} - dbh:query(select_extensions_sql:format(route.dialplan_uuid), function(ext) + params.dialplan_uuid = route.dialplan_uuid + dbh:query(select_extensions_sql, params, function(ext) local group_no = tonumber(ext.dialplan_detail_group) local tag = ext.dialplan_detail_tag local element = { diff --git a/resources/install/scripts/resources/functions/send_mail.lua b/resources/install/scripts/resources/functions/send_mail.lua index 9fd535f30f..3d9371c9e4 100644 --- a/resources/install/scripts/resources/functions/send_mail.lua +++ b/resources/install/scripts/resources/functions/send_mail.lua @@ -52,15 +52,23 @@ if not freeswitch then sql = sql .. "status, " sql = sql .. "email " sql = sql .. ") values ( " - sql = sql .. "'" .. email_uuid .. "', " - if call_uuid then sql = sql .. "'" .. call_uuid .. "', " end - sql = sql .. "'" .. domain_uuid .. "', " + sql = sql .. ":email_uuid, " + if call_uuid then sql = sql .. ":call_uuid, " end + sql = sql .. ":domain_uuid, " sql = sql .. "now()," - sql = sql .. "'" .. email_type .. "', " + sql = sql .. ":email_type, " sql = sql .. "'failed', " sql = sql .. "'' " sql = sql .. ") " - db:query(sql) + + local params = { + email_uuid = email_uuid; + call_uuid = call_uuid; + domain_uuid = domain_uuid; + email_type = email_type; + } + + db:query(sql, params) log.infof("Retained in v_emails as email_uuid = %s", email_uuid) else diff --git a/resources/install/scripts/resources/functions/settings.lua b/resources/install/scripts/resources/functions/settings.lua index 676b5f95f0..ae8dc985f6 100644 --- a/resources/install/scripts/resources/functions/settings.lua +++ b/resources/install/scripts/resources/functions/settings.lua @@ -1,21 +1,25 @@ ---debug - debug["sql"] = false; - --define the trim function require "resources.functions.trim"; +--include json library + local json + if (debug["sql"]) then + json = require "resources.functions.lunajson" + end + --get the domain_uuid if (domain_uuid == nil) then if (domain_name ~= nil) then - sql = "SELECT domain_uuid FROM v_domains "; - sql = sql .. "WHERE domain_name = '" .. domain_name .."' "; + local sql = "SELECT domain_uuid FROM v_domains "; + sql = sql .. "WHERE domain_name = :domain_name"; + local params = {domain_name = domain_name}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[conference] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[settings] SQL: " .. sql .. "; params: " .. json.encode(params) .. "\n"); end - status = dbh:query(sql, function(rows) + dbh:query(sql, params, function(rows) domain_uuid = string.lower(rows["domain_uuid"]); - end); + end); end end @@ -45,28 +49,28 @@ function settings(domain_uuid) --define the table - array = {} + local array = {} --get the default settings - sql = "SELECT * FROM v_default_settings "; + local sql = "SELECT * FROM v_default_settings "; sql = sql .. "WHERE default_setting_enabled = 'true' "; sql = sql .. "AND default_setting_category is not null "; sql = sql .. "AND default_setting_subcategory is not null "; sql = sql .. "AND default_setting_name is not null "; sql = sql .. "AND default_setting_value is not null "; sql = sql .. "ORDER BY default_setting_category, default_setting_subcategory ASC"; + if (debug["sql"]) then - freeswitch.consoleLog("notice", "SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[settings] SQL: " .. sql .. "\n"); end - x = 1; - previous_category = ''; + dbh:query(sql, function(row) --variables - setting_uuid = row.default_setting_uuid - category = row.default_setting_category; - subcategory = row.default_setting_subcategory; - name = row.default_setting_name; - value = row.default_setting_value; + local setting_uuid = row.default_setting_uuid + local category = row.default_setting_category; + local subcategory = row.default_setting_subcategory; + local name = row.default_setting_name; + local value = row.default_setting_value; --add the category array if (array[category] == nil) then @@ -76,54 +80,41 @@ --add the subcategory array if (array[category][subcategory] == nil) then array[category][subcategory] = {} - x = 1; - end - - --add the subcategory array - if (array[category][subcategory][name] == nil) then - array[category][subcategory][name] = {} end --set the name and value if (name == "array") then - array[category][subcategory][x] = {} - array[category][subcategory][x] = value; + local t = array[category][subcategory] + t[#t + 1] = value else if (value ~= nil) then array[category][subcategory][name] = value; end end - - --set the previous category - previous_category = category; - - --set the previous subcategory - previous_subcategory = subcategory; - - --increment the value of x - x = x + 1; end); --get the domain settings if (domain_uuid ~= nil) then - sql = "SELECT * FROM v_domain_settings "; - sql = sql .. "WHERE domain_uuid = '" .. domain_uuid .. "' "; + local sql = "SELECT * FROM v_domain_settings "; + sql = sql .. "WHERE domain_uuid = :domain_uuid "; sql = sql .. "AND domain_setting_enabled = 'true' "; sql = sql .. "AND domain_setting_category is not null "; sql = sql .. "AND domain_setting_subcategory is not null "; sql = sql .. "AND domain_setting_name is not null "; sql = sql .. "AND domain_setting_value is not null "; sql = sql .. "ORDER BY domain_setting_category, domain_setting_subcategory ASC "; + local params = {domain_uuid = domain_uuid}; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[directory] SQL: " .. sql .. "\n"); + freeswitch.consoleLog("notice", "[settings] SQL: " .. sql .. "; params: " .. json.encode(params) .. "\n"); end - dbh:query(sql, function(row) + local last_category, last_subcategory + dbh:query(sql, params, function(row) --variables - setting_uuid = row.domain_setting_uuid - category = row.domain_setting_category; - subcategory = row.domain_setting_subcategory; - name = row.domain_setting_name; - value = row.domain_setting_value; + local setting_uuid = row.domain_setting_uuid + local category = row.domain_setting_category; + local subcategory = row.domain_setting_subcategory; + local name = row.domain_setting_name; + local value = row.domain_setting_value; --add the category array if (array[category] == nil) then @@ -133,30 +124,25 @@ --add the subcategory array if (array[category][subcategory] == nil) then array[category][subcategory] = {} - x = 1; - end - - --add the subcategory array - if (array[category][subcategory][name] == nil) then - array[category][subcategory][name] = {} end --set the name and value if (name == "array") then - array[category][subcategory][x] = {} - array[category][subcategory][x] = value; + local t = array[category][subcategory] + -- overwrite entire array from default settings if needed + if last_category ~= category and last_subcategory ~= subcategory and t[1] then + t = {} + array[category][subcategory] = t + end + t[#t + 1] = value else if (value ~= nil) then array[category][subcategory][name] = value; end end - --set the previous category - previous_category = category; - - --set the previous subcategory - previous_subcategory = subcategory; - + -- set last category + last_category, last_subcategory = category, subcategory end); end @@ -168,3 +154,6 @@ --array = settings(domain_uuid); --result = array['domain']['template']['name']; --freeswitch.consoleLog("notice", result .. "\n"); + --for i, ext in ipairs(array.fax.allowed_extension) do + -- freeswitch.consoleLog("notice", "allowed_extension #" .. i .. ": " .. ext .. "\n"); + --end diff --git a/resources/install/scripts/transfer2.lua b/resources/install/scripts/transfer2.lua new file mode 100644 index 0000000000..499ca76d69 --- /dev/null +++ b/resources/install/scripts/transfer2.lua @@ -0,0 +1,32 @@ +local api = freeswitch.API() +local uuid = assert(argv[1]) +local t1 = assert(argv[2]) +local t2 = assert(argv[3]) + +require "resources.functions.channel_utils" +require "resources.functions.split" +local log = require "resources.functions.log".transfer2 + +log.noticef("session %s\n", uuid); + +local other_leg_uuid = channel_variable(uuid, "signal_bond") + +log.noticef("other leg: %s\n", other_leg_uuid or '') + +if other_leg_uuid and #other_leg_uuid > 0 then + if t2 ~= '::NONE::' then + if t2 == '::KILL::' then + channel_kill(other_leg_uuid) + else + channel_transfer(other_leg_uuid, usplit(t2, '::')) + end + end +end + +if t1 ~= '::NONE::' then + if t1 == '::KILL::' then + channel_kill(uuid) + else + channel_transfer(uuid, usplit(t1, '::')) + end +end