[Freeswitch-branches] [commit] r3550 - freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr

Freeswitch SVN mishehu at freeswitch.org
Tue Dec 5 18:08:57 EST 2006


Author: mishehu
Date: Tue Dec  5 18:08:55 2006
New Revision: 3550

Modified:
   freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/README
   freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/basecdr.h
   freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/cdrcontainer.cpp
   freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/cdrcontainer.h
   freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/csvcdr.cpp
   freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/csvcdr.h
   freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/mod_cdr.cpp
   freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/mysqlcdr.cpp
   freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/mysqlcdr.h
   freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/odbccdr.cpp
   freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/odbccdr.h
   freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/pddcdr.cpp
   freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/pddcdr.h
   freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/schema.sql
   freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/xmlcdr.cpp
   freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/xmlcdr.h

Log:
Finished updating the mod_cdr classes for core changes to switch_channel_t, also added some api commands and updated the documentation and db schemas.

Modified: freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/README
==============================================================================
--- freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/README	(original)
+++ freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/README	Tue Dec  5 18:08:55 2006
@@ -39,6 +39,7 @@
 		<param name="chanvars_fixed" value=""/> value is a comma separated list of fixed channel variables to log.  This cannot be a wildcard (*).  (optional)
 		<param name="chanvars_supp" value=""/>  value is a comma separated list of supplemental channel variables to log.  It can be a wildcard (*).  (optional)
 		<param name="repeat_fixed_in_supp" value=""/> value is a 0 for no, 1 for yes, and is for the case that you might want any fixed channel variables to be repeated in the supplemental list.
+		<param name="timezone" value=""/> value is utc for utc time, local for localtime.  If not specified or incorrectly specified, localtime is assumed.
 		
 Class:		PddCDR, located in pddcdr.h and pddcdr.cpp
 Description:	This is the Perl Data Dumper output class.  It writes each record to an individual text file
@@ -46,18 +47,20 @@
 Configuration:	Section name: <pddcdr>
 		<param name="path" value=""/>  value is the path where you want the output files (required)
 		<param name="chanvars" value=""/> value is a comma separated list of channel variables to log.  It can accept a wildcard (*) (optional)
+		<param name="timezone" value=""/> value is utc for utc time, local for localtime.  If not specified or incorrectly specified, localtime is assumed.
 
 Class:		MysqlCDR, located in mysqlcdr.h and mysqlcdr.cpp
 Description:	This class logs the call detail record to a MySQL 4.1.x or greater database using prepared
-		statements.  This class is a little more complex than the prior two in that the fixed channel variables are treated as additional columns on the main freeswitchcdr database table for improved normalization of the database.  As such, you need to specify the format of each fixed channel variable as well.  If you do not specify, it will default to a varchar column type, and will not execute if the table schema does not match.  Therefore it is very important to make sure that any fixed channel variables you log exist as columns on the table.  The supplemental channel variables are stored in a separate table using a key / value pair linking to the callid of the call.  Recommended to use at least one other logger in conjuction with this one just to be on the safe side, as failover handling of errors to write to the db are not yet implemented, and therefore there is a risk of data loss if the database connection is lost entirely (it will be limited to only those records created at the time of the loss of connection) or some other fatal error is encountered.
+		statements.  This class is a little more complex than the prior two in that the fixed channel variables are treated as additional columns on the main freeswitchcdr database table for improved normalization of the database.  As such, you need to specify the format of each fixed channel variable as well.  If you do not specify, it will default to a varchar column type, and will not execute if the table schema does not match the columns being operated upon.  Therefore it is very important to make sure that any fixed channel variables you log exist as columns on the table.  The supplemental channel variables are stored in a separate table using a key / value pair linking to the callid of the call.  Recommended to use at least one other logger in conjuction with this one just to be on the safe side, as failover handling of errors to write to the db are not yet implemented, and therefore there is a risk of data loss if the database connection is lost entirely (it will be limited to only those records created at the time of the loss of connection) or some other fatal error is encountered.  As of 2006-12-05, we have added a new column named "calltransferdate" to match changes in the core.  Please update your schema to match.
 Configuration:	Section: <mysqlcdr>
 		<param name="hostname" value=""/> value is the hostname or IP of the MySQL server (required)
 		<param name="username" value=""/> value is the username to connect to the MySQL server with (required)
 		<param name="password" value=""/> value is the password to use to authenticate to the MySQL server with (required)
 		<param name="dbname" value=""/> value is the name of the database to connect to (required)
-		<param name="chanvars_fixed" value=""/> Is a comma separated list of key=type pairs.  Types are x for decimal, s for string (varchar), d for double, i for integer, t for tiny.  If no type is provided, it defaults that column to string (varchar).  It cannot accept wildcards (*).  (optional)
+		<param name="chanvars_fixed" value=""/> Is a comma separated list of key=type pairs.  Types are x for decimal, s for string (varchar), d for double, i for integer, t for tiny.  If no type is provided, it defaults that column to string (varchar).  It cannot accept wildcards (*).  You must have a matching column of matching type in the main freeswitchcdr table. (optional)
 		<param name="chanvars_supp" value=""/> value is a comma separated list of supplemental channel variables to log.  Can be a wildcard (*) (optional)
 		<param name="chanvars_supp_repeat_fixed" value=""/> value is 0 for no, 1 for yes, and determines whether or not to repeat any of the fixed channel variables as key / value pairs in the chanvars table.
+		<param name="timezone" value=""/> value is utc for utc time, local for localtime.  If not specified or incorrectly specified, localtime is assumed.
 
 Class:		OdbcCDR, located in odbccdr.h and odbccdr.cpp
 		This class logs the call detail record to an ODBC database using prepared
@@ -73,6 +76,7 @@
 		<param name="chanvars_fixed" value=""/> Is a comma separated list of key=type pairs.  Types are x for decimal, s for string (varchar), d for double, i for integer, t for tiny.  If no type is provided, it defaults that column to string (varchar).  It cannot accept wildcards (*).  (optional)
 		<param name="chanvars_supp" value=""/> value is a comma separated list of supplemental channel variables to log.  Can be a wildcard (*) (optional)
 		<param name="chanvars_supp_repeat_fixed" value=""/> value is 0 for no, 1 for yes, and determines whether or not to repeat any of the fixed channel variables as key / value pairs in the chanvars table.
+		<param name="timezone" value=""/> value is utc for utc time, local for localtime.  If not specified or incorrectly specified, localtime is assumed.
 		
 FAQ:
 
@@ -90,29 +94,38 @@
 				
 Q: What happened to the ani2 field?
 A: Oops, you caught us.  The real name for is it aniii.  You will need to update any database schemas or external handlers for this change.
+		
+Q: Are there any API commands (executable from the console) that can be run?
+A: Yes, there are the following commands:
+	modcdr_reload - causes the freeswitch.xml to be reloaded and reruns the configure on all mod_cdr 	modules
+	modcdr_queue_pause - pauses the queue from extracting items for processing, useful if you need to 	free up some free space without taking the system down.
+	modcdr_queue_resume - resumes normal processing of items in the queue.
+	modcdr_show_active - displays the active backend loggers.
+	modcdr_show_available - displays the available (compiled-in) backend loggers.
 
 Example configuration:
 		
 	<configuration name="mod_cdr.conf" description="CDR Configuration">
 		<pddcdr>
 			<param name="path" value="/work/temp/pddcdr"/>
-			<param name="chanvars" value="username,accountcode"/>
-			<param name="chanvars_fixed" value="*"/>
+			<!-- <param name="chanvars" value="username,accountcode"/> -->
+			<!-- <param name="chanvars_fixed" value="foo"/> -->
 		</pddcdr>
 		<csvcdr>
 			<param name="path" value="/work/temp/csvcdr"/>
 			<param name="size_limit" value="25"/>
-			<param name="chanvars_fixed" value="username"/>
-			<param name="chanvars_supp" value="*"/>
-			<param name="repeat_fixed_in_supp" value="0"/>
+			<!-- <param name="chanvars_fixed" value="username"/> -->
+			<!-- <param name="chanvars_supp" value="*"/> -->
+			<!-- <param name="repeat_fixed_in_supp" value="0"/> -->
 		</csvcdr>
 		<mysqlcdr>
 			<param name="hostname" value="10.0.0.1"/>
 			<param name="username" value="test"/>
 			<param name="password" value="test"/>
 			<param name="dbname" value="testing"/>
-			<param name="chanvars_fixed" value="username=s,The_Kow=t"/>
-			<!-- This previous line logs username as a varchar, and The_Kow as a tiny -->
+			<!-- This following line logs username as a varchar, and The_Kow as a tiny -->
+			<!-- <param name="chanvars_fixed" value="username=s,The_Kow=t"/> -->
+			<!-- If you do not want to log any and all chanvars to the chanvar table, comment the next 2 lines out -->
 			<param name="chanvars_supp" value="*"/>
 			<param name="chanvars_supp_repeat_fixed" value="0"/>
 		</mysqlcdr>

Modified: freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/basecdr.h
==============================================================================
--- freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/basecdr.h	(original)
+++ freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/basecdr.h	Tue Dec  5 18:08:55 2006
@@ -59,6 +59,8 @@
 
 enum switch_mod_cdr_sql_types_t { CDR_INTEGER,CDR_STRING,CDR_DECIMAL,CDR_DOUBLE,CDR_TINY };
 
+typedef apr_status_t (*modcdr_time_convert_t)(apr_time_exp_t*,apr_time_t);
+
 class BaseCDR {
 	public:
 		BaseCDR();
@@ -70,6 +72,7 @@
 		virtual bool is_activated() = 0;
 		virtual void tempdump_record() = 0;
 		virtual void reread_tempdumped_records() = 0;
+		virtual std::string get_display_name() = 0; // Get the module name
 	protected:
 		void parse_channel_variables_xconfig(std::string& unparsed,std::list<std::string>& chanvarslist,bool fixed);
 		void parse_channel_variables_xconfig(std::string& unparsed,std::list<std::string>& chanvarslist,std::vector<switch_mod_cdr_sql_types_t>& chanvars_fixed_types);  // Typically used for SQL types

Modified: freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/cdrcontainer.cpp
==============================================================================
--- freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/cdrcontainer.cpp	(original)
+++ freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/cdrcontainer.cpp	Tue Dec  5 18:08:55 2006
@@ -171,6 +171,38 @@
 
 }
 
+void CDRContainer::active(switch_stream_handle_t *stream)
+{
+	switch_mod_cdr_newchannel_t *newchannel; // = new switch_mod_cdr_newchannel_t;
+	newchannel = 0;
+	
+	stream->write_function(stream,"The following mod_cdr logging backends are currently marked as active:\n");
+	BaseRegistry& registry(BaseRegistry::get());
+	for(BaseRegistry::iterator it = registry.active_begin(); it != registry.active_end(); ++it)
+	{
+		basecdr_creator func = *it;
+		BaseCDR* _ptr = func(newchannel);
+		std::auto_ptr<BaseCDR> ptr(_ptr);
+		stream->write_function(stream,"%s\n",ptr->get_display_name().c_str());
+	}
+}
+
+void CDRContainer::available(switch_stream_handle_t *stream)
+{
+	switch_mod_cdr_newchannel_t *newchannel; // = new switch_mod_cdr_newchannel_t;
+	newchannel = 0;
+	
+	stream->write_function(stream,"The following mod_cdr logging backends are currently avaible for use (providing you configure them):\n");
+	BaseRegistry& registry(BaseRegistry::get());
+	for(BaseRegistry::iterator it = registry.begin(); it != registry.end(); ++it)
+	{
+		basecdr_creator func = *it;
+		BaseCDR* _ptr = func(newchannel);
+		std::auto_ptr<BaseCDR> ptr(_ptr);
+		stream->write_function(stream,"%s\n",ptr->get_display_name().c_str());
+	}
+}
+
 void CDRContainer::add_cdr(switch_core_session_t *session)
 {
 	switch_mod_cdr_newchannel_t *newchannel = new switch_mod_cdr_newchannel_t;
@@ -183,21 +215,20 @@
 	newchannel->callerextension = switch_channel_get_caller_extension(newchannel->channel);
 	newchannel->callerprofile = switch_channel_get_caller_profile(newchannel->channel);
 	
-	BaseRegistry& registry(BaseRegistry::get());
-	for(BaseRegistry::iterator it = registry.active_begin(); it != registry.active_end(); ++it)
+	while (newchannel->callerprofile)
 	{
-		basecdr_creator func = *it;
-		
-		do 
+		BaseRegistry& registry(BaseRegistry::get());
+		for(BaseRegistry::iterator it = registry.active_begin(); it != registry.active_end(); ++it)
 		{
+			basecdr_creator func = *it;
+			
 			BaseCDR* newloggerobject = func(newchannel);
 			switch_console_printf(SWITCH_CHANNEL_LOG,"Adding a new logger object to the queue.\n");
 			switch_queue_push(cdrqueue,newloggerobject);
-			newchannel->callerprofile = newchannel->callerprofile->next;
-			if(newchannel->callerextension)
-				newchannel->callerextension = newchannel->callerextension->next;
-		} while (newchannel->callerprofile);
-		
+		}
+		newchannel->callerprofile = newchannel->callerprofile->next;
+		if(newchannel->callerextension)
+			newchannel->callerextension = newchannel->callerextension->next;
 	}
 		
 	delete newchannel;

Modified: freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/cdrcontainer.h
==============================================================================
--- freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/cdrcontainer.h	(original)
+++ freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/cdrcontainer.h	Tue Dec  5 18:08:55 2006
@@ -61,6 +61,8 @@
 		void reload(switch_stream_handle_t *stream);
 		void queue_pause(switch_stream_handle_t *stream);
 		void queue_resume(switch_stream_handle_t *stream);
+		void active(switch_stream_handle_t *stream);
+		void available(switch_stream_handle_t *stream);
 	protected:
 	private:
 		switch_xml_t cfg, xml, settings, param;

Modified: freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/csvcdr.cpp
==============================================================================
--- freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/csvcdr.cpp	(original)
+++ freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/csvcdr.cpp	Tue Dec  5 18:08:55 2006
@@ -55,19 +55,22 @@
 	
 	if(newchannel != 0)
 	{
-		switch_time_exp_t tempcallstart, tempcallanswer, tempcallend;
+		switch_time_exp_t tempcallstart, tempcallanswer, tempcalltransfer, tempcallend;
 		memset(&tempcallstart,0,sizeof(tempcallstart));
+		memset(&tempcalltransfer,0,sizeof(tempcalltransfer));
 		memset(&tempcallanswer,0,sizeof(tempcallanswer));
 		memset(&tempcallend,0,sizeof(tempcallend));
-		switch_time_exp_lt(&tempcallstart, callstartdate);
-		switch_time_exp_lt(&tempcallanswer, callanswerdate);
-		switch_time_exp_lt(&tempcallend, callenddate);
+		convert_time(&tempcallstart, callstartdate);
+		convert_time(&tempcallanswer, callanswerdate);
+		convert_time(&tempcalltransfer, calltransferdate);
+		convert_time(&tempcallend, callenddate);
 		
 		// Format the times
-		apr_size_t retsizecsd, retsizecad, retsizeced;  //csd == callstartdate, cad == callanswerdate, ced == callenddate, ceff == callenddate_forfile
-		char format[] = "%Y-%m-%d-%H-%M-%S";
+		apr_size_t retsizecsd, retsizecad, retsizectd, retsizeced;  //csd == callstartdate, cad == callanswerdate, ced == callenddate, ceff == callenddate_forfile
+		char format[] = "%Y-%m-%d %H:%M:%S";
 		switch_strftime(formattedcallstartdate,&retsizecsd,sizeof(formattedcallstartdate),format,&tempcallstart);
 		switch_strftime(formattedcallanswerdate,&retsizecad,sizeof(formattedcallanswerdate),format,&tempcallanswer);
+		switch_strftime(formattedcalltransferdate,&retsizectd,sizeof(formattedcalltransferdate),format,&tempcalltransfer);
 		switch_strftime(formattedcallenddate,&retsizeced,sizeof(formattedcallenddate),format,&tempcallend);
 
 		process_channel_variables(chanvars_fixed_list,newchannel->channel);
@@ -84,11 +87,13 @@
 bool CsvCDR::logchanvars=0;
 bool CsvCDR::connectionstate=0;
 bool CsvCDR::repeat_fixed_in_supp=0;
+modcdr_time_convert_t CsvCDR::convert_time = switch_time_exp_lt;
 std::string CsvCDR::outputfile_path;
 std::ofstream CsvCDR::outputfile;
 std::ofstream::pos_type CsvCDR::filesize_limit = (10 * 1024 * 1024); // Default file size is 10MB
 std::list<std::string> CsvCDR::chanvars_fixed_list;
 std::list<std::string> CsvCDR::chanvars_supp_list;
+std::string CsvCDR::display_name = "CsvCDR - The simple comma separated values CDR logger";
 
 void CsvCDR::connect(switch_xml_t& cfg, switch_xml_t& xml, switch_xml_t& settings, switch_xml_t& param)
 {
@@ -153,6 +158,18 @@
 					std::cout << "File size limit from config file is " << filesize_limit << " byte(s)." << std::endl;
 				}
 			}
+			else if(!strcmp(var,"timezone"))
+			{
+				if(!strcmp(val,"utc"))
+					convert_time = switch_time_exp_gmt;
+				else if(!strcmp(val,"local"))
+					convert_time = switch_time_exp_lt;
+				else
+				{
+					switch_console_printf(SWITCH_CHANNEL_LOG,"Invalid configuration parameter for timezone.  Possible values are utc and local.  You entered: %s\nDefaulting to local.\n",val);
+					convert_time = switch_time_exp_lt;
+				}
+			}
 		}
 		
 		if(count_config_params > 0)
@@ -220,8 +237,13 @@
 	
 	// Format the call record and proceed from here...
 	outputfile << "\"" << callstartdate << "\",\"";
+	outputfile << formattedcallstartdate << "\",\"";
 	outputfile << callanswerdate << "\",\"";
+	outputfile << formattedcallanswerdate << "\",\"";
+	outputfile << calltransferdate << "\",\"";
+	outputfile << formattedcalltransferdate << "\",\"";
 	outputfile << callenddate << "\",\"";
+	outputfile << formattedcallenddate << "\",\"";
 	outputfile << hangupcause_text << "\",\"";
 	outputfile << hangupcause << "\",\"";
 	outputfile << clid << "\",\"";
@@ -277,13 +299,18 @@
 
 }
 
+std::string CsvCDR::get_display_name()
+{
+	return display_name;
+}
+
 void CsvCDR::disconnect()
 {
 	outputfile.close();
 	activated = 0;
 	logchanvars = 0;
 	repeat_fixed_in_supp = 0;
-	outfile_path.clear();
+	outputfile_path.clear();
 	chanvars_fixed_list.clear();
 	chanvars_supp_list.clear();
 	connectionstate = 0;

Modified: freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/csvcdr.h
==============================================================================
--- freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/csvcdr.h	(original)
+++ freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/csvcdr.h	Tue Dec  5 18:08:55 2006
@@ -56,17 +56,21 @@
 		virtual bool is_activated();
 		virtual void tempdump_record();
 		virtual void reread_tempdumped_records();
+		virtual std::string get_display_name();
 
 	private:
 		static bool activated; // Is this module activated?
 		static bool connectionstate; // What is the status of the connection?
 		static bool logchanvars;
+		static modcdr_time_convert_t convert_time;
 		static bool repeat_fixed_in_supp; // Repeat the fixed chanvars in the supplemental?
 		static std::string outputfile_path; // The directory we'll dump these into
 		static std::list<std::string> chanvars_fixed_list; // Normally this would be used, but not in this class
 		static std::list<std::string> chanvars_supp_list; // This will hold the list for all chanvars here
+		static std::string display_name;
 		char formattedcallstartdate[100];
 		char formattedcallanswerdate[100];
+		char formattedcalltransferdate[100];
 		char formattedcallenddate[100];
 		static std::ofstream outputfile;
 		static std::ofstream::pos_type filesize_limit;

Modified: freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/mod_cdr.cpp
==============================================================================
--- freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/mod_cdr.cpp	(original)
+++ freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/mod_cdr.cpp	Tue Dec  5 18:08:55 2006
@@ -47,6 +47,8 @@
 static switch_status_t modcdr_reload(char *dest, switch_core_session_t *isession, switch_stream_handle_t *stream);
 static switch_status_t modcdr_queue_pause(char *dest, switch_core_session_t *isession, switch_stream_handle_t *stream);
 static switch_status_t modcdr_queue_resume(char *dest, switch_core_session_t *isession, switch_stream_handle_t *stream);
+static switch_status_t modcdr_show_active(char *dest, switch_core_session_t *isession, switch_stream_handle_t *stream);
+static switch_status_t modcdr_show_available(char *dest, switch_core_session_t *isession, switch_stream_handle_t *stream);
 static switch_thread_rwlock_t *cdr_rwlock;
 
 /* Now begins the glue that will tie this into the system.
@@ -61,12 +63,28 @@
 	/*.on_transmit */ NULL
 };
 
+static switch_api_interface_t modcdr_show_available_api = {
+	/*.interface_name */ "modcdr_show_available",
+	/*.desc */ "Displays the currently compiled-in mod_cdr backend loggers.",
+	/*.function */ modcdr_show_available,
+	/*.syntax */ "modcdr_queue_show_available",
+	/*.next */ 0
+};
+
+static switch_api_interface_t modcdr_show_active_api = {
+	/*.interface_name */ "modcdr_show_active",
+	/*.desc */ "Displays the currently active mod_cdr backend loggers.",
+	/*.function */ modcdr_show_active,
+	/*.syntax */ "modcdr_queue_show_active",
+	/*.next */ &modcdr_show_available_api
+};
+
 static switch_api_interface_t modcdr_queue_resume_api = {
 	/*.interface_name */ "modcdr_queue_resume",
 	/*.desc */ "Manually resumes the popping of objects from the queue.",
 	/*.function */ modcdr_queue_resume,
 	/*.syntax */ "modcdr_queue_resume",
-	/*.next */ 0
+	/*.next */ &modcdr_show_active_api
 };
 
 static switch_api_interface_t modcdr_queue_pause_api = {
@@ -150,6 +168,18 @@
 static switch_status_t modcdr_queue_resume(char *dest=0, switch_core_session_t *isession=0, switch_stream_handle_t *stream=0)
 {
 	newcdrcontainer->queue_resume(stream);
+	return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t modcdr_show_active(char *dest=0, switch_core_session_t *isession=0, switch_stream_handle_t *stream=0)
+{
+	newcdrcontainer->active(stream);
+	return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t modcdr_show_available(char *dest=0, switch_core_session_t *isession=0, switch_stream_handle_t *stream=0)
+{
+	newcdrcontainer->available(stream);
 	return SWITCH_STATUS_SUCCESS;
 }
 

Modified: freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/mysqlcdr.cpp
==============================================================================
--- freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/mysqlcdr.cpp	(original)
+++ freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/mysqlcdr.cpp	Tue Dec  5 18:08:55 2006
@@ -93,6 +93,8 @@
 char MysqlCDR::username[255] ="";
 char MysqlCDR::dbname[255] = "";
 char MysqlCDR::password[255] = "";
+modcdr_time_convert_t MysqlCDR::convert_time = switch_time_exp_lt;
+std::string MysqlCDR::display_name = "MysqlCDR - The MySQL 4.1+ CDR logger using prepared statements";
 //fstream MysqlCDR::tmpfile;
 
 void MysqlCDR::connect(switch_xml_t& cfg, switch_xml_t& xml, switch_xml_t& settings, switch_xml_t& param)
@@ -172,6 +174,18 @@
 						repeat_fixed_in_supp = 1;
 				}
 			}
+			else if(!strcmp(var,"timezone"))
+			{
+				if(!strcmp(val,"utc"))
+					convert_time = switch_time_exp_gmt;
+				else if(!strcmp(val,"local"))
+					convert_time = switch_time_exp_lt;
+				else
+				{
+					switch_console_printf(SWITCH_CHANNEL_LOG,"Invalid configuration parameter for timezone.  Possible values are utc and local.  You entered: %s\nDefaulting to local.\n",val);
+					convert_time = switch_time_exp_lt;
+				}
+			}
 		}
 		
 		if (count_config_params==4)
@@ -181,7 +195,7 @@
 		
 		if(activated)
 		{
-			tmp_sql_query = "INSERT INTO freeswitchcdr  (callstartdate,callanswerdate,callenddate,originated,clid,src,dst,ani,aniii,dialplan,myuuid,destuuid,srcchannel,dstchannel,lastapp,lastdata,billusec,disposition,hangupcause,amaflags";
+			tmp_sql_query = "INSERT INTO freeswitchcdr  (callstartdate,callanswerdate,calltransferdate,callenddate,originated,clid,src,dst,ani,aniii,dialplan,myuuid,destuuid,srcchannel,dstchannel,lastapp,lastdata,billusec,disposition,hangupcause,amaflags";
 			
 			int items_appended = 0;
 			
@@ -199,7 +213,7 @@
 				}
 			}
 			
-			tmp_sql_query.append(") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?");
+			tmp_sql_query.append(") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?");
 			
 			if(chanvars_fixed_list.size() > 0 )
 			{
@@ -299,24 +313,32 @@
 
 }
 
+std::string MysqlCDR::get_display_name()
+{
+	return display_name;
+}
 
 bool MysqlCDR::process_record()
 {
-	switch_time_exp_t tm1,tm2,tm3; // One for call start
+	switch_time_exp_t tm1,tm2,tm3,tm4; // One for call start, answer, transfer, and end
 	memset(&tm1,0,sizeof(tm1));
 	memset(&tm2,0,sizeof(tm2));
 	memset(&tm3,0,sizeof(tm3));
+	memset(&tm4,0,sizeof(tm4));
 	
-	switch_time_exp_lt(&tm1,callstartdate);
-	switch_time_exp_lt(&tm2,callanswerdate);
-	switch_time_exp_lt(&tm3,callenddate);
+	convert_time(&tm1,callstartdate);
+	convert_time(&tm2,callanswerdate);
+	convert_time(&tm3,calltransferdate);
+	convert_time(&tm4,callenddate);
 	
 	set_mysql_time(tm1,my_callstartdate);
 	set_mysql_time(tm2,my_callanswerdate);
-	set_mysql_time(tm3,my_callenddate);
+	set_mysql_time(tm3,my_calltransferdate);
+	set_mysql_time(tm4,my_calltransferdate);
 	
 	add_parameter(my_callstartdate,MYSQL_TYPE_DATETIME);
 	add_parameter(my_callanswerdate,MYSQL_TYPE_DATETIME);
+	add_parameter(my_calltransferdate,MYSQL_TYPE_DATETIME);
 	add_parameter(my_callenddate,MYSQL_TYPE_DATETIME);
 	
 	add_parameter(originated,MYSQL_TYPE_TINY);
@@ -583,6 +605,11 @@
 	chanvars_supp_list.clear();
 	chanvars_fixed_types.clear();
 	connectionstate = 0;
+	memset(hostname,0,255);
+	memset(username,0,255);
+	memset(password,0,255);
+	memset(dbname,0,255);
+	memset(sql_query,0,1024);
 	tmp_sql_query.clear();
 }
 

Modified: freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/mysqlcdr.h
==============================================================================
--- freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/mysqlcdr.h	(original)
+++ freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/mysqlcdr.h	Tue Dec  5 18:08:55 2006
@@ -53,6 +53,7 @@
 		virtual bool is_activated();
 		virtual void tempdump_record();
 		virtual void reread_tempdumped_records();
+		virtual std::string get_display_name();
 
 	private:
 		static bool activated;
@@ -72,11 +73,14 @@
 		static char username[255];
 		static char dbname[255];
 		static char password[255];
+		static modcdr_time_convert_t convert_time;
+		static std::string display_name;
 		//static fstream tmpfile;
 		std::vector<MYSQL_BIND> bindme;
 		//MYSQL_BIND *bindme;
 		MYSQL_TIME my_callstartdate;
 		MYSQL_TIME my_callanswerdate;
+		MYSQL_TIME my_calltransferdate;
 		MYSQL_TIME my_callenddate;
 		// Why all these long unsigned int's?  MySQL's prep statement API expects these to actually exist and not just be params passed to the function calls.  The are to measure the length of actual data in the char* arrays.
 		long unsigned int clid_length;

Modified: freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/odbccdr.cpp
==============================================================================
--- freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/odbccdr.cpp	(original)
+++ freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/odbccdr.cpp	Tue Dec  5 18:08:55 2006
@@ -43,19 +43,22 @@
 {
 	if(newchannel != 0)
 	{
-		switch_time_exp_t tempcallstart, tempcallanswer, tempcallend;
+		switch_time_exp_t tempcallstart, tempcallanswer, tempcalltransfer, tempcallend;
 		memset(&tempcallstart,0,sizeof(tempcallstart));
 		memset(&tempcallanswer,0,sizeof(tempcallanswer));
+		memset(&tempcalltransfer,0,sizeof(tempcalltransfer));
 		memset(&tempcallend,0,sizeof(tempcallend));
-		switch_time_exp_lt(&tempcallstart, callstartdate);
-		switch_time_exp_lt(&tempcallanswer, callanswerdate);
-		switch_time_exp_lt(&tempcallend, callenddate);
+		convert_time(&tempcallstart, callstartdate);
+		convert_time(&tempcallanswer, callanswerdate);
+		convert_time(&tempcalltransfer, calltransferdate);
+		convert_time(&tempcallend, callenddate);
 		
 		// Format the times
-		switch_size_t retsizecsd, retsizecad, retsizeced;  //csd == callstartdate, cad == callanswerdate, ced == callenddate, ceff == callenddate_forfile
+		switch_size_t retsizecsd, retsizecad, retsizectd, retsizeced;  //csd == callstartdate, cad == callanswerdate, ced == callenddate, ceff == callenddate_forfile
 		char format[] = "%Y-%m-%d %T";
 		switch_strftime(odbc_callstartdate,&retsizecsd,sizeof(odbc_callstartdate),format,&tempcallstart);
 		switch_strftime(odbc_callanswerdate,&retsizecad,sizeof(odbc_callanswerdate),format,&tempcallanswer);
+		switch_strftime(odbc_calltransferdate,&retsizectd,sizeof(odbc_calltransferdate),format,&tempcalltransfer);
 		switch_strftime(odbc_callenddate,&retsizeced,sizeof(odbc_callenddate),format,&tempcallend);
 		
 		if(chanvars_fixed_list.size() > 0)
@@ -74,6 +77,8 @@
 bool OdbcCDR::connectionstate = 0;
 bool OdbcCDR::logchanvars = 0;
 bool OdbcCDR::repeat_fixed_in_supp = 0;
+std::string OdbCDR::display_name = "OdbcCDR - The Open Database Backend Connector CDR logger backend";
+modcdr_time_convert_t OdbcCDR::convert_time;
 std::list<std::string> OdbcCDR::chanvars_fixed_list;
 std::list<std::string> OdbcCDR::chanvars_supp_list;
 std::vector<switch_mod_cdr_sql_types_t> OdbcCDR::chanvars_fixed_types;
@@ -188,6 +193,18 @@
 				if(val != 0)
 					strncpy(tablename_chanvars,val,strlen(val));
 			}
+			else if(!strcmp(var,"timezone"))
+			{
+				if(!strcmp(val,"utc"))
+					convert_time = switch_time_exp_gmt;
+				else if(!strcmp(val,"local"))
+					convert_time = switch_time_exp_lt;
+				else
+				{
+					switch_console_printf(SWITCH_CHANNEL_LOG,"Invalid configuration parameter for timezone.  Possible values are utc and local.  You entered: %s\nDefaulting to local.\n",val);
+					convert_time = switch_time_exp_lt;
+				}
+			}
 			
 			if(strlen(tablename) == 0)
 				strncpy(tablename,"freeswitchcdr",13);
@@ -205,7 +222,7 @@
 		{
 			tmp_sql_query = "INSERT INTO ";
 			tmp_sql_query.append(tablename);
-			tmp_sql_query.append(" (callstartdate,callanswerdate,callenddate,originated,clid,src,dst,ani,aniii,dialplan,myuuid,destuuid,srcchannel,dstchannel,lastapp,lastdata,billusec,disposition,hangupcause,amaflags");
+			tmp_sql_query.append(" (callstartdate,callanswerdate,calltransferdate,callenddate,originated,clid,src,dst,ani,aniii,dialplan,myuuid,destuuid,srcchannel,dstchannel,lastapp,lastdata,billusec,disposition,hangupcause,amaflags");
 			
 			int items_appended = 0;
 			
@@ -223,7 +240,7 @@
 				}
 			}
 			
-			tmp_sql_query.append(") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?");
+			tmp_sql_query.append(") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?");
 			
 			if(chanvars_fixed_list.size() > 0 )
 			{
@@ -287,8 +304,8 @@
 	    In this case, the default username and password will be used from odbc.conf */
 	
 	ODBC_res = SQLConnect(ODBC_con, (SQLCHAR*)dsn, SQL_NTS, (SQLCHAR*)username, SQL_NTS, (SQLCHAR*)password, SQL_NTS);
-	                                                                                                     	if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) 
-	{                
+	if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) 
+	{
 		switch_console_printf(SWITCH_CHANNEL_LOG,"Error connecting to the ODBC database on %d\n",ODBC_res);
 		SQLFreeHandle(SQL_HANDLE_DBC, ODBC_con);
 		SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
@@ -390,8 +407,9 @@
 	
 	int index = 1;
 	SQLBindParameter(ODBC_stmt, index++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(odbc_callstartdate), 0, odbc_callstartdate, 0, 0);
-	SQLBindParameter(ODBC_stmt, index++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(odbc_callstartdate), 0, odbc_callstartdate, 0, 0);
-	SQLBindParameter(ODBC_stmt, index++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(odbc_callstartdate), 0, odbc_callenddate, 0, 0);
+	SQLBindParameter(ODBC_stmt, index++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(odbc_callanswerdate), 0, odbc_callanswerdate, 0, 0);
+	SQLBindParameter(ODBC_stmt, index++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(odbc_calltransferdate), 0, odbc_calltransferdate, 0, 0);
+	SQLBindParameter(ODBC_stmt, index++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(odbc_callenddate), 0, odbc_callenddate, 0, 0);
 	
 	SQLBindParameter(ODBC_stmt, index++, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_TINYINT,0, 0,&originated, 0, 0);
 	SQLBindParameter(ODBC_stmt, index++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, sizeof(clid), 0, clid, 0, 0);
@@ -583,6 +601,11 @@
 	chanvars_supp_list.clear();
 	chanvars_fixed_types.clear();
 	connectionstate = 0;
+	memset(hostname,0,255);
+	memset(username,0,255);
+	memset(password,0,255);
+	memset(dbname,0,255);
+	memset(sql_query,0,1024);
 	tmp_sql_query.clear();
 	//tmp_sql_query_chanvars.clear();
 }
@@ -597,6 +620,11 @@
 	SQLFreeHandle(SQL_HANDLE_DBC, ODBC_con);
 	SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
 	connectionstate = 0;
+}
+
+std::string OdbcCDR::get_display_name()
+{
+	return display_name;
 }
 
 AUTO_REGISTER_BASECDR(OdbcCDR);

Modified: freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/odbccdr.h
==============================================================================
--- freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/odbccdr.h	(original)
+++ freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/odbccdr.h	Tue Dec  5 18:08:55 2006
@@ -64,10 +64,13 @@
 		virtual bool is_activated();
 		virtual void tempdump_record();
 		virtual void reread_tempdumped_records();
+		virtual std::string get_display_name();
 
 	private:
 		static bool activated;
 		static char sql_query[1024];
+		static modcdr_time_convert_t convert_time;
+		static std::string display_name;
 		static std::string tmp_sql_query; // Object must exist to bind the statement, this used for generating the sql
 		static char sql_query_chanvars[355];
 		static char sql_query_ping[10];
@@ -92,6 +95,7 @@
 		//static fstream tmpfile;
 		char odbc_callstartdate[128];
 		char odbc_callanswerdate[128];
+		char odbc_calltransferdate[128];
 		char odbc_callenddate[128];
 		void disconnect_stage_1();
 		void connect_to_database();

Modified: freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/pddcdr.cpp
==============================================================================
--- freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/pddcdr.cpp	(original)
+++ freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/pddcdr.cpp	Tue Dec  5 18:08:55 2006
@@ -47,22 +47,26 @@
 	memset(formattedcallstartdate,0,100);
 	memset(formattedcallanswerdate,0,100);
 	memset(formattedcallenddate,0,100);
+	memset(formattedcalltransferdate,0,100);
 	
 	if(newchannel != 0)
 	{
-		switch_time_exp_t tempcallstart, tempcallanswer, tempcallend;
+		switch_time_exp_t tempcallstart, tempcallanswer, tempcalltransfer, tempcallend;
 		memset(&tempcallstart,0,sizeof(tempcallstart));
 		memset(&tempcallanswer,0,sizeof(tempcallanswer));
+		memset(&tempcalltransfer,0,sizeof(tempcalltransfer));
 		memset(&tempcallend,0,sizeof(tempcallend));
-		switch_time_exp_lt(&tempcallstart, callstartdate);
-		switch_time_exp_lt(&tempcallanswer, callanswerdate);
-		switch_time_exp_lt(&tempcallend, callenddate);
+		convert_time(&tempcallstart, callstartdate);
+		convert_time(&tempcallanswer, callanswerdate);
+		convert_time(&tempcalltransfer, calltransferdate);
+		convert_time(&tempcallend, callenddate);
 		
 		// Format the times
-		size_t retsizecsd, retsizecad, retsizeced; //csd == callstartdate, cad == callanswerdate, ced == callenddate, ceff == callenddate_forfile
-		char format[] = "%Y-%m-%d-%H-%M-%S";
+		size_t retsizecsd, retsizecad, retsizectd, retsizeced; //csd == callstartdate, cad == callanswerdate, ced == callenddate, ceff == callenddate_forfile
+		char format[] = "%Y-%m-%d %H:%M:%S";
 		switch_strftime(formattedcallstartdate,&retsizecsd,sizeof(formattedcallstartdate),format,&tempcallstart);
 		switch_strftime(formattedcallanswerdate,&retsizecad,sizeof(formattedcallanswerdate),format,&tempcallanswer);
+		switch_strftime(formattedcalltransferdate,&retsizectd,sizeof(formattedcalltransferdate),format,&tempcalltransfer);
 		switch_strftime(formattedcallenddate,&retsizeced,sizeof(formattedcallenddate),format,&tempcallend);
 
 		std::ostringstream ostring;
@@ -88,9 +92,11 @@
 bool PddCDR::activated=0;
 bool PddCDR::logchanvars=0;
 bool PddCDR::connectionstate=0;
+modcdr_time_convert_t PddCDR::convert_time = switch_time_exp_lt;
 std::string PddCDR::outputfile_path;
 std::list<std::string> PddCDR::chanvars_fixed_list;
 std::list<std::string> PddCDR::chanvars_supp_list;
+std::string PddCDR::display_name = "PddCDR - Perl Data Dumper CDR logger";
 
 void PddCDR::connect(switch_xml_t& cfg, switch_xml_t& xml, switch_xml_t& settings, switch_xml_t& param)
 {
@@ -134,6 +140,18 @@
 			{
 				switch_console_printf(SWITCH_CHANNEL_LOG,"PddCDR has no need for a fixed or supplemental list of channel variables due to the nature of the format.  Please use the setting parameter of \"chanvars\" instead and try again.\n");
 			}
+			else if(!strcmp(var,"timezone"))
+			{
+				if(!strcmp(val,"utc"))
+					convert_time = switch_time_exp_gmt;
+				else if(!strcmp(val,"local"))
+					convert_time = switch_time_exp_lt;
+				else
+				{
+					switch_console_printf(SWITCH_CHANNEL_LOG,"Invalid configuration parameter for timezone.  Possible values are utc and local.  You entered: %s\nDefaulting to local.\n",val);
+					convert_time = switch_time_exp_lt;
+				}
+			}
 		}
 		
 		if(count_config_params > 0)
@@ -155,8 +173,13 @@
 		// Format the call record and proceed from here...
 		outputfile << "$VAR1 = {" << std::endl;
 		outputfile << "\t\'callstartdate\' = \'" << callstartdate << "\'," << std::endl;
+		outputfile <<  "\t\'formattedcallstartdate\' = \'" << formattedcallstartdate << "\'," << std::endl;
 		outputfile << "\t\'callanswerdate\' = \'" << callanswerdate << "\'," << std::endl;
+		outputfile << "\t\'formattedcallanswerdate\' = \'" << formattedcallanswerdate << "\'," << std::endl;
+		outputfile << "\t\'calltransferdate\' = \'" << calltransferdate << "\'," << std::endl;
+		outputfile << "\t\'formattedcalltransferdate\' = \'" << formattedcalltransferdate << "\'," << std::endl;
 		outputfile << "\t\'callenddate\' = \'" << callenddate << "\'," << std::endl;
+		outputfile << "\t\'formatcallenddate\' = \'" << formattedcallenddate << "\'," << std::endl;
 		outputfile << "\t\'hangupcause\' = \'" << hangupcause_text << "\'," << std::endl;
 		outputfile << "\t\'hangupcausecode\' = \'" << hangupcause << "\'," << std::endl;
 		outputfile << "\t\'clid\' = \'" << clid << "\'," << std::endl;
@@ -205,6 +228,11 @@
 void PddCDR::reread_tempdumped_records()
 {
 
+}
+
+std::string PddCDR::get_display_name()
+{
+	return display_name;
 }
 
 void PddCDR::disconnect()

Modified: freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/pddcdr.h
==============================================================================
--- freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/pddcdr.h	(original)
+++ freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/pddcdr.h	Tue Dec  5 18:08:55 2006
@@ -53,16 +53,20 @@
 		virtual bool is_activated();
 		virtual void tempdump_record();
 		virtual void reread_tempdumped_records();
+		virtual std::string get_display_name();
 
 	private:
 		static bool activated; // Is this module activated?
 		static bool connectionstate; // What is the status of the connection?
 		static bool logchanvars;
+		static modcdr_time_convert_t convert_time;
 		static std::string outputfile_path; // The directory we'll dump these into
 		static std::list<std::string> chanvars_fixed_list; // Normally this would be used, but not in this class
 		static std::list<std::string> chanvars_supp_list; // This will hold the list for all chanvars here
+		static std::string display_name;
 		char formattedcallstartdate[100];
 		char formattedcallanswerdate[100];
+		char formattedcalltransferdate[100];
 		char formattedcallenddate[100];
 		std::string outputfile_name;
 		std::ofstream outputfile;

Modified: freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/schema.sql
==============================================================================
--- freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/schema.sql	(original)
+++ freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/schema.sql	Tue Dec  5 18:08:55 2006
@@ -2,6 +2,7 @@
 	callid bigint unsigned default 0 primary key, /* This will need to be handled specially for auto increment, as that might not be standard */
 	callstartdate datetime NOT NULL,
 	callanswerdate datetime NOT NULL,
+	calltransferdate datetime NOT NULL,
 	callenddate datetime NOT NULL,
 	originated tinyint default 0,
 	clid varchar(80) default "Freeswitch - Unknown",

Modified: freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/xmlcdr.cpp
==============================================================================
--- freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/xmlcdr.cpp	(original)
+++ freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/xmlcdr.cpp	Tue Dec  5 18:08:55 2006
@@ -51,19 +51,22 @@
 	
 	if(newchannel != 0)
 	{
-		switch_time_exp_t tempcallstart, tempcallanswer, tempcallend;
+		switch_time_exp_t tempcallstart, tempcallanswer, tempcalltransfer, tempcallend;
 		memset(&tempcallstart,0,sizeof(tempcallstart));
 		memset(&tempcallanswer,0,sizeof(tempcallanswer));
 		memset(&tempcallend,0,sizeof(tempcallend));
-		switch_time_exp_lt(&tempcallstart, callstartdate);
-		switch_time_exp_lt(&tempcallanswer, callanswerdate);
-		switch_time_exp_lt(&tempcallend, callenddate);
+		memset(&tempcalltransfer,0,sizeof(tempcalltransfer));
+		convert_time(&tempcallstart, callstartdate);
+		convert_time(&tempcallanswer, callanswerdate);
+		convert_time(&tempcalltransfer, calltransferdate);
+		convert_time(&tempcallend, callenddate);
 		
 		// Format the times
-		size_t retsizecsd, retsizecad, retsizeced; //csd == callstartdate, cad == callanswerdate, ced == callenddate, ceff == callenddate_forfile
-		char format[] = "%Y-%m-%d-%H-%M-%S";
+		size_t retsizecsd, retsizecad, retsizectd, retsizeced; //csd == callstartdate, cad == callanswerdate, ced == callenddate, ceff == callenddate_forfile
+		char format[] = "%Y-%m-%d %H:%M:%S";
 		switch_strftime(formattedcallstartdate,&retsizecsd,sizeof(formattedcallstartdate),format,&tempcallstart);
 		switch_strftime(formattedcallanswerdate,&retsizecad,sizeof(formattedcallanswerdate),format,&tempcallanswer);
+		switch_strftime(formattedcalltransferdate,&retsizectd,sizeof(formattedcalltransferdate),format,&tempcalltransfer);
 		switch_strftime(formattedcallenddate,&retsizeced,sizeof(formattedcallenddate),format,&tempcallend);
 
 		std::ostringstream ostring;
@@ -90,9 +93,11 @@
 bool XmlCDR::activated=0;
 bool XmlCDR::logchanvars=0;
 bool XmlCDR::connectionstate=0;
+modcdr_time_convert_t XmlCDR::convert_time = switch_time_exp_lt;
 std::string XmlCDR::outputfile_path;
 std::list<std::string> XmlCDR::chanvars_fixed_list;
 std::list<std::string> XmlCDR::chanvars_supp_list;
+std::string XmlCDR::display_name = "XmlCDR - The rough implementation of XML CDR logger";
 
 void XmlCDR::connect(switch_xml_t& cfg, switch_xml_t& xml, switch_xml_t& settings, switch_xml_t& param)
 {
@@ -136,6 +141,18 @@
 			{
 				switch_console_printf(SWITCH_CHANNEL_LOG,"XmlCDR has no need for a fixed or supplemental list of channel variables due to the nature of the format.  Please use the setting parameter of \"chanvars\" instead and try again.\n");
 			}
+			else if(!strcmp(var,"timezone"))
+			{
+				if(!strcmp(val,"utc"))
+					convert_time = switch_time_exp_gmt;
+				else if(!strcmp(val,"local"))
+					convert_time = switch_time_exp_lt;
+				else
+				{
+					switch_console_printf(SWITCH_CHANNEL_LOG,"Invalid configuration parameter for timezone.  Possible values are utc and local.  You entered: %s\nDefaulting to local.\n",val);
+					convert_time = switch_time_exp_lt;
+				}
+			}
 		}
 		
 		if(count_config_params > 0)
@@ -159,8 +176,13 @@
 		outputfile << "<?xml version=\"1.0\"?>" << std::endl;
 		outputfile << "<document type=\"freeswitch-cdr/xml\">" << std::endl;
 		outputfile << "\t<callstartdate data=\"" << callstartdate << "\" />" << std::endl;
+		outputfile << "\t<formattedcallstartdate data=\"" << formattedcallstartdate << "\" />" << std::endl;
 		outputfile << "\t<callanswerdate data=\"" << callanswerdate << "\" />" << std::endl;
+		outputfile << "\t<formattedcallanswerdate data=\"" << formattedcallanswerdate << "\" />" << std::endl;
+		outputfile << "\t<calltransferdate data=\"" << calltransferdate << "\" />" << std::endl;
+		outputfile << "\t<formattedcalltransferdate data=\"" << formattedcalltransferdate << "\" />" << std::endl;
 		outputfile << "\t<callenddate data=\"" << callenddate << "\" />" << std::endl;
+		outputfile << "\t<formattedcallenddate data=\"" << formattedcallenddate << "\" />" << std::endl;
 		outputfile << "\t<hangupcause data=\"" << hangupcause_text << "\" />" << std::endl;
 		outputfile << "\t<hangupcausecode data=\"" << hangupcause << "\" />" << std::endl;
 		outputfile << "\t<clid data=\"" << clid << "\" />" << std::endl;
@@ -211,6 +233,11 @@
 void XmlCDR::reread_tempdumped_records()
 {
 
+}
+
+std::string XmlCDR::get_display_name()
+{
+	return display_name;
 }
 
 void XmlCDR::disconnect()

Modified: freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/xmlcdr.h
==============================================================================
--- freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/xmlcdr.h	(original)
+++ freeswitch/branches/mishehu/src/mod/event_handlers/mod_cdr/xmlcdr.h	Tue Dec  5 18:08:55 2006
@@ -54,16 +54,20 @@
 		virtual bool is_activated();
 		virtual void tempdump_record();
 		virtual void reread_tempdumped_records();
+		virtual std::string get_display_name();
 
 	private:
 		static bool activated; // Is this module activated?
 		static bool connectionstate; // What is the status of the connection?
 		static bool logchanvars;
+		static modcdr_time_convert_t convert_time;
 		static std::string outputfile_path; // The directory we'll dump these into
 		static std::list<std::string> chanvars_fixed_list; // Normally this would be used, but not in this class
 		static std::list<std::string> chanvars_supp_list; // This will hold the list for all chanvars here
+		static std::string display_name;
 		char formattedcallstartdate[100];
 		char formattedcallanswerdate[100];
+		char formattedcalltransferdate[100];
 		char formattedcallenddate[100];
 		std::string outputfile_name;
 		std::ofstream outputfile;



More information about the Freeswitch-branches mailing list