/* * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application * Copyright (C) 2005/2006, Anthony Minessale II * * 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 mod_timezone. * * The Initial Developer of the Original Code is * Massimo Cetra * Portions created by the Initial Developer are Copyright (C) * the Initial Developer. All Rights Reserved. * * mod_timezone.c -- Access to timezone informations and time string formatting * */ #include #include "mod_timezone.h" /* This converts a struct tm to a switch_time_exp_t We have to use UNIX structures to do our exams and use switch_* functions for the output. */ static void tm2switchtime(struct tm * tm, switch_time_exp_t *xt ) { if (!xt || !tm) { return; } memset( xt, 0, sizeof(xt) ); xt->tm_sec = tm->tm_sec; xt->tm_min = tm->tm_min; xt->tm_hour = tm->tm_hour; xt->tm_mday = tm->tm_mday; xt->tm_mon = tm->tm_mon; xt->tm_year = tm->tm_year; xt->tm_wday = tm->tm_wday; xt->tm_yday = tm->tm_yday; xt->tm_isdst = tm->tm_isdst; #if !defined(WIN32) && !defined(__SVR4) && !defined(__sun) xt->tm_gmtoff = tm->tm_gmtoff; #endif return; } /* ************************************************************************** LOADING OF THE XML DATA - HASH TABLE & MEMORY POOL MANAGEMENT ************************************************************************** */ typedef struct { switch_memory_pool_t *pool; switch_hash_t *hash; } switch_timezones_list_t; static switch_timezones_list_t TIMEZONES_LIST = { 0 }; static switch_event_node_t *NODE = NULL; const char *switch_lookup_timezone( const char *tz_name ) { char *value = NULL; if ( tz_name && (value = switch_core_hash_find(TIMEZONES_LIST.hash, tz_name))==NULL ) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Timezone '%s' not found!\n", tz_name); } return value; } void switch_load_timezones(switch_bool_t reload) { switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, cfg = NULL; unsigned total = 0; if (TIMEZONES_LIST.hash) { switch_core_hash_destroy(&TIMEZONES_LIST.hash); } if (TIMEZONES_LIST.pool) { switch_core_destroy_memory_pool(&TIMEZONES_LIST.pool); } memset(&TIMEZONES_LIST, 0, sizeof(TIMEZONES_LIST)); switch_core_new_memory_pool(&TIMEZONES_LIST.pool); switch_core_hash_init(&TIMEZONES_LIST.hash, TIMEZONES_LIST.pool); if ((xml = switch_xml_open_cfg("timezones.conf", &cfg, NULL))) { if ((x_lists = switch_xml_child(cfg, "timezones"))) { for (x_list = switch_xml_child(x_lists, "zone"); x_list; x_list = x_list->next) { const char *name = switch_xml_attr(x_list, "name"); const char *value= switch_xml_attr(x_list, "value"); if (switch_strlen_zero(name)) { continue; } if (switch_strlen_zero(value)) { continue; } switch_core_hash_insert(TIMEZONES_LIST.hash, name, switch_core_strdup(TIMEZONES_LIST.pool, value) ); total++; } } switch_xml_free(xml); } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Timezone %sloaded %d definitions\n", reload ? "re" : "", total); } /* ************************************************************************** API FUNCTIONS AND COMMANDS ************************************************************************** */ SWITCH_STANDARD_API(strftime_tz_api_function) { switch_time_t thetime; time_t timep; char *format = NULL; const char *tz_name; const char *tzdef; switch_size_t retsize; char date[80] = ""; struct tm tm; switch_time_exp_t stm; thetime = switch_timestamp_now(); timep = (thetime) / (int64_t) (1000000); if (!switch_strlen_zero(cmd)) { format = strchr(cmd, ' '); tz_name = cmd; if (format) { *format++ = '\0'; } tzdef = switch_lookup_timezone( tz_name ); } else { /* We set the default timezone to GMT. */ tz_name="GMT"; tzdef="GMT"; } if (tzdef) { /* The lookup of the zone may fail. */ tztime( &timep, tzdef, &tm ); tm2switchtime( &tm, &stm ); switch_strftime(date, &retsize, sizeof(date), switch_strlen_zero(format) ? "%Y-%m-%d %T" : format, &stm); stream->write_function(stream, "%s", date); } else { stream->write_function(stream, "-ERR Invalid Timezone\n"); } return SWITCH_STATUS_SUCCESS; } /* ************************************************************************** ************************************************************************** */ SWITCH_MODULE_LOAD_FUNCTION(mod_timezone_load); SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_timezone_shutdown); SWITCH_MODULE_DEFINITION(mod_timezone, mod_timezone_load, mod_timezone_shutdown, NULL); static void event_handler(switch_event_t *event) { switch_load_timezones(1); } SWITCH_MODULE_LOAD_FUNCTION(mod_timezone_load) { switch_api_interface_t *api_interface; if ((switch_event_bind_removable(modname, SWITCH_EVENT_RELOADXML, NULL, event_handler, NULL, &NODE) != SWITCH_STATUS_SUCCESS)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); } switch_load_timezones(0); *module_interface = switch_loadable_module_create_module_interface(pool, modname); SWITCH_ADD_API(api_interface, "strftime_tz", "strftime_tz", strftime_tz_api_function, ","); return SWITCH_STATUS_SUCCESS; } SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_timezone_shutdown) { if (TIMEZONES_LIST.hash) { switch_core_hash_destroy(&TIMEZONES_LIST.hash); } if (TIMEZONES_LIST.pool) { switch_core_destroy_memory_pool(&TIMEZONES_LIST.pool); } return SWITCH_STATUS_UNLOAD; } /* 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 expandtab: */