2009-09-25 19:48:46 +00:00
/*
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
2014-02-05 21:02:28 +00:00
* Copyright ( C ) 2005 - 2014 , Anthony Minessale II < anthm @ freeswitch . org >
2009-09-25 19:48:46 +00:00
*
* 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 FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II < anthm @ freeswitch . org >
* Portions created by the Initial Developer are Copyright ( C )
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
*
* Marc Olivier Chouinard < mochouinard at moctel dot com >
2014-02-14 00:03:11 +00:00
* Emmanuel Schmidbauer < e . schmidbauer @ gmail . com >
2009-09-25 19:48:46 +00:00
*
*
* mod_directory . c - - Search by Name Directory IVR
*
*/
# include <switch.h>
/* Prototypes */
SWITCH_MODULE_SHUTDOWN_FUNCTION ( mod_directory_shutdown ) ;
SWITCH_MODULE_LOAD_FUNCTION ( mod_directory_load ) ;
SWITCH_MODULE_DEFINITION ( mod_directory , mod_directory_load , mod_directory_shutdown , NULL ) ;
static const char * global_cf = " directory.conf " ;
static char dir_sql [ ] =
2010-02-06 03:38:24 +00:00
" CREATE TABLE directory_search ( \n "
" hostname VARCHAR(255), \n "
" uuid VARCHAR(255), \n "
" extension VARCHAR(255), \n "
" full_name VARCHAR(255), \n "
" full_name_digit VARCHAR(255), \n "
" first_name VARCHAR(255), \n "
" first_name_digit VARCHAR(255), \n "
" last_name VARCHAR(255), \n "
" last_name_digit VARCHAR(255), \n " " name_visible INTEGER, \n " " exten_visible INTEGER \n " " ); \n " ;
2009-09-25 19:48:46 +00:00
# define DIR_RESULT_ITEM "directory_result_item"
# define DIR_RESULT_SAY_NAME "directory_result_say_name"
# define DIR_RESULT_AT "directory_result_at"
# define DIR_RESULT_MENU "directory_result_menu"
# define DIR_INTRO "directory_intro"
# define DIR_MIN_SEARCH_DIGITS "directory_min_search_digits"
# define DIR_RESULT_COUNT "directory_result_count"
# define DIR_RESULT_COUNT_TOO_LARGE "directory_result_count_too_large"
# define DIR_RESULT_LAST "directory_result_last"
static switch_xml_config_string_options_t config_dtmf = { NULL , 2 , " [0-9# \\ *] " } ;
static switch_xml_config_int_options_t config_int_digit_timeout = { SWITCH_TRUE , 0 , SWITCH_TRUE , 30000 } ;
static switch_xml_config_int_options_t config_int_ht_0 = { SWITCH_TRUE , 0 } ;
static struct {
switch_hash_t * profile_hash ;
2011-04-29 15:24:50 +00:00
const char * hostname ;
2009-09-25 19:48:46 +00:00
int integer ;
int debug ;
char * dbname ;
switch_mutex_t * mutex ;
switch_memory_pool_t * pool ;
2011-12-18 05:22:24 +00:00
char odbc_dsn [ 1024 ] ;
2009-09-25 19:48:46 +00:00
} globals ;
# define DIR_PROFILE_CONFIGITEM_COUNT 100
struct dir_profile {
char * name ;
char next_key [ 2 ] ;
char prev_key [ 2 ] ;
char select_name_key [ 2 ] ;
char new_search_key [ 2 ] ;
char terminator_key [ 2 ] ;
char switch_order_key [ 2 ] ;
char * search_order ;
uint32_t min_search_digits ;
uint32_t max_menu_attempt ;
uint32_t digit_timeout ;
uint32_t max_result ;
2014-02-14 00:03:11 +00:00
switch_bool_t use_number_alias ;
2009-09-25 19:48:46 +00:00
switch_mutex_t * mutex ;
switch_thread_rwlock_t * rwlock ;
switch_memory_pool_t * pool ;
switch_xml_config_item_t config [ DIR_PROFILE_CONFIGITEM_COUNT ] ;
switch_xml_config_string_options_t config_str_pool ;
uint32_t flags ;
} ;
typedef struct dir_profile dir_profile_t ;
typedef enum {
PFLAG_DESTROY = 1 < < 0
} dir_flags_t ;
2010-02-06 03:38:24 +00:00
static int digit_matching_keypad ( char letter )
{
2009-09-25 19:48:46 +00:00
int result = - 1 ;
2010-02-06 03:38:24 +00:00
switch ( toupper ( letter ) ) {
case ' A ' :
case ' B ' :
case ' C ' :
result = 2 ;
break ;
case ' D ' :
case ' E ' :
case ' F ' :
result = 3 ;
break ;
case ' G ' :
case ' H ' :
case ' I ' :
result = 4 ;
break ;
case ' J ' :
case ' K ' :
case ' L ' :
result = 5 ;
break ;
case ' M ' :
case ' N ' :
case ' O ' :
result = 6 ;
break ;
case ' P ' :
case ' Q ' :
case ' R ' :
case ' S ' :
result = 7 ;
break ;
case ' T ' :
case ' U ' :
case ' V ' :
result = 8 ;
break ;
case ' W ' :
case ' X ' :
case ' Y ' :
case ' Z ' :
result = 9 ;
break ;
2009-09-25 19:48:46 +00:00
}
return result ;
}
char * string_to_keypad_digit ( const char * in )
{
const char * s = NULL ;
char * dst = NULL ;
char * d = NULL ;
if ( in ) {
s = in ;
dst = strdup ( in ) ;
d = dst ;
while ( * s ) {
char c ;
2014-01-22 21:28:53 +00:00
if ( ( c = ( char ) digit_matching_keypad ( * s + + ) ) > 0 ) {
2009-09-25 19:48:46 +00:00
* d + + = c + 48 ;
}
}
if ( * d ) {
* d = ' \0 ' ;
}
2010-02-06 03:38:24 +00:00
}
2009-09-25 19:48:46 +00:00
return dst ;
}
2011-12-18 05:22:24 +00:00
switch_cache_db_handle_t * directory_get_db_handle ( void )
{
switch_cache_db_handle_t * dbh = NULL ;
2012-10-10 01:20:32 +00:00
char * dsn ;
2011-12-18 05:22:24 +00:00
if ( ! zstr ( globals . odbc_dsn ) ) {
2012-10-10 01:20:32 +00:00
dsn = globals . odbc_dsn ;
2011-12-18 05:22:24 +00:00
} else {
2012-10-10 01:20:32 +00:00
dsn = globals . dbname ;
2011-12-18 05:22:24 +00:00
}
2012-10-10 01:20:32 +00:00
if ( switch_cache_db_get_db_handle_dsn ( & dbh , dsn ) ! = SWITCH_STATUS_SUCCESS ) {
dbh = NULL ;
}
return dbh ;
2011-12-18 05:22:24 +00:00
}
2009-09-25 19:48:46 +00:00
static switch_status_t directory_execute_sql ( char * sql , switch_mutex_t * mutex )
{
2011-12-18 05:22:24 +00:00
switch_cache_db_handle_t * dbh = NULL ;
switch_status_t status = SWITCH_STATUS_FALSE ;
2009-09-25 19:48:46 +00:00
if ( mutex ) {
switch_mutex_lock ( mutex ) ;
}
2011-12-18 05:22:24 +00:00
if ( ! ( dbh = directory_get_db_handle ( ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error Opening DB \n " ) ;
2009-09-25 19:48:46 +00:00
goto end ;
}
2011-12-18 05:22:24 +00:00
if ( globals . debug > 1 ) switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " sql: %s \n " , sql ) ;
status = switch_cache_db_execute_sql ( dbh , sql , NULL ) ;
end :
switch_cache_db_release_db_handle ( & dbh ) ;
2009-09-25 19:48:46 +00:00
if ( mutex ) {
switch_mutex_unlock ( mutex ) ;
}
return status ;
}
typedef enum {
ENTRY_MOVE_NEXT ,
ENTRY_MOVE_PREV
} entry_move_t ;
2013-01-13 05:51:54 +00:00
typedef enum {
SEARCH_BY_FIRST_NAME ,
SEARCH_BY_LAST_NAME ,
SEARCH_BY_FIRST_AND_LAST_NAME ,
SEARCH_BY_FULL_NAME
} search_by_t ;
2009-09-25 19:48:46 +00:00
struct search_params {
char digits [ 255 ] ;
char transfer_to [ 255 ] ;
char domain [ 255 ] ;
char profile [ 255 ] ;
2013-01-13 05:51:54 +00:00
search_by_t search_by ;
2009-09-25 19:48:46 +00:00
int timeout ;
int try_again ;
} ;
typedef struct search_params search_params_t ;
struct listing_callback {
char extension [ 255 ] ;
char fullname [ 255 ] ;
char first_name [ 255 ] ;
char last_name [ 255 ] ;
char transfer_to [ 255 ] ;
int name_visible ;
int exten_visible ;
int new_search ;
int index ;
int want ;
entry_move_t move ;
search_params_t * params ;
} ;
typedef struct listing_callback listing_callback_t ;
static int listing_callback ( void * pArg , int argc , char * * argv , char * * columnNames )
{
listing_callback_t * cbt = ( listing_callback_t * ) pArg ;
if ( cbt - > index + + ! = cbt - > want ) {
return 0 ;
}
switch_copy_string ( cbt - > extension , argv [ 0 ] , 255 ) ;
switch_copy_string ( cbt - > fullname , argv [ 1 ] , 255 ) ;
switch_copy_string ( cbt - > last_name , argv [ 2 ] , 255 ) ;
switch_copy_string ( cbt - > first_name , argv [ 3 ] , 255 ) ;
cbt - > name_visible = atoi ( argv [ 4 ] ) ;
cbt - > exten_visible = atoi ( argv [ 5 ] ) ;
return - 1 ;
}
struct callback {
char * buf ;
size_t len ;
int matches ;
} ;
typedef struct callback callback_t ;
static int sql2str_callback ( void * pArg , int argc , char * * argv , char * * columnNames )
{
callback_t * cbt = ( callback_t * ) pArg ;
switch_copy_string ( cbt - > buf , argv [ 0 ] , cbt - > len ) ;
cbt - > matches + + ;
return 0 ;
}
static switch_bool_t directory_execute_sql_callback ( switch_mutex_t * mutex , char * sql , switch_core_db_callback_func_t callback , void * pdata )
{
switch_bool_t ret = SWITCH_FALSE ;
2012-10-09 15:52:27 +00:00
switch_cache_db_handle_t * dbh = NULL ;
2009-09-25 19:48:46 +00:00
char * errmsg = NULL ;
if ( mutex ) {
switch_mutex_lock ( mutex ) ;
}
2012-10-09 15:52:27 +00:00
if ( ! ( dbh = directory_get_db_handle ( ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error Opening DB \n " ) ;
2009-09-25 19:48:46 +00:00
goto end ;
}
2012-10-09 15:52:27 +00:00
switch_cache_db_execute_sql_callback ( dbh , sql , callback , pdata , & errmsg ) ;
2009-09-25 19:48:46 +00:00
if ( errmsg ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " SQL ERR: [%s] %s \n " , sql , errmsg ) ;
2012-10-09 15:52:27 +00:00
free ( errmsg ) ;
2009-09-25 19:48:46 +00:00
}
2012-10-09 15:52:27 +00:00
end :
switch_cache_db_release_db_handle ( & dbh ) ;
2009-09-25 19:48:46 +00:00
if ( mutex ) {
switch_mutex_unlock ( mutex ) ;
}
return ret ;
}
# define DIR_DESC "directory"
2011-07-08 10:42:31 +00:00
# define DIR_USAGE "<profile_name> <domain_name> [<context_name>] | [<dialplan_name> <context_name>]"
2009-09-25 19:48:46 +00:00
static void free_profile ( dir_profile_t * profile )
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Destroying Profile %s \n " , profile - > name ) ;
switch_core_destroy_memory_pool ( & profile - > pool ) ;
}
static void profile_rwunlock ( dir_profile_t * profile )
{
switch_thread_rwlock_unlock ( profile - > rwlock ) ;
if ( switch_test_flag ( profile , PFLAG_DESTROY ) ) {
if ( switch_thread_rwlock_tryrdlock ( profile - > rwlock ) = = SWITCH_STATUS_SUCCESS ) {
free_profile ( profile ) ;
}
}
}
dir_profile_t * profile_set_config ( dir_profile_t * profile )
{
int i = 0 ;
profile - > config_str_pool . pool = profile - > pool ;
2010-02-06 03:38:24 +00:00
SWITCH_CONFIG_SET_ITEM ( profile - > config [ i + + ] , " next-key " , SWITCH_CONFIG_STRING , CONFIG_RELOADABLE , & profile - > next_key , " 6 " , & config_dtmf , NULL , NULL ) ;
SWITCH_CONFIG_SET_ITEM ( profile - > config [ i + + ] , " prev-key " , SWITCH_CONFIG_STRING , CONFIG_RELOADABLE , & profile - > prev_key , " 4 " , & config_dtmf , NULL , NULL ) ;
2009-09-25 19:48:46 +00:00
SWITCH_CONFIG_SET_ITEM ( profile - > config [ i + + ] , " terminator-key " , SWITCH_CONFIG_STRING , CONFIG_RELOADABLE ,
2010-02-06 03:38:24 +00:00
& profile - > terminator_key , " # " , & config_dtmf , NULL , NULL ) ;
2009-09-25 19:48:46 +00:00
SWITCH_CONFIG_SET_ITEM ( profile - > config [ i + + ] , " switch-order-key " , SWITCH_CONFIG_STRING , CONFIG_RELOADABLE ,
2010-02-06 03:38:24 +00:00
& profile - > switch_order_key , " * " , & config_dtmf , NULL , NULL ) ;
2009-09-25 19:48:46 +00:00
SWITCH_CONFIG_SET_ITEM ( profile - > config [ i + + ] , " select-name-key " , SWITCH_CONFIG_STRING , CONFIG_RELOADABLE ,
2010-02-06 03:38:24 +00:00
& profile - > select_name_key , " 1 " , & config_dtmf , NULL , NULL ) ;
2009-09-25 19:48:46 +00:00
SWITCH_CONFIG_SET_ITEM ( profile - > config [ i + + ] , " new-search-key " , SWITCH_CONFIG_STRING , CONFIG_RELOADABLE ,
2010-02-06 03:38:24 +00:00
& profile - > new_search_key , " 3 " , & config_dtmf , NULL , NULL ) ;
2009-09-25 19:48:46 +00:00
SWITCH_CONFIG_SET_ITEM ( profile - > config [ i + + ] , " search-order " , SWITCH_CONFIG_STRING , CONFIG_RELOADABLE ,
2010-02-06 03:38:24 +00:00
& profile - > search_order , " last_name " , & profile - > config_str_pool , NULL , NULL ) ;
2009-09-25 19:48:46 +00:00
SWITCH_CONFIG_SET_ITEM ( profile - > config [ i + + ] , " digit-timeout " , SWITCH_CONFIG_INT , CONFIG_RELOADABLE ,
2010-02-06 03:38:24 +00:00
& profile - > digit_timeout , 3000 , & config_int_digit_timeout , NULL , NULL ) ;
2009-09-25 19:48:46 +00:00
SWITCH_CONFIG_SET_ITEM ( profile - > config [ i + + ] , " min-search-digits " , SWITCH_CONFIG_INT , CONFIG_RELOADABLE ,
2010-02-06 03:38:24 +00:00
& profile - > min_search_digits , 3 , & config_int_ht_0 , NULL , NULL ) ;
2009-09-25 19:48:46 +00:00
SWITCH_CONFIG_SET_ITEM ( profile - > config [ i + + ] , " max-menu-attempts " , SWITCH_CONFIG_INT , CONFIG_RELOADABLE ,
2010-02-06 03:38:24 +00:00
& profile - > max_menu_attempt , 3 , & config_int_ht_0 , NULL , NULL ) ;
2009-09-25 19:48:46 +00:00
SWITCH_CONFIG_SET_ITEM ( profile - > config [ i + + ] , " max-result " , SWITCH_CONFIG_INT , CONFIG_RELOADABLE ,
2010-02-06 03:38:24 +00:00
& profile - > max_result , 5 , & config_int_ht_0 , NULL , NULL ) ;
2014-02-14 00:03:11 +00:00
SWITCH_CONFIG_SET_ITEM ( profile - > config [ i + + ] , " use-number-alias " , SWITCH_CONFIG_BOOL , CONFIG_RELOADABLE ,
& profile - > use_number_alias , SWITCH_FALSE , NULL , NULL , NULL ) ;
2009-09-25 19:48:46 +00:00
return profile ;
}
2010-02-06 03:38:24 +00:00
static dir_profile_t * load_profile ( const char * profile_name )
2009-09-25 19:48:46 +00:00
{
dir_profile_t * profile = NULL ;
switch_xml_t x_profiles , x_profile , cfg , xml = NULL ;
switch_event_t * event = NULL ;
if ( ! ( xml = switch_xml_open_cfg ( global_cf , & cfg , NULL ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Open of %s failed \n " , global_cf ) ;
return profile ;
}
if ( ! ( x_profiles = switch_xml_child ( cfg , " profiles " ) ) ) {
goto end ;
}
if ( ( x_profile = switch_xml_find_child ( x_profiles , " profile " , " name " , profile_name ) ) ) {
switch_memory_pool_t * pool ;
int count ;
if ( switch_core_new_memory_pool ( & pool ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Pool Failure \n " ) ;
goto end ;
}
if ( ! ( profile = switch_core_alloc ( pool , sizeof ( dir_profile_t ) ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Alloc Failure \n " ) ;
switch_core_destroy_memory_pool ( & pool ) ;
goto end ;
}
profile - > pool = pool ;
profile_set_config ( profile ) ;
/* Add the params to the event structure */
2010-09-29 20:47:58 +00:00
count = ( int ) switch_event_import_xml ( switch_xml_child ( x_profile , " param " ) , " name " , " value " , & event ) ;
2009-09-25 19:48:46 +00:00
if ( switch_xml_config_parse_event ( event , count , SWITCH_FALSE , profile - > config ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Failed to process configuration \n " ) ;
switch_core_destroy_memory_pool ( & pool ) ;
goto end ;
}
switch_thread_rwlock_create ( & profile - > rwlock , pool ) ;
profile - > name = switch_core_strdup ( pool , profile_name ) ;
switch_mutex_init ( & profile - > mutex , SWITCH_MUTEX_NESTED , profile - > pool ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " Added Profile %s \n " , profile - > name ) ;
switch_core_hash_insert ( globals . profile_hash , profile - > name , profile ) ;
}
2010-02-06 03:38:24 +00:00
end :
2009-09-25 19:48:46 +00:00
switch_xml_free ( xml ) ;
return profile ;
}
static switch_status_t load_config ( switch_bool_t reload )
{
2011-12-18 05:22:24 +00:00
switch_status_t status = SWITCH_STATUS_SUCCESS ;
2009-09-25 19:48:46 +00:00
switch_xml_t cfg , xml = NULL , settings , param , x_profiles , x_profile ;
2011-12-18 05:22:24 +00:00
switch_cache_db_handle_t * dbh = NULL ;
2009-09-25 19:48:46 +00:00
if ( ! ( xml = switch_xml_open_cfg ( global_cf , & cfg , NULL ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Open of %s failed \n " , global_cf ) ;
return SWITCH_STATUS_TERM ;
}
switch_mutex_lock ( globals . mutex ) ;
if ( ( settings = switch_xml_child ( cfg , " settings " ) ) ) {
for ( param = switch_xml_child ( settings , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
2011-12-18 05:22:24 +00:00
if ( ! strcasecmp ( var , " odbc-dsn " ) & & ! zstr ( val ) ) {
2013-09-12 20:10:54 +00:00
if ( switch_odbc_available ( ) | | switch_pgsql_available ( ) ) {
2011-12-18 05:22:24 +00:00
switch_set_string ( globals . odbc_dsn , val ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " ODBC IS NOT AVAILABLE! \n " ) ;
}
} else if ( ! strcasecmp ( var , " dbname " ) & & ! zstr ( val ) ) {
globals . dbname = switch_core_strdup ( globals . pool , val ) ;
}
2009-09-25 19:48:46 +00:00
if ( ! strcasecmp ( var , " debug " ) ) {
globals . debug = atoi ( val ) ;
}
}
}
if ( ( x_profiles = switch_xml_child ( cfg , " profiles " ) ) ) {
for ( x_profile = switch_xml_child ( x_profiles , " profile " ) ; x_profile ; x_profile = x_profile - > next ) {
load_profile ( switch_xml_attr_soft ( x_profile , " name " ) ) ;
}
}
2011-12-18 05:22:24 +00:00
if ( zstr ( globals . odbc_dsn ) & & zstr ( globals . dbname ) ) {
globals . dbname = switch_core_sprintf ( globals . pool , " directory " ) ;
}
dbh = directory_get_db_handle ( ) ;
if ( dbh ) {
if ( ! reload ) {
switch_cache_db_test_reactive ( dbh , " delete from directory_search where uuid != '' and name_visible != '' " , " drop table directory_search " , dir_sql ) ;
}
switch_cache_db_release_db_handle ( & dbh ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Cannot open DB!2 \n " ) ;
status = SWITCH_STATUS_TERM ;
goto end ;
}
end :
2009-09-25 19:48:46 +00:00
switch_mutex_unlock ( globals . mutex ) ;
switch_xml_free ( xml ) ;
2011-12-18 05:22:24 +00:00
return status ;
2009-09-25 19:48:46 +00:00
}
2010-02-06 03:38:24 +00:00
static dir_profile_t * get_profile ( const char * profile_name )
2009-09-25 19:48:46 +00:00
{
dir_profile_t * profile = NULL ;
switch_mutex_lock ( globals . mutex ) ;
if ( ! ( profile = switch_core_hash_find ( globals . profile_hash , profile_name ) ) ) {
profile = load_profile ( profile_name ) ;
}
if ( profile ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " [%s] rwlock \n " , profile - > name ) ;
switch_thread_rwlock_rdlock ( profile - > rwlock ) ;
}
switch_mutex_unlock ( globals . mutex ) ;
return profile ;
}
2014-04-25 20:53:11 +00:00
char * generate_sql_entry_for_user ( switch_core_session_t * session , switch_xml_t ut , switch_bool_t use_number_alias ) {
char * sql = NULL ;
int name_visible = 1 ;
int exten_visible = 1 ;
const char * id = switch_xml_attr_soft ( ut , " id " ) ;
const char * number_alias = switch_xml_attr_soft ( ut , " number-alias " ) ;
const char * extension = NULL ;
char * fullName = NULL ;
char * caller_name = NULL ;
char * caller_name_override = NULL ;
char * firstName = NULL ;
char * lastName = NULL ;
char * fullNameDigit = NULL ;
char * firstNameDigit = NULL ;
char * lastNameDigit = NULL ;
switch_xml_t x_params , x_param , x_vars , x_var ;
/* Check all the user params */
if ( ( x_params = switch_xml_child ( ut , " params " ) ) ) {
for ( x_param = switch_xml_child ( x_params , " param " ) ; x_param ; x_param = x_param - > next ) {
const char * var = switch_xml_attr_soft ( x_param , " name " ) ;
const char * val = switch_xml_attr_soft ( x_param , " value " ) ;
if ( ! strcasecmp ( var , " directory-visible " ) ) {
name_visible = switch_true ( val ) ;
}
if ( ! strcasecmp ( var , " directory-exten-visible " ) ) {
exten_visible = switch_true ( val ) ;
}
}
}
/* Check all the user variables */
if ( ( x_vars = switch_xml_child ( ut , " variables " ) ) ) {
for ( x_var = switch_xml_child ( x_vars , " variable " ) ; x_var ; x_var = x_var - > next ) {
const char * var = switch_xml_attr_soft ( x_var , " name " ) ;
const char * val = switch_xml_attr_soft ( x_var , " value " ) ;
if ( ! strcasecmp ( var , " effective_caller_id_name " ) ) {
caller_name = switch_core_session_strdup ( session , val ) ;
}
if ( ! strcasecmp ( var , " directory_full_name " ) ) {
caller_name_override = switch_core_session_strdup ( session , val ) ;
}
}
}
if ( caller_name_override ) {
fullName = caller_name_override ;
} else {
fullName = caller_name ;
}
if ( zstr ( fullName ) ) {
goto end ;
}
firstName = switch_core_session_strdup ( session , fullName ) ;
if ( ( lastName = strrchr ( firstName , ' ' ) ) ) {
* lastName + + = ' \0 ' ;
} else {
lastName = switch_core_session_strdup ( session , firstName ) ;
}
/* switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "FullName %s firstName [%s] lastName [%s]\n", fullName, firstName, lastName); */
if ( use_number_alias = = SWITCH_TRUE & & ! zstr ( number_alias ) ) {
extension = number_alias ;
} else {
extension = id ;
}
/* Generate Digits key mapping */
fullNameDigit = string_to_keypad_digit ( fullName ) ;
lastNameDigit = string_to_keypad_digit ( lastName ) ;
firstNameDigit = string_to_keypad_digit ( firstName ) ;
/* add user into DB */
sql = switch_mprintf ( " insert into directory_search values('%q','%q','%q','%q','%q','%q','%q','%q','%q','%d','%d') " ,
globals . hostname , switch_core_session_get_uuid ( session ) , extension , fullName , fullNameDigit , firstName , firstNameDigit ,
lastName , lastNameDigit , name_visible , exten_visible ) ;
switch_safe_free ( fullNameDigit ) ;
switch_safe_free ( lastNameDigit ) ;
switch_safe_free ( firstNameDigit ) ;
end :
return sql ;
}
2010-02-06 03:38:24 +00:00
static switch_status_t populate_database ( switch_core_session_t * session , dir_profile_t * profile , const char * domain_name )
{
2009-09-25 19:48:46 +00:00
switch_status_t status = SWITCH_STATUS_SUCCESS ;
char * sql = NULL ;
char * sqlvalues = NULL ;
char * sqltmp = NULL ;
2014-04-25 20:53:11 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
const char * group_selection = switch_channel_get_variable ( channel , " directory_group_selection " ) ;
2013-01-18 05:06:05 +00:00
int count = 0 ;
2009-09-25 19:48:46 +00:00
switch_xml_t xml_root = NULL , x_domain ;
switch_xml_t ut ;
switch_event_t * xml_params = NULL ;
2014-04-25 20:53:11 +00:00
switch_xml_t group = NULL , groups = NULL , users = NULL ;
2009-09-25 19:48:46 +00:00
switch_event_create ( & xml_params , SWITCH_EVENT_REQUEST_PARAMS ) ;
switch_assert ( xml_params ) ;
if ( switch_xml_locate_domain ( domain_name , xml_params , & xml_root , & x_domain ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Cannot locate domain %s \n " , domain_name ) ;
status = SWITCH_STATUS_FALSE ;
goto end ;
}
if ( ( groups = switch_xml_child ( x_domain , " groups " ) ) ) {
for ( group = switch_xml_child ( groups , " group " ) ; group ; group = group - > next ) {
2014-04-25 20:53:11 +00:00
const char * gname = switch_xml_attr_soft ( group , " name " ) ;
if ( group_selection & & strcasecmp ( gname , group_selection ) ) {
continue ;
}
2009-09-25 19:48:46 +00:00
if ( ( users = switch_xml_child ( group , " users " ) ) ) {
for ( ut = switch_xml_child ( users , " user " ) ; ut ; ut = ut - > next ) {
2014-04-25 20:53:11 +00:00
const char * uname = switch_xml_attr_soft ( ut , " id " ) ;
2009-09-25 19:48:46 +00:00
const char * type = switch_xml_attr_soft ( ut , " type " ) ;
if ( ! strcasecmp ( type , " pointer " ) ) {
2014-04-25 20:53:11 +00:00
switch_xml_t ux ;
2009-09-25 19:48:46 +00:00
2014-04-25 20:53:11 +00:00
if ( switch_xml_locate_user_merged ( " id " , uname , domain_name , NULL , & ux , NULL ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_WARNING , " Can't find user [%s@%s] from pointer \n " , uname , domain_name ) ;
} else {
sql = generate_sql_entry_for_user ( session , ux , profile - > use_number_alias ) ;
switch_xml_free ( ux ) ;
2009-09-25 19:48:46 +00:00
}
2014-04-25 20:53:11 +00:00
2009-09-25 19:48:46 +00:00
} else {
2014-04-25 20:53:11 +00:00
sql = generate_sql_entry_for_user ( session , ut , profile - > use_number_alias ) ;
2009-09-25 19:48:46 +00:00
}
2014-04-25 20:53:11 +00:00
if ( sql ) {
if ( sqlvalues ) {
sqltmp = sqlvalues ;
sqlvalues = switch_mprintf ( " %s;%s " , sqltmp , sql ) ;
switch_safe_free ( sqltmp ) ;
switch_safe_free ( sql ) ;
} else {
sqlvalues = sql ;
sql = NULL ;
}
2009-09-25 19:48:46 +00:00
}
2013-01-18 05:06:05 +00:00
if ( + + count > = 100 ) {
count = 0 ;
sql = switch_mprintf ( " BEGIN;%s;COMMIT; " , sqlvalues ) ;
directory_execute_sql ( sql , globals . mutex ) ;
switch_safe_free ( sql ) ;
switch_safe_free ( sqlvalues ) ;
}
2009-09-25 19:48:46 +00:00
}
}
}
}
2013-01-18 05:06:05 +00:00
if ( sqlvalues ) {
sql = switch_mprintf ( " BEGIN;%s;COMMIT; " , sqlvalues ) ;
directory_execute_sql ( sql , globals . mutex ) ;
}
2010-02-06 03:38:24 +00:00
end :
2009-09-25 19:48:46 +00:00
switch_safe_free ( sql ) ;
switch_safe_free ( sqlvalues ) ;
switch_event_destroy ( & xml_params ) ;
switch_xml_free ( xml_root ) ;
return status ;
}
struct cb_result {
char digits [ 255 ] ;
char digit ;
dir_profile_t * profile ;
} ;
typedef struct cb_result cbr_t ;
static switch_status_t on_dtmf ( switch_core_session_t * session , void * input , switch_input_type_t itype , void * buf , unsigned int buflen )
{
switch ( itype ) {
2010-02-06 03:38:24 +00:00
case SWITCH_INPUT_TYPE_DTMF :
{
switch_dtmf_t * dtmf = ( switch_dtmf_t * ) input ;
cbr_t * cbr = ( cbr_t * ) buf ;
cbr - > digit = dtmf - > digit ;
if ( dtmf - > digit = = * cbr - > profile - > terminator_key | | dtmf - > digit = = * cbr - > profile - > switch_order_key ) {
return SWITCH_STATUS_BREAK ;
}
2009-09-25 19:48:46 +00:00
2010-02-06 03:38:24 +00:00
if ( strlen ( cbr - > digits ) < sizeof ( cbr - > digits ) - 2 ) {
2010-09-29 20:47:58 +00:00
int at = ( int ) strlen ( cbr - > digits ) ;
2010-02-06 03:38:24 +00:00
cbr - > digits [ at + + ] = dtmf - > digit ;
cbr - > digits [ at ] = ' \0 ' ;
} else {
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " DTMF buffer is full \n " ) ;
return SWITCH_STATUS_BREAK ;
2009-09-25 19:48:46 +00:00
}
2010-02-06 03:38:24 +00:00
}
break ;
default :
break ;
2009-09-25 19:48:46 +00:00
}
return SWITCH_STATUS_BREAK ;
}
static switch_status_t listen_entry ( switch_core_session_t * session , dir_profile_t * profile , listing_callback_t * cbt )
{
char buf [ 2 ] = " " ;
char macro [ 256 ] = " " ;
char recorded_name [ 256 ] = " " ;
/* Try to use the recorded name from voicemail if it exist */
if ( switch_loadable_module_exists ( " mod_voicemail " ) = = SWITCH_STATUS_SUCCESS ) {
char * cmd = NULL ;
switch_stream_handle_t stream = { 0 } ;
SWITCH_STANDARD_STREAM ( stream ) ;
cmd = switch_core_session_sprintf ( session , " %s/%s@%s|name_path " , cbt - > params - > profile , cbt - > extension , cbt - > params - > domain ) ;
switch_api_execute ( " vm_prefs " , cmd , session , & stream ) ;
if ( strncmp ( " -ERR " , stream . data , 4 ) ) {
switch_copy_string ( recorded_name , ( char * ) stream . data , sizeof ( recorded_name ) ) ;
}
switch_safe_free ( stream . data ) ;
}
2009-10-23 16:03:42 +00:00
if ( zstr_buf ( buf ) ) {
2010-02-06 03:38:24 +00:00
switch_snprintf ( macro , sizeof ( macro ) , " phrase:%s:%d " , DIR_RESULT_ITEM , cbt - > want + 1 ) ;
2010-09-23 23:37:45 +00:00
switch_ivr_read ( session , 0 , 1 , macro , NULL , buf , sizeof ( buf ) , 1 , profile - > terminator_key , 0 ) ;
2009-09-25 19:48:46 +00:00
}
2009-10-23 16:03:42 +00:00
if ( ! zstr_buf ( recorded_name ) & & zstr_buf ( buf ) ) {
2010-09-23 23:37:45 +00:00
switch_ivr_read ( session , 0 , 1 , recorded_name , NULL , buf , sizeof ( buf ) , 1 , profile - > terminator_key , 0 ) ;
2009-09-25 19:48:46 +00:00
}
2009-10-23 16:03:42 +00:00
if ( zstr_buf ( recorded_name ) & & zstr_buf ( buf ) ) {
2009-09-25 19:48:46 +00:00
switch_snprintf ( macro , sizeof ( macro ) , " phrase:%s:%s " , DIR_RESULT_SAY_NAME , cbt - > fullname ) ;
2010-09-23 23:37:45 +00:00
switch_ivr_read ( session , 0 , 1 , macro , NULL , buf , sizeof ( buf ) , 1 , profile - > terminator_key , 0 ) ;
2009-09-25 19:48:46 +00:00
}
2009-10-23 16:03:42 +00:00
if ( cbt - > exten_visible & & zstr_buf ( buf ) ) {
2009-09-25 19:48:46 +00:00
switch_snprintf ( macro , sizeof ( macro ) , " phrase:%s:%s " , DIR_RESULT_AT , cbt - > extension ) ;
2010-09-23 23:37:45 +00:00
switch_ivr_read ( session , 0 , 1 , macro , NULL , buf , sizeof ( buf ) , 1 , profile - > terminator_key , 0 ) ;
2009-09-25 19:48:46 +00:00
}
2009-10-23 16:03:42 +00:00
if ( zstr_buf ( buf ) ) {
2010-02-06 03:38:24 +00:00
switch_snprintf ( macro , sizeof ( macro ) , " phrase:%s:%c,%c,%c,%c " , DIR_RESULT_MENU , * profile - > select_name_key , * profile - > next_key , * profile - > prev_key ,
* profile - > new_search_key ) ;
2010-09-23 23:37:45 +00:00
switch_ivr_read ( session , 0 , 1 , macro , NULL , buf , sizeof ( buf ) , profile - > digit_timeout , profile - > terminator_key , 0 ) ;
2009-09-25 19:48:46 +00:00
}
2009-10-23 16:03:42 +00:00
if ( ! zstr_buf ( buf ) ) {
2009-09-25 19:48:46 +00:00
if ( buf [ 0 ] = = * profile - > select_name_key ) {
switch_copy_string ( cbt - > transfer_to , cbt - > extension , 255 ) ;
}
if ( buf [ 0 ] = = * profile - > new_search_key ) {
cbt - > new_search = 1 ;
}
if ( buf [ 0 ] = = * profile - > prev_key ) {
cbt - > move = ENTRY_MOVE_PREV ;
}
} else {
return SWITCH_STATUS_TIMEOUT ;
}
return SWITCH_STATUS_SUCCESS ;
}
2010-02-06 03:38:24 +00:00
switch_status_t gather_name_digit ( switch_core_session_t * session , dir_profile_t * profile , search_params_t * params )
{
2009-09-25 19:48:46 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
switch_status_t status = SWITCH_STATUS_SUCCESS ;
cbr_t cbr ;
int loop = 1 ;
switch_input_args_t args = { 0 } ;
args . input_callback = on_dtmf ;
args . buf = & cbr ;
while ( switch_channel_ready ( channel ) & & loop ) {
char macro [ 255 ] ;
loop = 0 ;
memset ( & cbr , 0 , sizeof ( cbr ) ) ;
cbr . profile = profile ;
params - > timeout = 0 ;
/* Gather the user Name */
2013-01-13 05:51:54 +00:00
switch_snprintf ( macro , sizeof ( macro ) , " %s:%c " , ( params - > search_by = = SEARCH_BY_LAST_NAME ? " last_name " : " first_name " ) , * profile - > switch_order_key ) ;
2009-09-25 19:48:46 +00:00
switch_ivr_phrase_macro ( session , DIR_INTRO , macro , NULL , & args ) ;
while ( switch_channel_ready ( channel ) ) {
if ( cbr . digit = = * profile - > terminator_key ) {
status = SWITCH_STATUS_BREAK ;
break ;
}
if ( cbr . digit = = * profile - > switch_order_key ) {
2013-01-13 05:51:54 +00:00
if ( params - > search_by = = SEARCH_BY_LAST_NAME ) {
params - > search_by = SEARCH_BY_FIRST_NAME ;
2009-09-25 19:48:46 +00:00
} else {
2013-01-13 05:51:54 +00:00
params - > search_by = SEARCH_BY_LAST_NAME ;
2009-09-25 19:48:46 +00:00
}
loop = 1 ;
break ;
}
if ( switch_ivr_collect_digits_callback ( session , & args , profile - > digit_timeout , 0 ) = = SWITCH_STATUS_TIMEOUT ) {
params - > timeout = 1 ;
break ;
}
}
}
switch_copy_string ( params - > digits , cbr . digits , 255 ) ;
return status ;
}
2010-02-06 03:38:24 +00:00
switch_status_t navigate_entrys ( switch_core_session_t * session , dir_profile_t * profile , search_params_t * params )
{
2009-09-25 19:48:46 +00:00
switch_status_t status = SWITCH_STATUS_SUCCESS ;
2013-01-13 05:51:54 +00:00
char * sql = NULL , * sql_where = NULL ;
2009-09-25 19:48:46 +00:00
char entry_count [ 80 ] = " " ;
callback_t cbt = { 0 } ;
int result_count ;
char macro [ 256 ] = " " ;
listing_callback_t listing_cbt ;
int cur_entry = 0 ;
cbt . buf = entry_count ;
cbt . len = sizeof ( entry_count ) ;
2013-01-13 05:51:54 +00:00
if ( params - > search_by = = SEARCH_BY_FIRST_AND_LAST_NAME ) {
2016-11-11 17:27:35 +00:00
sql_where = switch_mprintf ( " hostname = '%q' and uuid = '%q' and name_visible = 1 and (%q like '%q%%' or %q like '%q%%') " ,
2013-01-13 05:51:54 +00:00
globals . hostname , switch_core_session_get_uuid ( session ) , " last_name_digit " , params - > digits , " first_name_digit " , params - > digits ) ;
} else if ( params - > search_by = = SEARCH_BY_FULL_NAME ) {
sql_where = switch_mprintf ( " hostname = '%q' and uuid = '%q' and name_visible = 1 and full_name_digit like '%%%q%%' " ,
2016-11-11 17:27:35 +00:00
globals . hostname , switch_core_session_get_uuid ( session ) , params - > digits ) ;
} else if ( params - > search_by = = SEARCH_BY_LAST_NAME ) {
sql_where = switch_mprintf ( " hostname = '%q' and uuid = '%q' and name_visible = 1 and last_name_digit like '%q%%' " ,
globals . hostname , switch_core_session_get_uuid ( session ) , params - > digits ) ;
2013-01-13 05:51:54 +00:00
} else {
2016-11-11 17:27:35 +00:00
sql_where = switch_mprintf ( " hostname = '%q' and uuid = '%q' and name_visible = 1 and first_name_digit like '%q%%' " ,
globals . hostname , switch_core_session_get_uuid ( session ) , params - > digits ) ;
2013-01-13 05:51:54 +00:00
}
2014-10-14 13:53:12 +00:00
sql = switch_mprintf ( " select count(*) from (select distinct first_name, last_name, extension from directory_search where %s) AS dsearch " , sql_where ) ;
2009-09-25 19:48:46 +00:00
2011-12-18 05:22:24 +00:00
directory_execute_sql_callback ( globals . mutex , sql , sql2str_callback , & cbt ) ;
2009-09-25 19:48:46 +00:00
switch_safe_free ( sql ) ;
result_count = atoi ( entry_count ) ;
if ( result_count = = 0 ) {
switch_snprintf ( macro , sizeof ( macro ) , " %d " , result_count ) ;
switch_ivr_phrase_macro ( session , DIR_RESULT_COUNT , macro , NULL , NULL ) ;
params - > try_again = 1 ;
2013-01-13 05:51:54 +00:00
status = SWITCH_STATUS_BREAK ;
goto end ;
2014-01-22 21:28:53 +00:00
} else if ( profile - > max_result ! = 0 & & ( uint32_t ) result_count > profile - > max_result ) {
2009-09-25 19:48:46 +00:00
switch_ivr_phrase_macro ( session , DIR_RESULT_COUNT_TOO_LARGE , NULL , NULL , NULL ) ;
params - > try_again = 1 ;
2013-01-13 05:51:54 +00:00
status = SWITCH_STATUS_BREAK ;
goto end ;
2009-09-25 19:48:46 +00:00
} else {
switch_snprintf ( macro , sizeof ( macro ) , " %d " , result_count ) ;
switch_ivr_phrase_macro ( session , DIR_RESULT_COUNT , macro , NULL , NULL ) ;
}
memset ( & listing_cbt , 0 , sizeof ( listing_cbt ) ) ;
listing_cbt . params = params ;
2014-04-25 20:53:11 +00:00
sql = switch_mprintf ( " select extension, full_name, last_name, first_name, name_visible, exten_visible from directory_search where %s group by extension, full_name, last_name, first_name, name_visible, exten_visible order by last_name, first_name " , sql_where ) ;
2009-09-25 19:48:46 +00:00
for ( cur_entry = 0 ; cur_entry < result_count ; cur_entry + + ) {
listing_cbt . index = 0 ;
listing_cbt . want = cur_entry ;
listing_cbt . move = ENTRY_MOVE_NEXT ;
2011-12-18 05:22:24 +00:00
directory_execute_sql_callback ( globals . mutex , sql , listing_callback , & listing_cbt ) ;
2009-09-25 19:48:46 +00:00
status = listen_entry ( session , profile , & listing_cbt ) ;
2009-10-23 16:03:42 +00:00
if ( ! zstr ( listing_cbt . transfer_to ) ) {
2009-09-25 19:48:46 +00:00
switch_copy_string ( params - > transfer_to , listing_cbt . transfer_to , 255 ) ;
break ;
}
if ( listing_cbt . new_search ) {
params - > try_again = 1 ;
goto end ;
}
if ( listing_cbt . move = = ENTRY_MOVE_NEXT ) {
if ( cur_entry = = result_count - 1 ) {
switch_snprintf ( macro , sizeof ( macro ) , " %d " , result_count ) ;
switch_ivr_phrase_macro ( session , DIR_RESULT_LAST , macro , NULL , NULL ) ;
cur_entry - = 1 ;
}
}
if ( listing_cbt . move = = ENTRY_MOVE_PREV ) {
if ( cur_entry < = 0 ) {
cur_entry = - 1 ;
} else {
cur_entry - = 2 ;
}
}
if ( status = = SWITCH_STATUS_TIMEOUT ) {
goto end ;
}
if ( status ! = SWITCH_STATUS_SUCCESS & & status ! = SWITCH_STATUS_BREAK ) {
goto end ;
}
}
2010-02-06 03:38:24 +00:00
end :
2009-09-25 19:48:46 +00:00
switch_safe_free ( sql ) ;
2013-01-13 05:51:54 +00:00
switch_safe_free ( sql_where ) ;
2009-09-25 19:48:46 +00:00
return status ;
}
SWITCH_STANDARD_APP ( directory_function )
{
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
int argc = 0 ;
char * argv [ 6 ] = { 0 } ;
char * mydata = NULL ;
const char * profile_name = NULL ;
2010-02-06 03:38:24 +00:00
const char * domain_name = NULL ;
2010-02-26 20:17:31 +00:00
const char * context_name = NULL ;
2011-07-08 10:42:31 +00:00
const char * dialplan_name = NULL ;
2013-01-13 05:51:54 +00:00
const char * search_by = NULL ;
2010-02-06 03:38:24 +00:00
dir_profile_t * profile = NULL ;
2009-09-25 19:48:46 +00:00
int x = 0 ;
char * sql = NULL ;
search_params_t s_param ;
int attempts = 3 ;
char macro [ 255 ] ;
2009-10-23 16:03:42 +00:00
if ( zstr ( data ) ) {
2009-10-04 07:40:12 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Missing profile name \n " ) ;
return ;
2009-09-25 19:48:46 +00:00
}
2009-10-04 07:40:12 +00:00
mydata = switch_core_session_strdup ( session , data ) ;
2010-02-26 20:17:31 +00:00
if ( ( argc = switch_separate_string ( mydata , ' ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ) < 2 ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Not enough args [%s] \n " , data ) ;
return ;
}
2009-10-04 07:40:12 +00:00
2009-09-25 19:48:46 +00:00
if ( argv [ x ] ) {
profile_name = argv [ x + + ] ;
}
if ( argv [ x ] ) {
domain_name = argv [ x + + ] ;
}
2011-07-08 10:42:31 +00:00
if ( argv [ x ] ) {
if ( ! ( argv [ x + 1 ] ) ) {
context_name = argv [ x + + ] ;
} else {
dialplan_name = argv [ x + + ] ;
}
}
2010-02-26 20:17:31 +00:00
if ( argv [ x ] ) {
context_name = argv [ x + + ] ;
}
2009-09-25 19:48:46 +00:00
if ( ! ( profile = get_profile ( profile_name ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Error invalid profile %s \n " , profile_name ) ;
2009-10-04 07:40:12 +00:00
return ;
2009-09-25 19:48:46 +00:00
}
2010-02-26 20:17:31 +00:00
if ( ! context_name ) {
context_name = domain_name ;
}
2011-07-08 10:42:31 +00:00
if ( ! dialplan_name ) {
dialplan_name = " XML " ;
}
2009-09-25 19:48:46 +00:00
populate_database ( session , profile , domain_name ) ;
memset ( & s_param , 0 , sizeof ( s_param ) ) ;
s_param . try_again = 1 ;
switch_copy_string ( s_param . profile , profile_name , 255 ) ;
switch_copy_string ( s_param . domain , domain_name , 255 ) ;
2013-01-13 05:51:54 +00:00
if ( ! ( search_by = switch_channel_get_variable ( channel , " directory_search_order " ) ) ) {
search_by = profile - > search_order ;
2009-09-25 19:48:46 +00:00
}
2013-01-13 05:51:54 +00:00
if ( ! strcasecmp ( search_by , " first_name " ) ) {
s_param . search_by = SEARCH_BY_FIRST_NAME ;
} else if ( ! strcasecmp ( search_by , " first_and_last_name " ) ) {
s_param . search_by = SEARCH_BY_FIRST_AND_LAST_NAME ;
} else {
s_param . search_by = SEARCH_BY_LAST_NAME ;
2010-09-10 02:43:27 +00:00
}
2009-09-25 19:48:46 +00:00
attempts = profile - > max_menu_attempt ;
2010-02-06 03:38:24 +00:00
s_param . try_again = 1 ;
2009-09-25 19:48:46 +00:00
while ( switch_channel_ready ( channel ) & & ( s_param . try_again & & attempts - - > 0 ) ) {
s_param . try_again = 0 ;
gather_name_digit ( session , profile , & s_param ) ;
2009-10-23 16:03:42 +00:00
if ( zstr ( s_param . digits ) ) {
2009-09-25 19:48:46 +00:00
s_param . try_again = 1 ;
continue ;
}
if ( strlen ( s_param . digits ) < profile - > min_search_digits ) {
switch_snprintf ( macro , sizeof ( macro ) , " %d " , profile - > min_search_digits ) ;
switch_ivr_phrase_macro ( session , DIR_MIN_SEARCH_DIGITS , macro , NULL , NULL ) ;
s_param . try_again = 1 ;
continue ;
}
navigate_entrys ( session , profile , & s_param ) ;
}
2009-10-23 16:03:42 +00:00
if ( ! zstr ( s_param . transfer_to ) ) {
2009-09-25 19:48:46 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Directory transfering call to : %s \n " , s_param . transfer_to ) ;
2011-07-08 10:42:31 +00:00
switch_ivr_session_transfer ( session , s_param . transfer_to , dialplan_name , context_name ) ;
2009-09-25 19:48:46 +00:00
}
/* Delete all sql entry for this call */
sql = switch_mprintf ( " delete from directory_search where hostname = '%q' and uuid = '%q' " , globals . hostname , switch_core_session_get_uuid ( session ) ) ;
2011-12-18 05:22:24 +00:00
directory_execute_sql ( sql , globals . mutex ) ;
2009-09-25 19:48:46 +00:00
switch_safe_free ( sql ) ;
2010-02-06 03:38:24 +00:00
profile_rwunlock ( profile ) ;
2009-09-25 19:48:46 +00:00
}
SWITCH_MODULE_LOAD_FUNCTION ( mod_directory_load )
{
switch_application_interface_t * app_interface ;
switch_status_t status ;
memset ( & globals , 0 , sizeof ( globals ) ) ;
globals . pool = pool ;
2014-03-08 19:37:09 +00:00
switch_core_hash_init ( & globals . profile_hash ) ;
2009-09-25 19:48:46 +00:00
switch_mutex_init ( & globals . mutex , SWITCH_MUTEX_NESTED , globals . pool ) ;
if ( ( status = load_config ( SWITCH_FALSE ) ) ! = SWITCH_STATUS_SUCCESS ) {
return status ;
}
/* connect my internal structure to the blank pointer passed to me */
* module_interface = switch_loadable_module_create_module_interface ( pool , modname ) ;
2011-04-29 15:24:50 +00:00
globals . hostname = switch_core_get_switchname ( ) ;
2009-09-25 19:48:46 +00:00
SWITCH_ADD_APP ( app_interface , " directory " , " directory " , DIR_DESC , directory_function , DIR_USAGE , SAF_NONE ) ;
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS ;
}
/*
Called when the system shuts down
Macro expands to : switch_status_t mod_directory_shutdown ( ) */
SWITCH_MODULE_SHUTDOWN_FUNCTION ( mod_directory_shutdown )
{
2014-08-30 03:41:58 +00:00
switch_hash_index_t * hi = NULL ;
2009-09-25 19:48:46 +00:00
dir_profile_t * profile ;
void * val = NULL ;
const void * key ;
switch_ssize_t keylen ;
char * sql = NULL ;
switch_mutex_lock ( globals . mutex ) ;
2014-08-30 03:41:58 +00:00
while ( ( hi = switch_core_hash_first_iter ( globals . profile_hash , hi ) ) ) {
2014-03-08 19:37:09 +00:00
switch_core_hash_this ( hi , & key , & keylen , & val ) ;
2009-09-25 19:48:46 +00:00
profile = ( dir_profile_t * ) val ;
switch_core_hash_delete ( globals . profile_hash , profile - > name ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Waiting for write lock (Profile %s) \n " , profile - > name ) ;
switch_thread_rwlock_wrlock ( profile - > rwlock ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Destroying Profile %s \n " , profile - > name ) ;
switch_core_destroy_memory_pool ( & profile - > pool ) ;
profile = NULL ;
}
sql = switch_mprintf ( " delete from directory_search where hostname = '%q' " , globals . hostname ) ;
directory_execute_sql ( sql , globals . mutex ) ;
switch_safe_free ( sql ) ;
switch_mutex_unlock ( globals . mutex ) ;
return SWITCH_STATUS_SUCCESS ;
}
/* For Emacs:
* Local Variables :
* mode : c
* indent - tabs - mode : t
* tab - width : 4
* c - basic - offset : 4
* End :
* For VIM :
2013-06-25 16:50:17 +00:00
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 noet
2009-09-25 19:48:46 +00:00
*/