2009-03-05 03:09:31 +00:00
/*
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
* Copyright ( C ) 2005 - 2009 , Anthony Minessale II < anthm @ freeswitch . org >
*
* 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
* Mathieu Rene < mathieu . rene @ gmail . com >
* Portions created by the Initial Developer are Copyright ( C )
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
*
* Mathieu Rene < mathieu . rene @ gmail . com >
*
*
* switch_xml_config . c - Generic configuration parser
*
*/
# include <switch.h>
2009-03-05 16:16:20 +00:00
SWITCH_DECLARE ( switch_size_t ) switch_event_import_xml ( switch_xml_t xml , const char * keyname , const char * valuename , switch_event_t * * event )
2009-03-05 03:09:31 +00:00
{
switch_xml_t node ;
2009-03-05 16:16:20 +00:00
switch_size_t count = 0 ;
2009-03-05 04:22:09 +00:00
2009-03-05 16:16:20 +00:00
if ( ! * event ) {
switch_event_create ( event , SWITCH_EVENT_REQUEST_PARAMS ) ;
switch_assert ( event ) ;
}
2009-03-05 03:09:31 +00:00
for ( node = xml ; node ; node = node - > next ) {
2009-03-05 16:16:20 +00:00
const char * key = switch_xml_attr_soft ( node , keyname ) ;
const char * value = switch_xml_attr_soft ( node , valuename ) ;
if ( key & & value ) {
switch_event_add_header_string ( * event , SWITCH_STACK_BOTTOM , key , value ) ;
count + + ;
}
2009-03-05 03:09:31 +00:00
}
2009-03-05 16:16:20 +00:00
return count ;
}
SWITCH_DECLARE ( switch_status_t ) switch_xml_config_parse ( switch_xml_t xml , int reload , switch_xml_config_item_t * instructions )
{
switch_event_t * event ;
switch_status_t result ;
int count = switch_event_import_xml ( xml , " name " , " value " , & event ) ;
result = switch_xml_config_parse_event ( event , count , reload , instructions ) ;
if ( event ) {
switch_event_destroy ( & event ) ;
}
return result ;
}
SWITCH_DECLARE ( switch_status_t ) switch_xml_config_parse_event ( switch_event_t * event , int count , int reload , switch_xml_config_item_t * instructions )
{
switch_xml_config_item_t * item ;
int file_count = 0 , matched_count = 0 ;
2009-03-05 04:23:54 +00:00
for ( item = instructions ; item - > key ; item + + ) {
2009-03-05 03:09:31 +00:00
const char * value = switch_event_get_header ( event , item - > key ) ;
2009-03-05 05:32:50 +00:00
switch_bool_t changed = SWITCH_FALSE ;
switch_xml_config_callback_t callback = ( switch_xml_config_callback_t ) item - > function ;
2009-03-05 03:09:31 +00:00
if ( reload & & ! item - > reloadable ) {
continue ;
}
switch ( item - > type ) {
case SWITCH_CONFIG_INT :
{
2009-03-05 15:03:29 +00:00
switch_xml_config_int_options_t * int_options = ( switch_xml_config_int_options_t * ) item - > data ;
2009-03-05 03:09:31 +00:00
int * dest = ( int * ) item - > ptr ;
2009-03-05 05:32:50 +00:00
int intval ;
2009-03-05 03:09:31 +00:00
if ( value ) {
if ( switch_is_number ( value ) ) {
2009-03-05 05:32:50 +00:00
intval = atoi ( value ) ;
2009-03-05 03:09:31 +00:00
} else {
2009-03-05 05:32:50 +00:00
intval = ( int ) ( intptr_t ) item - > defaultvalue ;
2009-03-05 15:03:29 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid value [%s] for parameter [%s], setting default [%d] \n " ,
2009-03-05 05:32:50 +00:00
value , item - > key , intval ) ;
2009-03-05 03:09:31 +00:00
}
2009-03-05 15:03:29 +00:00
if ( int_options ) {
/* Enforce validation options */
if ( ( int_options - > enforce_min & & ! ( intval > int_options - > min ) ) | |
( int_options - > enforce_max & & ! ( intval < int_options - > max ) ) ) {
/* Validation failed, set default */
intval = ( int ) ( intptr_t ) item - > defaultvalue ;
/* Then complain */
if ( int_options - > enforce_min & & int_options - > enforce_max ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid value [%s] for parameter [%s], should be between [%d] and [%d], setting default [%d] \n " ,
value , item - > key , int_options - > min , int_options - > max , intval ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid value [%s] for parameter [%s], should be %s [%d], setting default [%d] \n " ,
value , item - > key , int_options - > enforce_min ? " at least " : " at max " , int_options - > enforce_min ? int_options - > min : int_options - > max , intval ) ;
}
}
}
2009-03-05 03:09:31 +00:00
} else {
2009-03-05 05:32:50 +00:00
intval = ( int ) ( intptr_t ) item - > defaultvalue ;
}
if ( * dest ! = intval ) {
* dest = intval ;
changed = SWITCH_TRUE ;
2009-03-05 03:09:31 +00:00
}
}
break ;
case SWITCH_CONFIG_STRING :
{
2009-03-05 04:22:09 +00:00
switch_xml_config_string_options_t * string_options = ( switch_xml_config_string_options_t * ) item - > data ;
2009-03-05 15:03:29 +00:00
const char * newstring = NULL ;
if ( ! string_options ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Missing mandatory switch_xml_config_string_options_t structure for parameter [%s], skipping! \n " ,
item - > key ) ;
continue ;
}
/* Perform validation */
if ( value ) {
if ( ! switch_strlen_zero ( string_options - > validation_regex ) ) {
if ( switch_regex_match ( value , string_options - > validation_regex ) = = SWITCH_STATUS_SUCCESS ) {
newstring = value ; /* Regex match, accept value*/
} else {
newstring = ( char * ) item - > defaultvalue ; /* Regex failed */
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid value [%s] for parameter [%s], setting default [%s] \n " ,
value , item - > key , newstring ) ;
}
} else {
newstring = value ; /* No validation */
2009-03-05 04:22:09 +00:00
}
2009-03-05 03:09:31 +00:00
} else {
2009-03-05 15:03:29 +00:00
newstring = ( char * ) item - > defaultvalue ;
}
if ( newstring ) {
if ( string_options - > length > 0 ) {
/* We have a preallocated buffer */
char * dest = ( char * ) item - > ptr ;
2009-03-05 05:32:50 +00:00
2009-03-05 15:03:29 +00:00
if ( strncasecmp ( dest , newstring , string_options - > length ) ) {
switch_copy_string ( dest , newstring , string_options - > length ) ;
changed = SWITCH_TRUE ;
}
} else {
char * * dest = ( char * * ) item - > ptr ;
if ( strcasecmp ( * dest , newstring ) ) {
if ( string_options - > pool ) {
* dest = switch_core_strdup ( string_options - > pool , newstring ) ;
} else {
switch_safe_free ( * dest ) ;
* dest = strdup ( newstring ) ;
}
changed = SWITCH_TRUE ;
2009-03-05 04:22:09 +00:00
}
2009-03-05 03:09:31 +00:00
}
}
}
break ;
2009-03-05 15:03:29 +00:00
case SWITCH_CONFIG_BOOL :
2009-03-05 03:09:31 +00:00
{
switch_bool_t * dest = ( switch_bool_t * ) item - > ptr ;
2009-03-05 15:03:29 +00:00
switch_bool_t newval = SWITCH_FALSE ;
if ( value & & switch_true ( value ) ) {
newval = SWITCH_TRUE ;
} else if ( value & & switch_false ( value ) ) {
newval = SWITCH_FALSE ;
} else if ( value ) {
/* Value isnt true or false */
newval = ( switch_bool_t ) ( intptr_t ) item - > defaultvalue ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid value [%s] for parameter [%s], setting default [%s] \n " ,
value , item - > key , newval ? " true " : " false " ) ;
} else {
newval = ( switch_bool_t ) ( intptr_t ) item - > defaultvalue ;
}
2009-03-05 05:32:50 +00:00
if ( * dest ! = newval ) {
* dest = newval ;
changed = SWITCH_TRUE ;
2009-03-05 03:09:31 +00:00
}
}
break ;
case SWITCH_CONFIG_CUSTOM :
break ;
case SWITCH_CONFIG_ENUM :
{
2009-03-05 04:23:54 +00:00
switch_xml_config_enum_item_t * enum_options = ( switch_xml_config_enum_item_t * ) item - > data ;
2009-03-05 03:09:31 +00:00
int * dest = ( int * ) item - > ptr ;
2009-03-05 05:50:11 +00:00
int newval = 0 ;
2009-03-05 03:09:31 +00:00
if ( value ) {
2009-03-05 04:23:54 +00:00
for ( ; enum_options - > key ; enum_options + + ) {
if ( ! strcasecmp ( value , enum_options - > key ) ) {
2009-03-05 05:32:50 +00:00
newval = enum_options - > value ;
2009-03-05 03:09:31 +00:00
break ;
}
}
} else {
2009-03-05 05:32:50 +00:00
newval = ( int ) ( intptr_t ) item - > defaultvalue ;
}
if ( ! enum_options - > key ) { /* if (!found) */
newval = ( int ) ( intptr_t ) item - > defaultvalue ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid value [%s] for parameter [%s] \n " , value , item - > key ) ;
}
if ( * dest ! = newval ) {
changed = SWITCH_TRUE ;
* dest = newval ;
2009-03-05 03:09:31 +00:00
}
}
break ;
case SWITCH_CONFIG_FLAG :
{
int32_t * dest = ( int32_t * ) item - > ptr ;
2009-03-05 04:30:15 +00:00
int index = ( int ) ( intptr_t ) item - > data ;
2009-03-05 06:00:36 +00:00
int8_t currentval = ( int8_t ) ! ! ( * dest & index ) ;
2009-03-05 05:32:50 +00:00
int8_t newval = 0 ;
2009-03-05 03:09:31 +00:00
if ( value ) {
2009-03-05 05:32:50 +00:00
newval = switch_true ( value ) ;
2009-03-05 03:09:31 +00:00
} else {
2009-03-05 05:32:50 +00:00
newval = ( switch_bool_t ) ( intptr_t ) item - > defaultvalue ;
}
if ( newval ! = currentval ) {
changed = SWITCH_TRUE ;
if ( newval ) {
2009-03-05 03:09:31 +00:00
* dest | = ( 1 < < index ) ;
} else {
* dest & = ~ ( 1 < < index ) ;
}
}
}
break ;
case SWITCH_CONFIG_FLAGARRAY :
{
int8_t * dest = ( int8_t * ) item - > ptr ;
2009-03-05 05:45:42 +00:00
int8_t index = ( int8_t ) ( intptr_t ) item - > data ;
2009-03-05 05:41:40 +00:00
int8_t newval = value ? ! ! switch_true ( value ) : ( int8_t ) ( ( intptr_t ) item - > defaultvalue ) ;
2009-03-05 05:32:50 +00:00
if ( dest [ index ] ! = newval ) {
changed = SWITCH_TRUE ;
dest [ index ] = newval ;
2009-03-05 03:09:31 +00:00
}
}
break ;
case SWITCH_CONFIG_LAST :
break ;
2009-03-05 05:32:50 +00:00
default :
break ;
}
if ( callback ) {
2009-03-05 16:57:26 +00:00
callback ( item , ( reload ? CONFIG_RELOAD : CONFIG_LOAD ) , changed ) ;
2009-03-05 03:09:31 +00:00
}
}
2009-03-05 03:30:48 +00:00
if ( file_count > matched_count ) {
2009-03-05 16:16:20 +00:00
/* User made a mistake, find it */
switch_event_header_t * header ;
for ( header = event - > headers ; header ; header = header - > next ) {
switch_bool_t found = SWITCH_FALSE ;
for ( item = instructions ; item - > key ; item + + ) {
if ( strcasecmp ( header - > name , item - > key ) ) {
found = SWITCH_TRUE ;
break ;
}
}
if ( ! found ) {
/* Tell the user */
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Configuration parameter [%s] is unfortunately not valid, you might want to double-check that. \n " , header - > name ) ;
}
2009-03-05 03:09:31 +00:00
}
}
2009-03-05 16:16:20 +00:00
return SWITCH_STATUS_SUCCESS ;
2009-03-05 03:09:31 +00:00
}
2009-03-05 03:12:28 +00:00
2009-03-05 16:57:26 +00:00
SWITCH_DECLARE ( void ) switch_xml_config_cleanup ( switch_xml_config_item_t * instructions )
{
switch_xml_config_item_t * item ;
for ( item = instructions ; item - > key ; item + + ) {
switch_xml_config_callback_t callback = ( switch_xml_config_callback_t ) item - > function ;
switch ( item - > type ) {
case SWITCH_CONFIG_STRING :
{
char * * ptr = ( char * * ) item - > ptr ;
switch_xml_config_string_options_t * string_options = ( switch_xml_config_string_options_t * ) item - > data ;
/* if (using_strdup) */
if ( string_options & & ! string_options - > pool & & ! string_options - > length ) {
switch_safe_free ( * ptr ) ;
}
}
break ;
default :
break ;
}
if ( callback ) {
callback ( item , CONFIG_SHUTDOWN , SWITCH_FALSE ) ;
}
}
}
2009-03-05 03:12:28 +00:00
/* For Emacs:
* Local Variables :
* mode : c
* indent - tabs - mode : t
* tab - width : 4
* c - basic - offset : 4
* End :
* For VIM :
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 :
*/