@ -25,7 +25,6 @@
# include "asterisk/strings.h"
# include "asterisk/utils.h"
# include "asterisk/app.h"
# include "asterisk/res_geolocation.h"
# include "geoloc_private.h"
static void varlist_to_str ( struct ast_variable * list , struct ast_str * * buf , size_t len )
@ -37,20 +36,52 @@ static void varlist_to_str(struct ast_variable *list, struct ast_str** buf, size
}
}
# define RESOLVE_FOR_READ(_param) \
( { \
if ( ast_test_flag ( & opts , OPT_GEOLOC_RESOLVE ) ) { \
struct ast_variable * resolved = geoloc_eprofile_resolve_varlist ( \
eprofile - > _param , eprofile - > location_variables , chan ) ; \
if ( ! resolved ) { \
ast_log ( LOG_ERROR , " %s: Unable to resolve " # _param " \n " , chan_name ) ; \
pbx_builtin_setvar_helper ( chan , " GEOLOCPROFILESTATUS " , " -3 " ) ; \
return 0 ; \
} \
varlist_to_str ( resolved , buf , len ) ; \
ast_variables_destroy ( resolved ) ; \
} else { \
varlist_to_str ( eprofile - > _param , buf , len ) ; \
} \
} )
enum my_app_option_flags {
OPT_GEOLOC_RESOLVE = ( 1 < < 0 ) ,
OPT_GEOLOC_APPEND = ( 1 < < 1 ) ,
} ;
AST_APP_OPTIONS ( action_options , {
AST_APP_OPTION ( ' r ' , OPT_GEOLOC_RESOLVE ) ,
AST_APP_OPTION ( ' a ' , OPT_GEOLOC_APPEND ) ,
} ) ;
static int geoloc_profile_read ( struct ast_channel * chan ,
const char * cmd , char * data , struct ast_str * * buf , ssize_t len )
{
char * parsed_data = ast_strdupa ( data ) ;
const char * chan_name = ast_channel_name ( chan ) ;
struct ast_datastore * ds ;
struct ast_geoloc_eprofile * orig_eprofile = NULL ;
struct ast_geoloc_eprofile * eprofile = NULL ;
struct ast_flags opts = { 0 , } ;
AST_DECLARE_APP_ARGS ( args ,
AST_APP_ARG ( field ) ;
AST_APP_ARG ( options ) ;
) ;
/* Check for zero arguments */
if ( ast_strlen_zero ( parsed_data ) ) {
ast_log ( LOG_ERROR , " %s: Cannot call without arguments \n " , cmd ) ;
ast_log ( LOG_ERROR , " %s: Cannot call without arguments \n " , c han_name ) ;
pbx_builtin_setvar_helper ( chan , " GEOLOCPROFILESTATUS " , " -1 " ) ;
return 0 ;
}
@ -58,25 +89,45 @@ static int geoloc_profile_read(struct ast_channel *chan,
AST_STANDARD_APP_ARGS ( args , parsed_data ) ;
if ( ast_strlen_zero ( args . field ) ) {
ast_log ( LOG_ERROR , " %s: Cannot call without a field to query \n " , c md ) ;
ast_log ( LOG_ERROR , " %s: Cannot call without a field to query \n " , c han_name ) ;
pbx_builtin_setvar_helper ( chan , " GEOLOCPROFILESTATUS " , " -1 " ) ;
return 0 ;
}
if ( ! ast_strlen_zero ( args . options ) ) {
if ( ast_app_parse_options ( action_options , & opts , NULL , args . options ) ) {
ast_log ( LOG_ERROR , " %s: Invalid options: %s \n " , chan_name , args . options ) ;
pbx_builtin_setvar_helper ( chan , " GEOLOCPROFILESTATUS " , " -1 " ) ;
return 0 ;
}
}
ds = ast_geoloc_datastore_find ( chan ) ;
if ( ! ds ) {
ast_log ( LOG_NOTICE , " %s: There is no geoloc profile on this channel \n " , cmd ) ;
ast_log ( LOG_NOTICE , " %s: There is no geoloc profile on this channel \n " , c han_name ) ;
pbx_builtin_setvar_helper ( chan , " GEOLOCPROFILESTATUS " , " -2 " ) ;
return 0 ;
}
eprofile = ast_geoloc_datastore_get_eprofile ( ds , 0 ) ;
orig_eprofile = ast_geoloc_datastore_get_eprofile ( ds , 0 ) ;
if ( ! orig_eprofile ) {
ast_log ( LOG_NOTICE , " %s: There is no geoloc profile on this channel \n " , chan_name ) ;
pbx_builtin_setvar_helper ( chan , " GEOLOCPROFILESTATUS " , " -2 " ) ;
return 0 ;
}
eprofile = ast_geoloc_eprofile_dup ( orig_eprofile ) ;
ao2_ref ( orig_eprofile , - 1 ) ;
if ( ! eprofile ) {
ast_log ( LOG_NOTICE , " %s: There is no geoloc profile on this channel \n " , cmd ) ;
ast_log ( LOG_ ERROR, " %s: Unable to duplicate eprofile \n " , chan_name ) ;
pbx_builtin_setvar_helper ( chan , " GEOLOCPROFILESTATUS " , " -2 " ) ;
return 0 ;
}
if ( ! eprofile - > effective_location ) {
ast_geoloc_eprofile_refresh_location ( eprofile ) ;
}
pbx_builtin_setvar_helper ( chan , " GEOLOCPROFILESTATUS " , " 0 " ) ;
if ( ast_strings_equal ( args . field , " inheritable " ) ) {
ast_str_append ( buf , len , " %s " , ds - > inheritance ? " true " : " false " ) ;
@ -101,19 +152,19 @@ static int geoloc_profile_read(struct ast_channel *chan,
} else if ( ast_strings_equal ( args . field , " notes " ) ) {
ast_str_append ( buf , len , " %s " , eprofile - > notes ) ;
} else if ( ast_strings_equal ( args . field , " location_info " ) ) {
varlist_to_str( eprofile - > location_info , buf , len ) ;
RESOLVE_FOR_READ( location_info ) ;
} else if ( ast_strings_equal ( args . field , " location_info_refinement " ) ) {
varlist_to_str( eprofile - > location_refinement , buf , len ) ;
RESOLVE_FOR_READ( location_refinement ) ;
} else if ( ast_strings_equal ( args . field , " location_variables " ) ) {
varlist_to_str( eprofile - > location_variables , buf , len ) ;
RESOLVE_FOR_READ( location_variables ) ;
} else if ( ast_strings_equal ( args . field , " effective_location " ) ) {
varlist_to_str( eprofile - > effective_location , buf , le n) ;
RESOLVE_FOR_READ( effective_locatio n) ;
} else if ( ast_strings_equal ( args . field , " usage_rules " ) ) {
varlist_to_str( eprofile - > usage_rules , buf , len ) ;
RESOLVE_FOR_READ( usage_rules ) ;
} else if ( ast_strings_equal ( args . field , " confidence " ) ) {
varlist_to_str ( eprofile - > confidence , buf , len ) ;
} else {
ast_log ( LOG_ERROR , " %s: Field '%s' is not valid \n " , c md , args . field ) ;
ast_log ( LOG_ERROR , " %s: Field '%s' is not valid \n " , c han_name , args . field ) ;
pbx_builtin_setvar_helper ( chan , " GEOLOCPROFILESTATUS " , " -3 " ) ;
}
@ -121,6 +172,10 @@ static int geoloc_profile_read(struct ast_channel *chan,
return 0 ;
}
# define VAR_LIST_REPLACE(_old, _new) \
ast_variables_destroy ( _old ) ; \
_old = _new ;
# define TEST_ENUM_VALUE(_chan_name, _ep, _field, _value) \
( { \
enum ast_geoloc_ # # _field v ; \
@ -142,8 +197,26 @@ static int geoloc_profile_read(struct ast_channel *chan,
pbx_builtin_setvar_helper ( chan , " GEOLOCPROFILESTATUS " , " -3 " ) ; \
return 0 ; \
} \
ast_variables_destroy ( _ep - > _field ) ; \
_ep - > _field = _list ; \
if ( ast_test_flag ( & opts , OPT_GEOLOC_APPEND ) ) { \
ast_variable_list_append ( & _ep - > _field , _list ) ; \
} else { \
VAR_LIST_REPLACE ( _ep - > _field , _list ) ; \
} \
} )
# define RESOLVE_FOR_WRITE(_param) \
( { \
if ( ast_test_flag ( & opts , OPT_GEOLOC_RESOLVE ) ) { \
struct ast_variable * resolved = geoloc_eprofile_resolve_varlist ( \
eprofile - > _param , eprofile - > location_variables , chan ) ; \
if ( ! resolved ) { \
ast_log ( LOG_ERROR , " %s: Unable to resolve " # _param " %p %p \n " , chan_name , eprofile - > _param , eprofile - > location_variables ) ; \
pbx_builtin_setvar_helper ( chan , " GEOLOCPROFILESTATUS " , " -3 " ) ; \
return 0 ; \
} \
VAR_LIST_REPLACE ( eprofile - > _param , resolved ) ; \
} \
} )
static int geoloc_profile_write ( struct ast_channel * chan , const char * cmd , char * data ,
@ -153,9 +226,11 @@ static int geoloc_profile_write(struct ast_channel *chan, const char *cmd, char
const char * chan_name = ast_channel_name ( chan ) ;
struct ast_datastore * ds ; /* Reminder: datastores aren't ao2 objects */
RAII_VAR ( struct ast_geoloc_eprofile * , eprofile , NULL , ao2_cleanup ) ;
struct ast_flags opts = { 0 , } ;
AST_DECLARE_APP_ARGS ( args ,
AST_APP_ARG ( field ) ;
AST_APP_ARG ( options ) ;
) ;
/* Check for zero arguments */
@ -173,6 +248,18 @@ static int geoloc_profile_write(struct ast_channel *chan, const char *cmd, char
return 0 ;
}
if ( ! ast_strlen_zero ( args . options ) ) {
if ( ast_app_parse_options ( action_options , & opts , NULL , args . options ) ) {
ast_log ( LOG_ERROR , " %s: Invalid options: %s \n " , chan_name , args . options ) ;
pbx_builtin_setvar_helper ( chan , " GEOLOCPROFILESTATUS " , " -1 " ) ;
return 0 ;
}
}
ast_debug ( 1 , " %s: name: %s value: %s options: %s append: %s resolve: %s \n " , chan_name ,
args . field , value , args . options , ast_test_flag ( & opts , OPT_GEOLOC_APPEND ) ? " yes " : " no " ,
ast_test_flag ( & opts , OPT_GEOLOC_RESOLVE ) ? " yes " : " no " ) ;
ds = ast_geoloc_datastore_find ( chan ) ;
if ( ! ds ) {
ds = ast_geoloc_datastore_create ( ast_channel_name ( chan ) ) ;
@ -203,6 +290,8 @@ static int geoloc_profile_write(struct ast_channel *chan, const char *cmd, char
if ( ast_strings_equal ( args . field , " inheritable " ) ) {
ast_geoloc_datastore_set_inheritance ( ds , ast_true ( value ) ) ;
} else if ( ast_strings_equal ( args . field , " id " ) ) {
ast_string_field_set ( eprofile , id , value ) ;
} else if ( ast_strings_equal ( args . field , " location_reference " ) ) {
struct ast_geoloc_location * loc = ast_geoloc_get_location ( value ) ;
ao2_cleanup ( loc ) ;
@ -224,18 +313,25 @@ static int geoloc_profile_write(struct ast_channel *chan, const char *cmd, char
TEST_ENUM_VALUE ( chan_name , eprofile , format , value ) ;
} else if ( ast_strings_equal ( args . field , " pidf_element " ) ) {
TEST_ENUM_VALUE ( chan_name , eprofile , pidf_element , value ) ;
} else if ( ast_strings_equal ( args . field , " location_info " ) ) {
TEST_VARLIST ( chan_name , eprofile , location_info , value ) ;
} else if ( ast_strings_equal ( args . field , " location_source " ) ) {
ast_string_field_set ( eprofile , location_source , value ) ;
} else if ( ast_strings_equal ( args . field , " notes " ) ) {
ast_string_field_set ( eprofile , notes , value ) ;
} else if ( ast_strings_equal ( args . field , " location_info " ) ) {
TEST_VARLIST ( chan_name , eprofile , location_info , value ) ;
RESOLVE_FOR_WRITE ( location_info ) ;
} else if ( ast_strings_equal ( args . field , " location_info_refinement " ) ) {
TEST_VARLIST ( chan_name , eprofile , location_refinement , value ) ;
RESOLVE_FOR_WRITE ( location_refinement ) ;
} else if ( ast_strings_equal ( args . field , " location_variables " ) ) {
TEST_VARLIST ( chan_name , eprofile , location_variables , value ) ;
RESOLVE_FOR_WRITE ( location_variables ) ;
} else if ( ast_strings_equal ( args . field , " effective_location " ) ) {
TEST_VARLIST ( chan_name , eprofile , effective_location , value ) ;
RESOLVE_FOR_WRITE ( effective_location ) ;
} else if ( ast_strings_equal ( args . field , " usage_rules " ) ) {
TEST_VARLIST ( chan_name , eprofile , usage_rules , value ) ;
RESOLVE_FOR_WRITE ( usage_rules ) ;
} else if ( ast_strings_equal ( args . field , " confidence " ) ) {
TEST_VARLIST ( chan_name , eprofile , confidence , value ) ;
} else {
@ -245,6 +341,7 @@ static int geoloc_profile_write(struct ast_channel *chan, const char *cmd, char
}
ast_geoloc_eprofile_refresh_location ( eprofile ) ;
pbx_builtin_setvar_helper ( chan , " GEOLOCPROFILESTATUS " , " 0 " ) ;
return 0 ;