Improve security on the lua scripts, add lua json library, add *77 dnd toggle feature code, speed dial *0[ext], and improve blf support for extension number alias.

This commit is contained in:
markjcrane
2016-12-08 18:36:15 -07:00
parent 30acee4dff
commit 9b1b38fab6
84 changed files with 3881 additions and 1346 deletions
@@ -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, [[ <node type="]] .. field.node_type .. [[" domain="]] .. field.node_domain .. [[" description="]] .. field.node_description .. [["/>]]);
else
@@ -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());
@@ -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, [[ <group name="]]..field["control_name"]..[[">]]);
--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, [[ <control digits="]]..row["control_digits"]..[[" action="]]..row["control_action"]..[[" data="]]..row["control_data"]..[["/>]]);
@@ -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, [[ <profile name="]]..field["profile_name"]..[[">]]);
--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"];
@@ -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
@@ -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());
@@ -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, [[ <gateway name="]] .. string.lower(field.gateway_uuid) .. [[">]]);
if (string.len(field.username) > 0) then
@@ -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());
@@ -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, [[<?xml version="1.0" encoding="UTF-8" standalone="no"?>]])
@@ -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, [[ </users>]])
@@ -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, [[<?xml version="1.0" encoding="UTF-8" standalone="no"?>]])
@@ -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, [[ </users>]])
@@ -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, [[<?xml version="1.0" encoding="UTF-8" standalone="no"?>]]);
table.insert(xml, [[<document type="freeswitch/xml">]]);
table.insert(xml, [[ <section name="directory">]]);
sql = "SELECT domain_name FROM v_domains ";
local sql = "SELECT domain_name FROM v_domains ";
dbh:query(sql, function(row)
table.insert(xml, [[ <domain name="]]..row.domain_name..[[" />]]);
end);
@@ -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);
@@ -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, [[<document type="freeswitch/xml">]]);
table.insert(xml, [[ <section name="directory">]]);
table.insert(xml, [[ <domain name="]] .. domain_name .. [[" alias="true">]]);
table.insert(xml, [[ <user id="]] .. extension .. [[">]]);
table.insert(xml, [[ <user id="]] .. extension .. [["]] .. number_alias .. [[>]]);
table.insert(xml, [[ <params>]]);
table.insert(xml, [[ <param name="reverse-auth-user" value="]] .. extension .. [["/>]]);
table.insert(xml, [[ <param name="reverse-auth-pass" value="]] .. password .. [["/>]]);
@@ -1,6 +1,6 @@
-- xml_handler.lua
-- Part of FusionPBX
-- Copyright (C) 2013 - 2015 Mark J Crane <markjcrane@fusionpbx.com>
-- Copyright (C) 2013 - 2016 Mark J Crane <markjcrane@fusionpbx.com>
-- 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, [[ <variable name="call_timeout" value="]] .. call_timeout .. [["/>]]);
table.insert(xml, [[ <variable name="caller_id_name" value="]] .. sip_from_user .. [["/>]]);
table.insert(xml, [[ <variable name="caller_id_number" value="]] .. sip_from_number .. [["/>]]);
table.insert(xml, [[ <variable name="presence_id" value="]] .. presence_id .. [["/>]]);
if (string.len(call_group) > 0) then
table.insert(xml, [[ <variable name="call_group" value="]] .. call_group .. [["/>]]);
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("'", "&#39;").."' "..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("'", "&#39;").."' "..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("'", "&#39;").."' "..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
@@ -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, [[ <phrases>]]);
table.insert(xml, [[ <macros>]]);
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