| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Asterisk -- An open source telephony toolkit. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (C) 2006, Proformatique | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Written by Richard Braun <rbraun@proformatique.com> | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * Based on res_sqlite3 by Anthony Minessale II, | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * and res_config_mysql by Matthew Boehm | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * See http://www.asterisk.org for more information about
 | 
					
						
							|  |  |  |  * the Asterisk project. Please do not directly contact | 
					
						
							|  |  |  |  * any of the maintainers of this project for assistance; | 
					
						
							|  |  |  |  * the project provides a web site, mailing lists and IRC | 
					
						
							|  |  |  |  * channels for your use. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software, distributed under the terms of | 
					
						
							|  |  |  |  * the GNU General Public License Version 2. See the LICENSE file | 
					
						
							|  |  |  |  * at the top of the source tree. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \page res_config_sqlite | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * \section intro_sec Presentation | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * res_config_sqlite is a module for the Asterisk Open Source PBX to | 
					
						
							|  |  |  |  * support SQLite 2 databases. It can be used to fetch configuration | 
					
						
							|  |  |  |  * from a database (static configuration files and/or using the Asterisk | 
					
						
							| 
									
										
										
										
											2017-12-22 09:23:22 -05:00
										 |  |  |  * RealTime Architecture - ARA).  It can also be used to log CDR entries. | 
					
						
							| 
									
										
										
										
											2008-07-19 10:46:12 +00:00
										 |  |  |  * Note that Asterisk already comes with a module named cdr_sqlite. | 
					
						
							|  |  |  |  * There are two reasons for including it in res_config_sqlite: | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * the first is that rewriting it was a training to learn how to write a | 
					
						
							|  |  |  |  * simple module for Asterisk, the other is to have the same database open for | 
					
						
							|  |  |  |  * all kinds of operations, which improves reliability and performance. | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * \section conf_sec Configuration | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2012-09-22 20:43:30 +00:00
										 |  |  |  * The main configuration file is res_config_sqlite.conf.sample It must be readable or | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * res_config_sqlite will fail to start. It is suggested to use the sample file | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * in this package as a starting point. The file has only one section | 
					
						
							|  |  |  |  * named <code>general</code>. Here are the supported parameters : | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * <dl> | 
					
						
							|  |  |  |  *	<dt><code>dbfile</code></dt> | 
					
						
							|  |  |  |  *	<dd>The absolute path to the SQLite database (the file can be non existent, | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  *			res_config_sqlite will create it if it has the appropriate rights)</dd> | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  *	<dt><code>config_table</code></dt> | 
					
						
							|  |  |  |  *	<dd>The table used for static configuration</dd> | 
					
						
							|  |  |  |  *	<dt><code>cdr_table</code></dt> | 
					
						
							|  |  |  |  *	<dd>The table used to store CDR entries (if ommitted, CDR support is | 
					
						
							|  |  |  |  *			disabled)</dd> | 
					
						
							|  |  |  |  * </dl> | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * To use res_config_sqlite for static and/or RealTime configuration, refer to the | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * Asterisk documentation. The file tables.sql can be used to create the | 
					
						
							|  |  |  |  * needed tables. | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * \section status_sec Driver status | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * The CLI command <code>show sqlite status</code> returns status information | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * about the running driver. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * \section credits_sec Credits | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-06-01 18:36:25 +00:00
										 |  |  |  * res_config_sqlite was developed by Richard Braun at the Proformatique company. | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * \file | 
					
						
							|  |  |  |  * \brief res_config_sqlite module. | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-14 21:44:27 +00:00
										 |  |  | /*! \li \ref res_config_sqlite.c uses the configuration file \ref res_config_sqlite.conf
 | 
					
						
							| 
									
										
										
										
											2012-10-01 23:24:10 +00:00
										 |  |  |  * \addtogroup configuration_file Configuration Files | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-22 09:23:22 -05:00
										 |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2012-10-01 23:24:10 +00:00
										 |  |  |  * \page res_config_sqlite.conf res_config_sqlite.conf | 
					
						
							|  |  |  |  * \verbinclude res_config_sqlite.conf.sample | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | /*** MODULEINFO
 | 
					
						
							|  |  |  | 	<depend>sqlite</depend> | 
					
						
							| 
									
										
										
										
											2017-12-22 16:27:52 -05:00
										 |  |  | 	<support_level>deprecated</support_level> | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  ***/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "asterisk.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <sqlite.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-10 00:42:13 +00:00
										 |  |  | #include "asterisk/logger.h"
 | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | #include "asterisk/app.h"
 | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | #include "asterisk/pbx.h"
 | 
					
						
							|  |  |  | #include "asterisk/cdr.h"
 | 
					
						
							|  |  |  | #include "asterisk/cli.h"
 | 
					
						
							|  |  |  | #include "asterisk/lock.h"
 | 
					
						
							|  |  |  | #include "asterisk/config.h"
 | 
					
						
							|  |  |  | #include "asterisk/module.h"
 | 
					
						
							|  |  |  | #include "asterisk/linkedlists.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | #define MACRO_BEGIN	do {
 | 
					
						
							|  |  |  | #define MACRO_END	} while (0)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define RES_CONFIG_SQLITE_NAME "res_config_sqlite"
 | 
					
						
							|  |  |  | #define RES_CONFIG_SQLITE_DRIVER "sqlite"
 | 
					
						
							|  |  |  | #define RES_CONFIG_SQLITE_DESCRIPTION "Resource Module for SQLite 2"
 | 
					
						
							|  |  |  | #define RES_CONFIG_SQLITE_CONF_FILE "res_config_sqlite.conf"
 | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | enum { | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 	RES_CONFIG_SQLITE_CONFIG_ID, | 
					
						
							| 
									
										
										
										
											2007-09-17 20:24:50 +00:00
										 |  |  | 	RES_CONFIG_SQLITE_CONFIG_CAT_METRIC, | 
					
						
							|  |  |  | 	RES_CONFIG_SQLITE_CONFIG_VAR_METRIC, | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 	RES_CONFIG_SQLITE_CONFIG_COMMENTED, | 
					
						
							|  |  |  | 	RES_CONFIG_SQLITE_CONFIG_FILENAME, | 
					
						
							|  |  |  | 	RES_CONFIG_SQLITE_CONFIG_CATEGORY, | 
					
						
							|  |  |  | 	RES_CONFIG_SQLITE_CONFIG_VAR_NAME, | 
					
						
							|  |  |  | 	RES_CONFIG_SQLITE_CONFIG_VAR_VAL, | 
					
						
							|  |  |  | 	RES_CONFIG_SQLITE_CONFIG_COLUMNS, | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | #define SET_VAR(config, to, from)			\
 | 
					
						
							|  |  |  | MACRO_BEGIN						\ | 
					
						
							|  |  |  | 	int __error;					\ | 
					
						
							|  |  |  | 							\ | 
					
						
							|  |  |  | 	__error = set_var(&to, #to, from->value);	\ | 
					
						
							|  |  |  | 							\ | 
					
						
							|  |  |  | 	if (__error) {					\ | 
					
						
							|  |  |  | 		ast_config_destroy(config);		\ | 
					
						
							|  |  |  | 		unload_config();			\ | 
					
						
							|  |  |  | 		return 1;				\ | 
					
						
							|  |  |  | 	}						\ | 
					
						
							|  |  |  | MACRO_END | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-14 00:08:52 +00:00
										 |  |  | AST_THREADSTORAGE(sql_buf); | 
					
						
							|  |  |  | AST_THREADSTORAGE(where_buf); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | /*!
 | 
					
						
							|  |  |  |  * Maximum number of loops before giving up executing a query. Calls to | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  |  * sqlite_xxx() functions which can return SQLITE_BUSY | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * are enclosed by RES_CONFIG_SQLITE_BEGIN and RES_CONFIG_SQLITE_END, e.g. | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * <pre> | 
					
						
							|  |  |  |  * char *errormsg; | 
					
						
							|  |  |  |  * int error; | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * RES_CONFIG_SQLITE_BEGIN | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  *	 error = sqlite_exec(db, query, NULL, NULL, &errormsg); | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * RES_CONFIG_SQLITE_END(error) | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * if (error) | 
					
						
							|  |  |  |  *	 ...; | 
					
						
							|  |  |  |  * </pre> | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | #define RES_CONFIG_SQLITE_MAX_LOOPS 10
 | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * Macro used before executing a query. | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * \see RES_CONFIG_SQLITE_MAX_LOOPS. | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | #define RES_CONFIG_SQLITE_BEGIN						\
 | 
					
						
							|  |  |  | MACRO_BEGIN								\ | 
					
						
							|  |  |  | 	int __i;							\ | 
					
						
							|  |  |  | 									\ | 
					
						
							|  |  |  | 	for (__i = 0; __i < RES_CONFIG_SQLITE_MAX_LOOPS; __i++)	{ | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * Macro used after executing a query. | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * \see RES_CONFIG_SQLITE_MAX_LOOPS. | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | #define RES_CONFIG_SQLITE_END(error)					\
 | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 		if (error != SQLITE_BUSY)	\ | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 			break;						\ | 
					
						
							|  |  |  | 		usleep(1000);						\ | 
					
						
							|  |  |  | 	}								\ | 
					
						
							|  |  |  | MACRO_END; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * Structure sent to the SQLite callback function for static configuration. | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * \see add_cfg_entry() | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | struct cfg_entry_args { | 
					
						
							|  |  |  | 	struct ast_config *cfg; | 
					
						
							|  |  |  | 	struct ast_category *cat; | 
					
						
							|  |  |  | 	char *cat_name; | 
					
						
							| 
									
										
										
										
											2007-09-17 20:24:50 +00:00
										 |  |  | 	struct ast_flags flags; | 
					
						
							| 
									
										
										
										
											2008-03-11 22:55:16 +00:00
										 |  |  | 	const char *who_asked; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * Structure sent to the SQLite callback function for RealTime configuration. | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * \see add_rt_cfg_entry() | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | struct rt_cfg_entry_args { | 
					
						
							|  |  |  | 	struct ast_variable *var; | 
					
						
							|  |  |  | 	struct ast_variable *last; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * Structure sent to the SQLite callback function for RealTime configuration | 
					
						
							|  |  |  |  * (realtime_multi_handler()). | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * \see add_rt_multi_cfg_entry() | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | struct rt_multi_cfg_entry_args { | 
					
						
							|  |  |  | 	struct ast_config *cfg; | 
					
						
							|  |  |  | 	char *initfield; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \brief Allocate a variable. | 
					
						
							|  |  |  |  * \param var the address of the variable to set (it will be allocated) | 
					
						
							|  |  |  |  * \param name the name of the variable (for error handling) | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * \param value the value to store in var | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \retval 0 on success | 
					
						
							|  |  |  |  * \retval 1 if an allocation error occurred | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2007-11-14 15:13:22 +00:00
										 |  |  | static int set_var(char **var, const char *name, const char *value); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \brief Load the configuration file. | 
					
						
							|  |  |  |  * \see unload_config() | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * This function sets dbfile, config_table, and cdr_table. It calls | 
					
						
							|  |  |  |  * check_vars() before returning, and unload_config() if an error occurred. | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \retval 0 on success | 
					
						
							|  |  |  |  * \retval 1 if an error occurred | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | static int load_config(void); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \brief Free resources related to configuration. | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * \see load_config() | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void unload_config(void); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \brief Asterisk callback function for CDR support. | 
					
						
							| 
									
										
										
										
											2007-09-05 16:31:39 +00:00
										 |  |  |  * \param cdr the CDR entry Asterisk sends us. | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * Asterisk will call this function each time a CDR entry must be logged if | 
					
						
							|  |  |  |  * CDR support is enabled. | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \retval 0 on success | 
					
						
							|  |  |  |  * \retval 1 if an error occurred | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | static int cdr_handler(struct ast_cdr *cdr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \brief SQLite callback function for static configuration. | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * This function is passed to the SQLite engine as a callback function to | 
					
						
							|  |  |  |  * parse a row and store it in a struct ast_config object. It relies on | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * resulting rows being sorted by category. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \param arg a pointer to a struct cfg_entry_args object | 
					
						
							|  |  |  |  * \param argc number of columns | 
					
						
							|  |  |  |  * \param argv values in the row | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * \param columnNames names and types of the columns | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \retval 0 on success | 
					
						
							|  |  |  |  * \retval 1 if an error occurred | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * \see cfg_entry_args | 
					
						
							|  |  |  |  * \see sql_get_config_table | 
					
						
							|  |  |  |  * \see config_handler() | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int add_cfg_entry(void *arg, int argc, char **argv, char **columnNames); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \brief Asterisk callback function for static configuration. | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * Asterisk will call this function when it loads its static configuration, | 
					
						
							|  |  |  |  * which usually happens at startup and reload. | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * \param database the database to use (ignored) | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \param table the table to use | 
					
						
							|  |  |  |  * \param file the file to load from the database | 
					
						
							|  |  |  |  * \param cfg the struct ast_config object to use when storing variables | 
					
						
							| 
									
										
										
										
											2007-08-16 21:09:46 +00:00
										 |  |  |  * \param flags Optional flags.  Not used. | 
					
						
							| 
									
										
										
										
											2007-09-05 16:31:39 +00:00
										 |  |  |  * \param suggested_incl suggest include. | 
					
						
							| 
									
										
										
										
											2010-06-08 14:38:18 +00:00
										 |  |  |  * \param who_asked | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \retval cfg object | 
					
						
							|  |  |  |  * \retval NULL if an error occurred | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * \see add_cfg_entry() | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2007-08-29 20:55:40 +00:00
										 |  |  | static struct ast_config * config_handler(const char *database, const char *table, const char *file, | 
					
						
							| 
									
										
										
										
											2008-03-11 22:55:16 +00:00
										 |  |  | 	struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl, const char *who_asked); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \brief SQLite callback function for RealTime configuration. | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * This function is passed to the SQLite engine as a callback function to | 
					
						
							|  |  |  |  * parse a row and store it in a linked list of struct ast_variable objects. | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \param arg a pointer to a struct rt_cfg_entry_args object | 
					
						
							|  |  |  |  * \param argc number of columns | 
					
						
							|  |  |  |  * \param argv values in the row | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * \param columnNames names and types of the columns | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \retval 0 on success. | 
					
						
							|  |  |  |  * \retval 1 if an error occurred. | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * \see rt_cfg_entry_args | 
					
						
							|  |  |  |  * \see realtime_handler() | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int add_rt_cfg_entry(void *arg, int argc, char **argv, | 
					
						
							|  |  |  | 	char **columnNames); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2008-07-19 10:46:12 +00:00
										 |  |  |  * \brief Asterisk callback function for RealTime configuration. | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * Asterisk will call this function each time it requires a variable | 
					
						
							|  |  |  |  * through the RealTime architecture. ap is a list of parameters and | 
					
						
							|  |  |  |  * values used to find a specific row, e.g one parameter "name" and | 
					
						
							|  |  |  |  * one value "123" so that the SQL query becomes <code>SELECT * FROM | 
					
						
							|  |  |  |  * table WHERE name = '123';</code>. | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * \param database the database to use (ignored) | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * \param table the table to use | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  |  * \param fields list of parameters and values to match | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * \retval a linked list of struct ast_variable objects | 
					
						
							|  |  |  |  * \retval NULL if an error occurred | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * \see add_rt_cfg_entry() | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static struct ast_variable * realtime_handler(const char *database, | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	const char *table, const struct ast_variable *fields); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \brief SQLite callback function for RealTime configuration. | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * This function performs the same actions as add_rt_cfg_entry() except | 
					
						
							|  |  |  |  * that the rt_multi_cfg_entry_args structure is designed to store | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * categories in addition to variables. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \param arg a pointer to a struct rt_multi_cfg_entry_args object | 
					
						
							|  |  |  |  * \param argc number of columns | 
					
						
							|  |  |  |  * \param argv values in the row | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * \param columnNames names and types of the columns | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \retval 0 on success. | 
					
						
							|  |  |  |  * \retval 1 if an error occurred. | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * \see rt_multi_cfg_entry_args | 
					
						
							|  |  |  |  * \see realtime_multi_handler() | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int add_rt_multi_cfg_entry(void *arg, int argc, char **argv, | 
					
						
							|  |  |  | 	char **columnNames); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \brief Asterisk callback function for RealTime configuration. | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * This function performs the same actions as realtime_handler() except | 
					
						
							|  |  |  |  * that it can store variables per category, and can return several | 
					
						
							|  |  |  |  * categories. | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * \param database the database to use (ignored) | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \param table the table to use | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  |  * \param fields list of parameters and values to match | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \retval a struct ast_config object storing categories and variables. | 
					
						
							|  |  |  |  * \retval NULL if an error occurred. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * \see add_rt_multi_cfg_entry() | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static struct ast_config * realtime_multi_handler(const char *database, | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	const char *table, const struct ast_variable *fields); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \brief Asterisk callback function for RealTime configuration (variable | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * update). | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * Asterisk will call this function each time a variable has been modified | 
					
						
							|  |  |  |  * internally and must be updated in the backend engine. keyfield and entity | 
					
						
							|  |  |  |  * are used to find the row to update, e.g. <code>UPDATE table SET ... WHERE | 
					
						
							|  |  |  |  * keyfield = 'entity';</code>. ap is a list of parameters and values with the | 
					
						
							|  |  |  |  * same format as the other realtime functions. | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * \param database the database to use (ignored) | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \param table the table to use | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * \param keyfield the column of the matching cell | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \param entity the value of the matching cell | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  |  * \param fields list of parameters and new values to update in the database | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \retval the number of affected rows. | 
					
						
							|  |  |  |  * \retval -1 if an error occurred. | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | static int realtime_update_handler(const char *database, const char *table, | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	const char *keyfield, const char *entity, const struct ast_variable *fields); | 
					
						
							| 
									
										
										
										
											2008-10-14 00:08:52 +00:00
										 |  |  | static int realtime_update2_handler(const char *database, const char *table, | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	const struct ast_variable *lookup_fields, const struct ast_variable *update_fields); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief Asterisk callback function for RealTime configuration (variable | 
					
						
							|  |  |  |  * create/store). | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  |  * Asterisk will call this function each time a variable has been created | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * internally and must be stored in the backend engine. | 
					
						
							|  |  |  |  * are used to find the row to update, e.g. ap is a list of parameters and | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  |  * values with the same format as the other realtime functions. | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  |  * \param database the database to use (ignored) | 
					
						
							|  |  |  |  * \param table the table to use | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  |  * \param fields list of parameters and new values to insert into the database | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  |  * \retval the rowid of inserted row. | 
					
						
							|  |  |  |  * \retval -1 if an error occurred. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int realtime_store_handler(const char *database, const char *table, | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	const struct ast_variable *fields); | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * \brief Asterisk callback function for RealTime configuration (destroys | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  |  * variable). | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  |  * Asterisk will call this function each time a variable has been destroyed | 
					
						
							|  |  |  |  * internally and must be removed from the backend engine. keyfield and entity | 
					
						
							|  |  |  |  * are used to find the row to delete, e.g. <code>DELETE FROM table WHERE | 
					
						
							|  |  |  |  * keyfield = 'entity';</code>. ap is a list of parameters and values with the | 
					
						
							|  |  |  |  * same format as the other realtime functions. | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  |  * \param database the database to use (ignored) | 
					
						
							|  |  |  |  * \param table the table to use | 
					
						
							|  |  |  |  * \param keyfield the column of the matching cell | 
					
						
							|  |  |  |  * \param entity the value of the matching cell | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  |  * \param fields list of additional parameters for cell matching | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  |  * \retval the number of affected rows. | 
					
						
							|  |  |  |  * \retval -1 if an error occurred. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int realtime_destroy_handler(const char *database, const char *table, | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	const char *keyfield, const char *entity, const struct ast_variable *fields); | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \brief Asterisk callback function for the CLI status command. | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-11-12 23:44:20 +00:00
										 |  |  |  * \param e CLI command | 
					
						
							| 
									
										
										
										
											2017-12-22 09:23:22 -05:00
										 |  |  |  * \param cmd | 
					
						
							| 
									
										
										
										
											2007-11-12 23:44:20 +00:00
										 |  |  |  * \param a CLI argument list | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * \return RESULT_SUCCESS | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2007-10-19 18:01:00 +00:00
										 |  |  | static char *handle_cli_show_sqlite_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a); | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | static char *handle_cli_sqlite_show_tables(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int realtime_require_handler(const char *database, const char *table, va_list ap); | 
					
						
							|  |  |  | static int realtime_unload_handler(const char *unused, const char *tablename); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  | /*! The SQLite database object. */ | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | static sqlite *db; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  | /*! Set to 1 if CDR support is enabled. */ | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | static int use_cdr; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  | /*! Set to 1 if the CDR callback function was registered. */ | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | static int cdr_registered; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  | /*! Set to 1 if the CLI status command callback function was registered. */ | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | static int cli_status_registered; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  | /*! The path of the database file. */ | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | static char *dbfile; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  | /*! The name of the static configuration table. */ | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | static char *config_table; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  | /*! The name of the table used to store CDR entries. */ | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | static char *cdr_table; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * The structure specifying all callback functions used by Asterisk for static | 
					
						
							|  |  |  |  * and RealTime configuration. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static struct ast_config_engine sqlite_engine = | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 	.name = RES_CONFIG_SQLITE_DRIVER, | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 	.load_func = config_handler, | 
					
						
							|  |  |  | 	.realtime_func = realtime_handler, | 
					
						
							|  |  |  | 	.realtime_multi_func = realtime_multi_handler, | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 	.store_func = realtime_store_handler, | 
					
						
							|  |  |  | 	.destroy_func = realtime_destroy_handler, | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 	.update_func = realtime_update_handler, | 
					
						
							| 
									
										
										
										
											2008-10-14 00:08:52 +00:00
										 |  |  | 	.update2_func = realtime_update2_handler, | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 	.require_func = realtime_require_handler, | 
					
						
							|  |  |  | 	.unload_func = realtime_unload_handler, | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * The mutex used to prevent simultaneous access to the SQLite database. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | AST_MUTEX_DEFINE_STATIC(mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * Structure containing details and callback functions for the CLI status | 
					
						
							|  |  |  |  * command. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2007-10-19 18:01:00 +00:00
										 |  |  | static struct ast_cli_entry cli_status[] = { | 
					
						
							| 
									
										
										
										
											2007-10-22 20:05:18 +00:00
										 |  |  | 	AST_CLI_DEFINE(handle_cli_show_sqlite_status, "Show status information about the SQLite 2 driver"), | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 	AST_CLI_DEFINE(handle_cli_sqlite_show_tables, "Cached table information about the SQLite 2 driver"), | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct sqlite_cache_columns { | 
					
						
							|  |  |  | 	char *name; | 
					
						
							|  |  |  | 	char *type; | 
					
						
							|  |  |  | 	unsigned char isint;    /*!< By definition, only INTEGER PRIMARY KEY is an integer; everything else is a string. */ | 
					
						
							|  |  |  | 	AST_RWLIST_ENTRY(sqlite_cache_columns) list; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | struct sqlite_cache_tables { | 
					
						
							|  |  |  | 	char *name; | 
					
						
							|  |  |  | 	AST_RWLIST_HEAD(_columns, sqlite_cache_columns) columns; | 
					
						
							|  |  |  | 	AST_RWLIST_ENTRY(sqlite_cache_tables) list; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static AST_RWLIST_HEAD_STATIC(sqlite_tables, sqlite_cache_tables); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Taken from Asterisk 1.2 cdr_sqlite.so. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  | /*! SQL query format to create the CDR table if non existent. */ | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | static char *sql_create_cdr_table = | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | "CREATE TABLE '%q' (\n" | 
					
						
							|  |  |  | "	id		INTEGER,\n" | 
					
						
							|  |  |  | "	clid		VARCHAR(80)	NOT NULL	DEFAULT '',\n" | 
					
						
							|  |  |  | "	src		VARCHAR(80)	NOT NULL	DEFAULT '',\n" | 
					
						
							|  |  |  | "	dst		VARCHAR(80)	NOT NULL	DEFAULT '',\n" | 
					
						
							|  |  |  | "	dcontext	VARCHAR(80)	NOT NULL	DEFAULT '',\n" | 
					
						
							|  |  |  | "	channel		VARCHAR(80)	NOT NULL	DEFAULT '',\n" | 
					
						
							|  |  |  | "	dstchannel	VARCHAR(80)	NOT NULL	DEFAULT '',\n" | 
					
						
							|  |  |  | "	lastapp		VARCHAR(80)	NOT NULL	DEFAULT '',\n" | 
					
						
							|  |  |  | "	lastdata	VARCHAR(80)	NOT NULL	DEFAULT '',\n" | 
					
						
							|  |  |  | "	start		DATETIME	NOT NULL	DEFAULT '0000-00-00 00:00:00',\n" | 
					
						
							|  |  |  | "	answer		DATETIME	NOT NULL	DEFAULT '0000-00-00 00:00:00',\n" | 
					
						
							|  |  |  | "	end		DATETIME	NOT NULL	DEFAULT '0000-00-00 00:00:00',\n" | 
					
						
							|  |  |  | "	duration	INT(11)		NOT NULL	DEFAULT 0,\n" | 
					
						
							|  |  |  | "	billsec		INT(11)		NOT NULL	DEFAULT 0,\n" | 
					
						
							|  |  |  | "	disposition	VARCHAR(45)	NOT NULL	DEFAULT '',\n" | 
					
						
							|  |  |  | "	amaflags	INT(11)		NOT NULL	DEFAULT 0,\n" | 
					
						
							|  |  |  | "	accountcode	VARCHAR(20)	NOT NULL	DEFAULT '',\n" | 
					
						
							|  |  |  | "	uniqueid	VARCHAR(32)	NOT NULL	DEFAULT '',\n" | 
					
						
							|  |  |  | "	userfield	VARCHAR(255)	NOT NULL	DEFAULT '',\n" | 
					
						
							|  |  |  | "	PRIMARY KEY	(id)\n" | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | ");"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | /*!
 | 
					
						
							|  |  |  |  * SQL query format to describe the table structure | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2008-11-29 15:29:33 +00:00
										 |  |  | #define sql_table_structure "SELECT sql FROM sqlite_master WHERE type='table' AND tbl_name='%s'"
 | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * SQL query format to fetch the static configuration of a file. | 
					
						
							|  |  |  |  * Rows must be sorted by category. | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-07-23 14:32:04 +00:00
										 |  |  |  * \see add_cfg_entry() | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2008-11-29 15:29:33 +00:00
										 |  |  | #define sql_get_config_table \
 | 
					
						
							|  |  |  | 	"SELECT *" \ | 
					
						
							|  |  |  | 	"	FROM '%q'" \ | 
					
						
							|  |  |  | 	"	WHERE filename = '%q' AND commented = 0" \ | 
					
						
							|  |  |  | 	"	ORDER BY cat_metric ASC, var_metric ASC;" | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | static void free_table(struct sqlite_cache_tables *tblptr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct sqlite_cache_columns *col; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Obtain a write lock to ensure there are no read locks outstanding */ | 
					
						
							|  |  |  | 	AST_RWLIST_WRLOCK(&(tblptr->columns)); | 
					
						
							|  |  |  | 	while ((col = AST_RWLIST_REMOVE_HEAD(&(tblptr->columns), list))) { | 
					
						
							|  |  |  | 		ast_free(col); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	AST_RWLIST_UNLOCK(&(tblptr->columns)); | 
					
						
							|  |  |  | 	AST_RWLIST_HEAD_DESTROY(&(tblptr->columns)); | 
					
						
							|  |  |  | 	ast_free(tblptr); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int find_table_cb(void *vtblptr, int argc, char **argv, char **columnNames) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct sqlite_cache_tables *tblptr = vtblptr; | 
					
						
							|  |  |  | 	char *sql = ast_strdupa(argv[0]), *start, *end, *type, *remainder; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	AST_DECLARE_APP_ARGS(fie, | 
					
						
							|  |  |  | 		AST_APP_ARG(ld)[100]; /* This means we support up to 100 columns per table */ | 
					
						
							|  |  |  | 	); | 
					
						
							|  |  |  | 	struct sqlite_cache_columns *col; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* This is really fun.  We get to parse an SQL statement to figure out
 | 
					
						
							|  |  |  | 	 * what columns are in the table. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	if ((start = strchr(sql, '(')) && (end = strrchr(sql, ')'))) { | 
					
						
							|  |  |  | 		start++; | 
					
						
							|  |  |  | 		*end = '\0'; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		/* Abort */ | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	AST_STANDARD_APP_ARGS(fie, start); | 
					
						
							|  |  |  | 	for (i = 0; i < fie.argc; i++) { | 
					
						
							|  |  |  | 		fie.ld[i] = ast_skip_blanks(fie.ld[i]); | 
					
						
							|  |  |  | 		ast_debug(5, "Found field: %s\n", fie.ld[i]); | 
					
						
							|  |  |  | 		if (strncasecmp(fie.ld[i], "PRIMARY KEY", 11) == 0 && (start = strchr(fie.ld[i], '(')) && (end = strchr(fie.ld[i], ')'))) { | 
					
						
							|  |  |  | 			*end = '\0'; | 
					
						
							|  |  |  | 			AST_RWLIST_TRAVERSE(&(tblptr->columns), col, list) { | 
					
						
							|  |  |  | 				if (strcasecmp(start + 1, col->name) == 0 && strcasestr(col->type, "INTEGER")) { | 
					
						
							|  |  |  | 					col->isint = 1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		/* type delimiter could be any space character */ | 
					
						
							|  |  |  | 		for (type = fie.ld[i]; *type > 32; type++); | 
					
						
							|  |  |  | 		*type++ = '\0'; | 
					
						
							|  |  |  | 		type = ast_skip_blanks(type); | 
					
						
							|  |  |  | 		for (remainder = type; *remainder > 32; remainder++); | 
					
						
							|  |  |  | 		*remainder = '\0'; | 
					
						
							|  |  |  | 		if (!(col = ast_calloc(1, sizeof(*col) + strlen(fie.ld[i]) + strlen(type) + 2))) { | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		col->name = (char *)col + sizeof(*col); | 
					
						
							|  |  |  | 		col->type = (char *)col + sizeof(*col) + strlen(fie.ld[i]) + 1; | 
					
						
							|  |  |  | 		strcpy(col->name, fie.ld[i]); /* SAFE */ | 
					
						
							|  |  |  | 		strcpy(col->type, type); /* SAFE */ | 
					
						
							|  |  |  | 		if (strcasestr(col->type, "INTEGER") && strcasestr(col->type, "PRIMARY KEY")) { | 
					
						
							|  |  |  | 			col->isint = 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		AST_LIST_INSERT_TAIL(&(tblptr->columns), col, list); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct sqlite_cache_tables *find_table(const char *tablename) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct sqlite_cache_tables *tblptr; | 
					
						
							|  |  |  | 	int i, err; | 
					
						
							|  |  |  | 	char *sql, *errstr = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	AST_RWLIST_RDLOCK(&sqlite_tables); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < 2; i++) { | 
					
						
							|  |  |  | 		AST_RWLIST_TRAVERSE(&sqlite_tables, tblptr, list) { | 
					
						
							|  |  |  | 			if (strcmp(tblptr->name, tablename) == 0) { | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (tblptr) { | 
					
						
							|  |  |  | 			AST_RWLIST_RDLOCK(&(tblptr->columns)); | 
					
						
							|  |  |  | 			AST_RWLIST_UNLOCK(&sqlite_tables); | 
					
						
							|  |  |  | 			return tblptr; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (i == 0) { | 
					
						
							|  |  |  | 			AST_RWLIST_UNLOCK(&sqlite_tables); | 
					
						
							|  |  |  | 			AST_RWLIST_WRLOCK(&sqlite_tables); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Table structure not cached; build the structure now */ | 
					
						
							| 
									
										
										
										
											2012-08-21 21:01:11 +00:00
										 |  |  | 	if (ast_asprintf(&sql, sql_table_structure, tablename) < 0) { | 
					
						
							| 
									
										
										
										
											2008-11-02 18:52:13 +00:00
										 |  |  | 		sql = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 	if (!(tblptr = ast_calloc(1, sizeof(*tblptr) + strlen(tablename) + 1))) { | 
					
						
							|  |  |  | 		AST_RWLIST_UNLOCK(&sqlite_tables); | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Memory error.  Cannot cache table '%s'\n", tablename); | 
					
						
							| 
									
										
										
										
											2012-08-21 21:01:11 +00:00
										 |  |  | 		ast_free(sql); | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	tblptr->name = (char *)tblptr + sizeof(*tblptr); | 
					
						
							|  |  |  | 	strcpy(tblptr->name, tablename); /* SAFE */ | 
					
						
							|  |  |  | 	AST_RWLIST_HEAD_INIT(&(tblptr->columns)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_debug(1, "About to query table structure: %s\n", sql); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_lock(&mutex); | 
					
						
							|  |  |  | 	if ((err = sqlite_exec(db, sql, find_table_cb, tblptr, &errstr))) { | 
					
						
							|  |  |  | 		ast_mutex_unlock(&mutex); | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "SQLite error %d: %s\n", err, errstr); | 
					
						
							|  |  |  | 		ast_free(errstr); | 
					
						
							|  |  |  | 		free_table(tblptr); | 
					
						
							| 
									
										
										
										
											2010-06-08 06:57:24 +00:00
										 |  |  | 		AST_RWLIST_UNLOCK(&sqlite_tables); | 
					
						
							| 
									
										
										
										
											2012-08-21 21:01:11 +00:00
										 |  |  | 		ast_free(sql); | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ast_mutex_unlock(&mutex); | 
					
						
							| 
									
										
										
										
											2012-08-21 21:01:11 +00:00
										 |  |  | 	ast_free(sql); | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (AST_LIST_EMPTY(&(tblptr->columns))) { | 
					
						
							|  |  |  | 		free_table(tblptr); | 
					
						
							| 
									
										
										
										
											2010-06-08 06:57:24 +00:00
										 |  |  | 		AST_RWLIST_UNLOCK(&sqlite_tables); | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	AST_RWLIST_INSERT_TAIL(&sqlite_tables, tblptr, list); | 
					
						
							|  |  |  | 	AST_RWLIST_RDLOCK(&(tblptr->columns)); | 
					
						
							|  |  |  | 	AST_RWLIST_UNLOCK(&sqlite_tables); | 
					
						
							|  |  |  | 	return tblptr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define release_table(a)	AST_RWLIST_UNLOCK(&((a)->columns))
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-14 15:13:22 +00:00
										 |  |  | static int set_var(char **var, const char *name, const char *value) | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (*var) | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 		ast_free(*var); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	*var = ast_strdup(value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!*var) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Unable to allocate variable %s\n", name); | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int check_vars(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (!dbfile) { | 
					
						
							| 
									
										
										
										
											2008-07-16 19:57:02 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "Required parameter undefined: dbfile\n"); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	use_cdr = (cdr_table != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int load_config(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct ast_config *config; | 
					
						
							|  |  |  | 	struct ast_variable *var; | 
					
						
							|  |  |  | 	int error; | 
					
						
							| 
									
										
										
										
											2007-08-16 21:09:46 +00:00
										 |  |  | 	struct ast_flags config_flags = { 0 }; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 	config = ast_config_load(RES_CONFIG_SQLITE_CONF_FILE, config_flags); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-12 23:30:03 +00:00
										 |  |  | 	if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEINVALID) { | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "Unable to load " RES_CONFIG_SQLITE_CONF_FILE "\n"); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (var = ast_variable_browse(config, "general"); var; var = var->next) { | 
					
						
							|  |  |  | 		if (!strcasecmp(var->name, "dbfile")) | 
					
						
							|  |  |  | 			SET_VAR(config, dbfile, var); | 
					
						
							|  |  |  | 		else if (!strcasecmp(var->name, "config_table")) | 
					
						
							|  |  |  | 			SET_VAR(config, config_table, var); | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 		else if (!strcasecmp(var->name, "cdr_table")) { | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 			SET_VAR(config, cdr_table, var); | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 		} else | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 			ast_log(LOG_WARNING, "Unknown parameter : %s\n", var->name); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_config_destroy(config); | 
					
						
							|  |  |  | 	error = check_vars(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (error) { | 
					
						
							|  |  |  | 		unload_config(); | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void unload_config(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 	struct sqlite_cache_tables *tbl; | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 	ast_free(dbfile); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 	dbfile = NULL; | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 	ast_free(config_table); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 	config_table = NULL; | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 	ast_free(cdr_table); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 	cdr_table = NULL; | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 	AST_RWLIST_WRLOCK(&sqlite_tables); | 
					
						
							|  |  |  | 	while ((tbl = AST_RWLIST_REMOVE_HEAD(&sqlite_tables, list))) { | 
					
						
							|  |  |  | 		free_table(tbl); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	AST_RWLIST_UNLOCK(&sqlite_tables); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int cdr_handler(struct ast_cdr *cdr) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 	char *errormsg = NULL, *tmp, workspace[500]; | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 	int error, scannum; | 
					
						
							|  |  |  | 	struct sqlite_cache_tables *tbl = find_table(cdr_table); | 
					
						
							|  |  |  | 	struct sqlite_cache_columns *col; | 
					
						
							|  |  |  | 	struct ast_str *sql1 = ast_str_create(160), *sql2 = ast_str_create(16); | 
					
						
							| 
									
										
										
										
											2008-12-13 08:36:35 +00:00
										 |  |  | 	int first = 1; | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-17 16:34:41 -05:00
										 |  |  | 	if (!sql1 || !sql2) { | 
					
						
							|  |  |  | 		ast_free(sql1); | 
					
						
							|  |  |  | 		ast_free(sql2); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 	if (!tbl) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "No such table: %s\n", cdr_table); | 
					
						
							| 
									
										
										
										
											2015-09-17 16:34:41 -05:00
										 |  |  | 		ast_free(sql1); | 
					
						
							|  |  |  | 		ast_free(sql2); | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 	ast_str_set(&sql1, 0, "INSERT INTO %s (", cdr_table); | 
					
						
							|  |  |  | 	ast_str_set(&sql2, 0, ") VALUES ("); | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 	AST_RWLIST_TRAVERSE(&(tbl->columns), col, list) { | 
					
						
							|  |  |  | 		if (col->isint) { | 
					
						
							| 
									
										
										
										
											2013-06-17 03:00:38 +00:00
										 |  |  | 			ast_cdr_format_var(cdr, col->name, &tmp, workspace, sizeof(workspace), 1); | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 			if (!tmp) { | 
					
						
							|  |  |  | 				continue; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-08-10 19:20:57 +00:00
										 |  |  | 			if (sscanf(tmp, "%30d", &scannum) == 1) { | 
					
						
							| 
									
										
										
										
											2008-12-13 08:36:35 +00:00
										 |  |  | 				ast_str_append(&sql1, 0, "%s%s", first ? "" : ",", col->name); | 
					
						
							|  |  |  | 				ast_str_append(&sql2, 0, "%s%d", first ? "" : ",", scannum); | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2013-06-17 03:00:38 +00:00
										 |  |  | 			ast_cdr_format_var(cdr, col->name, &tmp, workspace, sizeof(workspace), 0); | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 			if (!tmp) { | 
					
						
							|  |  |  | 				continue; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-12-13 08:36:35 +00:00
										 |  |  | 			ast_str_append(&sql1, 0, "%s%s", first ? "" : ",", col->name); | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 			tmp = sqlite_mprintf("%Q", tmp); | 
					
						
							| 
									
										
										
										
											2008-12-13 08:36:35 +00:00
										 |  |  | 			ast_str_append(&sql2, 0, "%s%s", first ? "" : ",", tmp); | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 			sqlite_freemem(tmp); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-02-05 19:36:29 +00:00
										 |  |  | 		first = 0; | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 	release_table(tbl); | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-13 08:36:35 +00:00
										 |  |  | 	ast_str_append(&sql1, 0, "%s)", ast_str_buffer(sql2)); | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 	ast_free(sql2); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-13 08:36:35 +00:00
										 |  |  | 	ast_debug(1, "SQL query: %s\n", ast_str_buffer(sql1)); | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 	ast_mutex_lock(&mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 	RES_CONFIG_SQLITE_BEGIN | 
					
						
							| 
									
										
										
										
											2008-12-13 08:36:35 +00:00
										 |  |  | 		error = sqlite_exec(db, ast_str_buffer(sql1), NULL, NULL, &errormsg); | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 	RES_CONFIG_SQLITE_END(error) | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_unlock(&mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 	ast_free(sql1); | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 	if (error) { | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "%s\n", S_OR(errormsg, sqlite_error_string(error))); | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 		sqlite_freemem(errormsg); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 	sqlite_freemem(errormsg); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int add_cfg_entry(void *arg, int argc, char **argv, char **columnNames) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct cfg_entry_args *args; | 
					
						
							|  |  |  | 	struct ast_variable *var; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 	if (argc != RES_CONFIG_SQLITE_CONFIG_COLUMNS) { | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		ast_log(LOG_WARNING, "Corrupt table\n"); | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	args = arg; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-17 20:24:50 +00:00
										 |  |  | 	if (!strcmp(argv[RES_CONFIG_SQLITE_CONFIG_VAR_NAME], "#include")) { | 
					
						
							|  |  |  | 		struct ast_config *cfg; | 
					
						
							|  |  |  | 		char *val; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		val = argv[RES_CONFIG_SQLITE_CONFIG_VAR_VAL]; | 
					
						
							| 
									
										
										
										
											2008-03-11 22:55:16 +00:00
										 |  |  | 		cfg = ast_config_internal_load(val, args->cfg, args->flags, "", args->who_asked); | 
					
						
							| 
									
										
										
										
											2007-09-17 20:24:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (!cfg) { | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "Unable to include %s\n", val); | 
					
						
							|  |  |  | 			return 1; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			args->cfg = cfg; | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 	if (!args->cat_name || strcmp(args->cat_name, argv[RES_CONFIG_SQLITE_CONFIG_CATEGORY])) { | 
					
						
							| 
									
										
										
										
											2017-02-21 09:56:54 -05:00
										 |  |  | 		args->cat = ast_category_new_dynamic(argv[RES_CONFIG_SQLITE_CONFIG_CATEGORY]); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		if (!args->cat) { | 
					
						
							|  |  |  | 			return 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 		ast_free(args->cat_name); | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 		args->cat_name = ast_strdup(argv[RES_CONFIG_SQLITE_CONFIG_CATEGORY]); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (!args->cat_name) { | 
					
						
							|  |  |  | 			ast_category_destroy(args->cat); | 
					
						
							|  |  |  | 			return 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ast_category_append(args->cfg, args->cat); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 	var = ast_variable_new(argv[RES_CONFIG_SQLITE_CONFIG_VAR_NAME], argv[RES_CONFIG_SQLITE_CONFIG_VAR_VAL], ""); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!var) { | 
					
						
							| 
									
										
										
										
											2012-04-06 18:19:03 +00:00
										 |  |  | 		ast_log(LOG_WARNING, "Unable to allocate variable\n"); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_variable_append(args->cat, var); | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-29 20:55:40 +00:00
										 |  |  | static struct ast_config *config_handler(const char *database,	const char *table, const char *file, | 
					
						
							| 
									
										
										
										
											2008-03-11 22:55:16 +00:00
										 |  |  | 	struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl, const char *who_asked) | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct cfg_entry_args args; | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 	char *query, *errormsg = NULL; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 	int error; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!config_table) { | 
					
						
							|  |  |  | 		if (!table) { | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "Table name unspecified\n"); | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else | 
					
						
							|  |  |  | 		table = config_table; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 	query = sqlite_mprintf(sql_get_config_table, table, file); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!query) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Unable to allocate SQL query\n"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_debug(1, "SQL query: %s\n", query); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 	args.cfg = cfg; | 
					
						
							|  |  |  | 	args.cat = NULL; | 
					
						
							|  |  |  | 	args.cat_name = NULL; | 
					
						
							| 
									
										
										
										
											2007-09-17 20:24:50 +00:00
										 |  |  | 	args.flags = flags; | 
					
						
							| 
									
										
										
										
											2008-03-11 22:55:16 +00:00
										 |  |  | 	args.who_asked = who_asked; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_lock(&mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 	RES_CONFIG_SQLITE_BEGIN | 
					
						
							|  |  |  | 		error = sqlite_exec(db, query, add_cfg_entry, &args, &errormsg); | 
					
						
							|  |  |  | 	RES_CONFIG_SQLITE_END(error) | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_unlock(&mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 	ast_free(args.cat_name); | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 	sqlite_freemem(query); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (error) { | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "%s\n", S_OR(errormsg, sqlite_error_string(error))); | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 		sqlite_freemem(errormsg); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 	sqlite_freemem(errormsg); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return cfg; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int add_rt_cfg_entry(void *arg, int argc, char **argv, char **columnNames) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct rt_cfg_entry_args *args; | 
					
						
							|  |  |  | 	struct ast_variable *var; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	args = arg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < argc; i++) { | 
					
						
							|  |  |  | 		if (!argv[i]) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-29 20:55:40 +00:00
										 |  |  | 		if (!(var = ast_variable_new(columnNames[i], argv[i], ""))) | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 			return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!args->var) | 
					
						
							|  |  |  | 			args->var = var; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!args->last) | 
					
						
							|  |  |  | 			args->last = var; | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			args->last->next = var; | 
					
						
							|  |  |  | 			args->last = var; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | static struct ast_variable * realtime_handler(const char *database, const char *table, const struct ast_variable *fields) | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 	char *query, *errormsg = NULL, *op, *tmp_str; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 	struct rt_cfg_entry_args args; | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	const struct ast_variable *field = fields; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 	int error; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!table) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Table name unspecified\n"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	if (!fields) { | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	op = (strchr(field->name, ' ') == NULL) ? " =" : ""; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* \cond DOXYGEN_CAN_PARSE_THIS */ | 
					
						
							|  |  |  | #undef QUERY
 | 
					
						
							| 
									
										
										
										
											2008-10-14 00:08:52 +00:00
										 |  |  | #define QUERY "SELECT * FROM '%q' WHERE%s %q%s '%q'"
 | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | /* \endcond */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	query = sqlite_mprintf(QUERY, table, (config_table && !strcmp(config_table, table)) ? " commented = 0 AND" : "", field->name, op, field->value); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!query) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Unable to allocate SQL query\n"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	while ((field = field->next)) { | 
					
						
							|  |  |  | 		op = (strchr(field->name, ' ') == NULL) ? " =" : ""; | 
					
						
							|  |  |  | 		tmp_str = sqlite_mprintf("%s AND %q%s '%q'", query, field->name, op, field->value); | 
					
						
							|  |  |  | 		sqlite_freemem(query); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 		if (!tmp_str) { | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "Unable to reallocate SQL query\n"); | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 		query = tmp_str; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	tmp_str = sqlite_mprintf("%s LIMIT 1;", query); | 
					
						
							|  |  |  | 	sqlite_freemem(query); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!tmp_str) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Unable to reallocate SQL query\n"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	query = tmp_str; | 
					
						
							| 
									
										
										
										
											2007-06-14 19:39:12 +00:00
										 |  |  | 	ast_debug(1, "SQL query: %s\n", query); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 	args.var = NULL; | 
					
						
							|  |  |  | 	args.last = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_lock(&mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 	RES_CONFIG_SQLITE_BEGIN | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		error = sqlite_exec(db, query, add_rt_cfg_entry, &args, &errormsg); | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 	RES_CONFIG_SQLITE_END(error) | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_unlock(&mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sqlite_freemem(query); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (error) { | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 		ast_log(LOG_WARNING, "%s\n", S_OR(errormsg, sqlite_error_string(error))); | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 		sqlite_freemem(errormsg); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		ast_variables_destroy(args.var); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 	sqlite_freemem(errormsg); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return args.var; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int add_rt_multi_cfg_entry(void *arg, int argc, char **argv, char **columnNames) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct rt_multi_cfg_entry_args *args; | 
					
						
							|  |  |  | 	struct ast_category *cat; | 
					
						
							|  |  |  | 	struct ast_variable *var; | 
					
						
							|  |  |  | 	char *cat_name; | 
					
						
							|  |  |  | 	size_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 	args = arg; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 	cat_name = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * cat_name should always be set here, since initfield is forged from | 
					
						
							|  |  |  | 	 * params[0] in realtime_multi_handler(), which is a search parameter | 
					
						
							|  |  |  | 	 * of the SQL query. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	for (i = 0; i < argc; i++) { | 
					
						
							|  |  |  | 		if (!strcmp(args->initfield, columnNames[i])) | 
					
						
							|  |  |  | 			cat_name = argv[i]; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!cat_name) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Bogus SQL results, cat_name is NULL !\n"); | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-21 09:56:54 -05:00
										 |  |  | 	cat = ast_category_new_dynamic(cat_name); | 
					
						
							|  |  |  | 	if (!cat) { | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_category_append(args->cfg, cat); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < argc; i++) { | 
					
						
							| 
									
										
										
										
											2011-10-13 00:17:42 +00:00
										 |  |  | 		if (!argv[i]) { | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2011-10-13 00:17:42 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-29 20:55:40 +00:00
										 |  |  | 		if (!(var = ast_variable_new(columnNames[i], argv[i], ""))) { | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 			ast_log(LOG_WARNING, "Unable to allocate variable\n"); | 
					
						
							|  |  |  | 			return 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ast_variable_append(cat, var); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | static struct ast_config *realtime_multi_handler(const char *database, | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	const char *table, const struct ast_variable *fields) | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 	char *query, *errormsg = NULL, *op, *tmp_str, *initfield; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 	struct rt_multi_cfg_entry_args args; | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	const struct ast_variable *field = fields; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 	struct ast_config *cfg; | 
					
						
							|  |  |  | 	int error; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!table) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Table name unspecified\n"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	if (!fields) { | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	if (!(cfg = ast_config_new())) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Unable to allocate configuration structure\n"); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	if (!(initfield = ast_strdup(field->name))) { | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		ast_config_destroy(cfg); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tmp_str = strchr(initfield, ' '); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (tmp_str) | 
					
						
							|  |  |  | 		*tmp_str = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	op = (!strchr(field->name, ' ')) ? " =" : ""; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Asterisk sends us an already escaped string when searching for | 
					
						
							|  |  |  | 	 * "exten LIKE" (uh!). Handle it separately. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	tmp_str = (!strcmp(field->value, "\\_%")) ? "_%" : (char *)field->value; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* \cond DOXYGEN_CAN_PARSE_THIS */ | 
					
						
							|  |  |  | #undef QUERY
 | 
					
						
							| 
									
										
										
										
											2011-11-03 20:37:50 +00:00
										 |  |  | #define QUERY "SELECT * FROM '%q' WHERE%s %q%s '%q'"
 | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | /* \endcond */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	if (!(query = sqlite_mprintf(QUERY, table, (config_table && !strcmp(config_table, table)) ? " commented = 0 AND" : "", field->name, op, tmp_str))) { | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		ast_log(LOG_WARNING, "Unable to allocate SQL query\n"); | 
					
						
							|  |  |  | 		ast_config_destroy(cfg); | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 		ast_free(initfield); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	while ((field = field->next)) { | 
					
						
							|  |  |  | 		op = (!strchr(field->name, ' ')) ? " =" : ""; | 
					
						
							|  |  |  | 		tmp_str = sqlite_mprintf("%s AND %q%s '%q'", query, field->name, op, field->value); | 
					
						
							|  |  |  | 		sqlite_freemem(query); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 		if (!tmp_str) { | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "Unable to reallocate SQL query\n"); | 
					
						
							|  |  |  | 			ast_config_destroy(cfg); | 
					
						
							|  |  |  | 			ast_free(initfield); | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 		query = tmp_str; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!(tmp_str = sqlite_mprintf("%s ORDER BY %q;", query, initfield))) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Unable to reallocate SQL query\n"); | 
					
						
							| 
									
										
										
										
											2008-07-17 15:45:25 +00:00
										 |  |  | 		sqlite_freemem(query); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		ast_config_destroy(cfg); | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 		ast_free(initfield); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sqlite_freemem(query); | 
					
						
							|  |  |  | 	query = tmp_str; | 
					
						
							| 
									
										
										
										
											2007-06-14 19:39:12 +00:00
										 |  |  | 	ast_debug(1, "SQL query: %s\n", query); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 	args.cfg = cfg; | 
					
						
							|  |  |  | 	args.initfield = initfield; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_lock(&mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 	RES_CONFIG_SQLITE_BEGIN | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		error = sqlite_exec(db, query, add_rt_multi_cfg_entry, &args, &errormsg); | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 	RES_CONFIG_SQLITE_END(error) | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_unlock(&mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sqlite_freemem(query); | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 	ast_free(initfield); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (error) { | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 		ast_log(LOG_WARNING, "%s\n", S_OR(errormsg, sqlite_error_string(error))); | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 		sqlite_freemem(errormsg); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		ast_config_destroy(cfg); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 	sqlite_freemem(errormsg); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return cfg; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int realtime_update_handler(const char *database, const char *table, | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	const char *keyfield, const char *entity, const struct ast_variable *fields) | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 	char *query, *errormsg = NULL, *tmp_str; | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	const struct ast_variable *field = fields; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 	int error, rows_num; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!table) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Table name unspecified\n"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	if (!field) { | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* \cond DOXYGEN_CAN_PARSE_THIS */ | 
					
						
							|  |  |  | #undef QUERY
 | 
					
						
							|  |  |  | #define QUERY "UPDATE '%q' SET %q = '%q'"
 | 
					
						
							|  |  |  | /* \endcond */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	if (!(query = sqlite_mprintf(QUERY, table, field->name, field->value))) { | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		ast_log(LOG_WARNING, "Unable to allocate SQL query\n"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	while ((field = field->next)) { | 
					
						
							|  |  |  | 		tmp_str = sqlite_mprintf("%s, %q = '%q'", query, field->name, field->value); | 
					
						
							|  |  |  | 		sqlite_freemem(query); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 		if (!tmp_str) { | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "Unable to reallocate SQL query\n"); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 		query = tmp_str; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!(tmp_str = sqlite_mprintf("%s WHERE %q = '%q';", query, keyfield, entity))) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Unable to reallocate SQL query\n"); | 
					
						
							| 
									
										
										
										
											2008-07-17 18:36:34 +00:00
										 |  |  | 		sqlite_freemem(query); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sqlite_freemem(query); | 
					
						
							|  |  |  | 	query = tmp_str; | 
					
						
							| 
									
										
										
										
											2007-06-14 19:39:12 +00:00
										 |  |  | 	ast_debug(1, "SQL query: %s\n", query); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_lock(&mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 	RES_CONFIG_SQLITE_BEGIN | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		error = sqlite_exec(db, query, NULL, NULL, &errormsg); | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 	RES_CONFIG_SQLITE_END(error) | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!error) | 
					
						
							|  |  |  | 		rows_num = sqlite_changes(db); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		rows_num = -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_unlock(&mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sqlite_freemem(query); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (error) { | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 		ast_log(LOG_WARNING, "%s\n", S_OR(errormsg, sqlite_error_string(error))); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 	sqlite_freemem(errormsg); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return rows_num; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-14 00:08:52 +00:00
										 |  |  | static int realtime_update2_handler(const char *database, const char *table, | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	const struct ast_variable *lookup_fields, const struct ast_variable *update_fields) | 
					
						
							| 
									
										
										
										
											2008-10-14 00:08:52 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	char *errormsg = NULL, *tmp1, *tmp2; | 
					
						
							|  |  |  | 	int error, rows_num, first = 1; | 
					
						
							|  |  |  | 	struct ast_str *sql = ast_str_thread_get(&sql_buf, 100); | 
					
						
							|  |  |  | 	struct ast_str *where = ast_str_thread_get(&where_buf, 100); | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	const struct ast_variable *field; | 
					
						
							| 
									
										
										
										
											2008-10-14 00:08:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!table) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Table name unspecified\n"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!sql) { | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_str_set(&sql, 0, "UPDATE %s SET", table); | 
					
						
							|  |  |  | 	ast_str_set(&where, 0, " WHERE"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	for (field = lookup_fields; field; field = field->next) { | 
					
						
							| 
									
										
										
										
											2008-10-14 00:08:52 +00:00
										 |  |  | 		ast_str_append(&where, 0, "%s %s = %s", | 
					
						
							|  |  |  | 			first ? "" : " AND", | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 			tmp1 = sqlite_mprintf("%q", field->name), | 
					
						
							|  |  |  | 			tmp2 = sqlite_mprintf("%Q", field->value)); | 
					
						
							| 
									
										
										
										
											2008-10-14 00:08:52 +00:00
										 |  |  | 		sqlite_freemem(tmp1); | 
					
						
							|  |  |  | 		sqlite_freemem(tmp2); | 
					
						
							|  |  |  | 		first = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (first) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "No criteria specified on update to '%s@%s'!\n", table, database); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	first = 1; | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	for (field = update_fields; field; field = field->next) { | 
					
						
							| 
									
										
										
										
											2008-10-14 00:08:52 +00:00
										 |  |  | 		ast_str_append(&sql, 0, "%s %s = %s", | 
					
						
							|  |  |  | 			first ? "" : ",", | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 			tmp1 = sqlite_mprintf("%q", field->name), | 
					
						
							|  |  |  | 			tmp2 = sqlite_mprintf("%Q", field->value)); | 
					
						
							| 
									
										
										
										
											2008-10-14 00:08:52 +00:00
										 |  |  | 		sqlite_freemem(tmp1); | 
					
						
							|  |  |  | 		sqlite_freemem(tmp2); | 
					
						
							|  |  |  | 		first = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-13 08:36:35 +00:00
										 |  |  | 	ast_str_append(&sql, 0, " %s", ast_str_buffer(where)); | 
					
						
							|  |  |  | 	ast_debug(1, "SQL query: %s\n", ast_str_buffer(sql)); | 
					
						
							| 
									
										
										
										
											2008-10-14 00:08:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_lock(&mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	RES_CONFIG_SQLITE_BEGIN | 
					
						
							| 
									
										
										
										
											2008-12-13 08:36:35 +00:00
										 |  |  | 		error = sqlite_exec(db, ast_str_buffer(sql), NULL, NULL, &errormsg); | 
					
						
							| 
									
										
										
										
											2008-10-14 00:08:52 +00:00
										 |  |  | 	RES_CONFIG_SQLITE_END(error) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!error) { | 
					
						
							|  |  |  | 		rows_num = sqlite_changes(db); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		rows_num = -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_unlock(&mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (error) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "%s\n", S_OR(errormsg, sqlite_error_string(error))); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	sqlite_freemem(errormsg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return rows_num; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | static int realtime_store_handler(const char *database, const char *table, const struct ast_variable *fields) | 
					
						
							| 
									
										
										
										
											2008-03-31 14:20:39 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 	char *errormsg = NULL, *tmp_str, *tmp_keys = NULL, *tmp_keys2 = NULL, *tmp_vals = NULL, *tmp_vals2 = NULL; | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	const struct ast_variable *field = fields; | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 	int error, rows_id; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!table) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Table name unspecified\n"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	if (!fields) { | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* \cond DOXYGEN_CAN_PARSE_THIS */ | 
					
						
							|  |  |  | #undef QUERY
 | 
					
						
							|  |  |  | #define QUERY "INSERT into '%q' (%s) VALUES (%s);"
 | 
					
						
							|  |  |  | /* \endcond */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	do { | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 		if ( tmp_keys2 ) { | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 			tmp_keys = sqlite_mprintf("%s, %q", tmp_keys2, field->name); | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 			sqlite_freemem(tmp_keys2); | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 			tmp_keys = sqlite_mprintf("%q", field->name); | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if (!tmp_keys) { | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "Unable to reallocate SQL query\n"); | 
					
						
							| 
									
										
										
										
											2008-07-17 18:36:34 +00:00
										 |  |  | 			sqlite_freemem(tmp_vals); | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if ( tmp_vals2 ) { | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 			tmp_vals = sqlite_mprintf("%s, '%q'", tmp_vals2, field->value); | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 			sqlite_freemem(tmp_vals2); | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 			tmp_vals = sqlite_mprintf("'%q'", field->value); | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if (!tmp_vals) { | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "Unable to reallocate SQL query\n"); | 
					
						
							| 
									
										
										
										
											2008-07-17 18:36:34 +00:00
										 |  |  | 			sqlite_freemem(tmp_keys); | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		tmp_keys2 = tmp_keys; | 
					
						
							|  |  |  | 		tmp_vals2 = tmp_vals; | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	} while ((field = field->next)); | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!(tmp_str = sqlite_mprintf(QUERY, table, tmp_keys, tmp_vals))) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Unable to reallocate SQL query\n"); | 
					
						
							| 
									
										
										
										
											2008-07-17 18:36:34 +00:00
										 |  |  | 		sqlite_freemem(tmp_keys); | 
					
						
							|  |  |  | 		sqlite_freemem(tmp_vals); | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sqlite_freemem(tmp_keys); | 
					
						
							|  |  |  | 	sqlite_freemem(tmp_vals); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_debug(1, "SQL query: %s\n", tmp_str); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_lock(&mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 	RES_CONFIG_SQLITE_BEGIN | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 		error = sqlite_exec(db, tmp_str, NULL, NULL, &errormsg); | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 	RES_CONFIG_SQLITE_END(error) | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!error) { | 
					
						
							|  |  |  | 		rows_id = sqlite_last_insert_rowid(db); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		rows_id = -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_unlock(&mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sqlite_freemem(tmp_str); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (error) { | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 		ast_log(LOG_WARNING, "%s\n", S_OR(errormsg, sqlite_error_string(error))); | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 	sqlite_freemem(errormsg); | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return rows_id; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int realtime_destroy_handler(const char *database, const char *table, | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	const char *keyfield, const char *entity, const struct ast_variable *fields) | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 	char *query, *errormsg = NULL, *tmp_str; | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	const struct ast_variable *field; | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 	int error, rows_num; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!table) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Table name unspecified\n"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* \cond DOXYGEN_CAN_PARSE_THIS */ | 
					
						
							|  |  |  | #undef QUERY
 | 
					
						
							|  |  |  | #define QUERY "DELETE FROM '%q' WHERE"
 | 
					
						
							|  |  |  | /* \endcond */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!(query = sqlite_mprintf(QUERY, table))) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Unable to allocate SQL query\n"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-27 16:17:01 +00:00
										 |  |  | 	for (field = fields; field; field = field->next) { | 
					
						
							|  |  |  | 		tmp_str = sqlite_mprintf("%s %q = '%q' AND", query, field->name, field->value); | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 		sqlite_freemem(query); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!tmp_str) { | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "Unable to reallocate SQL query\n"); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		query = tmp_str; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!(tmp_str = sqlite_mprintf("%s %q = '%q';", query, keyfield, entity))) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Unable to reallocate SQL query\n"); | 
					
						
							| 
									
										
										
										
											2008-07-17 18:36:34 +00:00
										 |  |  | 		sqlite_freemem(query); | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	sqlite_freemem(query); | 
					
						
							|  |  |  | 	query = tmp_str; | 
					
						
							|  |  |  | 	ast_debug(1, "SQL query: %s\n", query); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_lock(&mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 	RES_CONFIG_SQLITE_BEGIN | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 		error = sqlite_exec(db, query, NULL, NULL, &errormsg); | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 	RES_CONFIG_SQLITE_END(error) | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-14 00:08:52 +00:00
										 |  |  | 	if (!error) { | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 		rows_num = sqlite_changes(db); | 
					
						
							| 
									
										
										
										
											2008-10-14 00:08:52 +00:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 		rows_num = -1; | 
					
						
							| 
									
										
										
										
											2008-10-14 00:08:52 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_unlock(&mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sqlite_freemem(query); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (error) { | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 		ast_log(LOG_WARNING, "%s\n", S_OR(errormsg, sqlite_error_string(error))); | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 	sqlite_freemem(errormsg); | 
					
						
							| 
									
										
										
										
											2007-08-17 13:45:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return rows_num; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | static int realtime_require_handler(const char *unused, const char *tablename, va_list ap) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct sqlite_cache_tables *tbl = find_table(tablename); | 
					
						
							|  |  |  | 	struct sqlite_cache_columns *col; | 
					
						
							|  |  |  | 	char *elm; | 
					
						
							| 
									
										
										
										
											2011-05-05 22:44:52 +00:00
										 |  |  | 	int type, res = 0; | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!tbl) { | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while ((elm = va_arg(ap, char *))) { | 
					
						
							|  |  |  | 		type = va_arg(ap, require_type); | 
					
						
							| 
									
										
										
										
											2011-05-05 22:44:52 +00:00
										 |  |  | 		va_arg(ap, int); | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | 		/* Check if the field matches the criteria */ | 
					
						
							|  |  |  | 		AST_RWLIST_TRAVERSE(&tbl->columns, col, list) { | 
					
						
							|  |  |  | 			if (strcmp(col->name, elm) == 0) { | 
					
						
							|  |  |  | 				/* SQLite only has two types - the 32-bit integer field that
 | 
					
						
							|  |  |  | 				 * is the key column, and everything else (everything else | 
					
						
							|  |  |  | 				 * being a string). | 
					
						
							|  |  |  | 				 */ | 
					
						
							|  |  |  | 				if (col->isint && !ast_rq_is_int(type)) { | 
					
						
							|  |  |  | 					ast_log(LOG_WARNING, "Realtime table %s: column '%s' is an integer field, but Asterisk requires that it not be!\n", tablename, col->name); | 
					
						
							|  |  |  | 					res = -1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (!col) { | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "Realtime table %s requires column '%s', but that column does not exist!\n", tablename, elm); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	AST_RWLIST_UNLOCK(&(tbl->columns)); | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int realtime_unload_handler(const char *unused, const char *tablename) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct sqlite_cache_tables *tbl; | 
					
						
							|  |  |  | 	AST_RWLIST_WRLOCK(&sqlite_tables); | 
					
						
							|  |  |  | 	AST_RWLIST_TRAVERSE_SAFE_BEGIN(&sqlite_tables, tbl, list) { | 
					
						
							|  |  |  | 		if (!strcasecmp(tbl->name, tablename)) { | 
					
						
							|  |  |  | 			AST_RWLIST_REMOVE_CURRENT(list); | 
					
						
							|  |  |  | 			free_table(tbl); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	AST_RWLIST_TRAVERSE_SAFE_END | 
					
						
							|  |  |  | 	AST_RWLIST_UNLOCK(&sqlite_tables); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-19 18:01:00 +00:00
										 |  |  | static char *handle_cli_show_sqlite_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-10-19 18:01:00 +00:00
										 |  |  | 	switch (cmd) { | 
					
						
							|  |  |  | 	case CLI_INIT: | 
					
						
							| 
									
										
										
										
											2008-07-31 21:53:59 +00:00
										 |  |  | 		e->command = "sqlite show status"; | 
					
						
							| 
									
										
										
										
											2007-10-19 18:01:00 +00:00
										 |  |  | 		e->usage = | 
					
						
							| 
									
										
										
										
											2008-07-31 21:53:59 +00:00
										 |  |  | 			"Usage: sqlite show status\n" | 
					
						
							| 
									
										
										
										
											2007-10-19 18:01:00 +00:00
										 |  |  | 			"       Show status information about the SQLite 2 driver\n"; | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	case CLI_GENERATE: | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (a->argc != 3) | 
					
						
							|  |  |  | 		return CLI_SHOWUSAGE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_cli(a->fd, "SQLite database path: %s\n", dbfile); | 
					
						
							|  |  |  | 	ast_cli(a->fd, "config_table: "); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!config_table) | 
					
						
							| 
									
										
										
										
											2007-10-19 18:01:00 +00:00
										 |  |  | 		ast_cli(a->fd, "unspecified, must be present in extconfig.conf\n"); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2007-10-19 18:01:00 +00:00
										 |  |  | 		ast_cli(a->fd, "%s\n", config_table); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-19 18:01:00 +00:00
										 |  |  | 	ast_cli(a->fd, "cdr_table: "); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!cdr_table) | 
					
						
							| 
									
										
										
										
											2007-10-19 18:01:00 +00:00
										 |  |  | 		ast_cli(a->fd, "unspecified, CDR support disabled\n"); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2007-10-19 18:01:00 +00:00
										 |  |  | 		ast_cli(a->fd, "%s\n", cdr_table); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-19 18:01:00 +00:00
										 |  |  | 	return CLI_SUCCESS; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-30 17:32:28 +00:00
										 |  |  | static char *handle_cli_sqlite_show_tables(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct sqlite_cache_tables *tbl; | 
					
						
							|  |  |  | 	struct sqlite_cache_columns *col; | 
					
						
							|  |  |  | 	int found = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (cmd) { | 
					
						
							|  |  |  | 	case CLI_INIT: | 
					
						
							|  |  |  | 		e->command = "sqlite show tables"; | 
					
						
							|  |  |  | 		e->usage = | 
					
						
							|  |  |  | 			"Usage: sqlite show tables\n" | 
					
						
							|  |  |  | 			"       Show table information about the SQLite 2 driver\n"; | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	case CLI_GENERATE: | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (a->argc != 3) | 
					
						
							|  |  |  | 		return CLI_SHOWUSAGE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	AST_RWLIST_RDLOCK(&sqlite_tables); | 
					
						
							|  |  |  | 	AST_RWLIST_TRAVERSE(&sqlite_tables, tbl, list) { | 
					
						
							|  |  |  | 		found++; | 
					
						
							|  |  |  | 		ast_cli(a->fd, "Table %s:\n", tbl->name); | 
					
						
							|  |  |  | 		AST_RWLIST_TRAVERSE(&(tbl->columns), col, list) { | 
					
						
							|  |  |  | 			fprintf(stderr, "%s\n", col->name); | 
					
						
							|  |  |  | 			ast_cli(a->fd, "  %20.20s  %-30.30s\n", col->name, col->type); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	AST_RWLIST_UNLOCK(&sqlite_tables); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!found) { | 
					
						
							|  |  |  | 		ast_cli(a->fd, "No tables currently in cache\n"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return CLI_SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | static int unload_module(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-12-08 05:59:46 +00:00
										 |  |  | 	if (cdr_registered && ast_cdr_unregister(RES_CONFIG_SQLITE_NAME)) { | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-08 05:59:46 +00:00
										 |  |  | 	if (cli_status_registered) { | 
					
						
							|  |  |  | 		ast_cli_unregister_multiple(cli_status, ARRAY_LEN(cli_status)); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ast_config_engine_deregister(&sqlite_engine); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (db) | 
					
						
							|  |  |  | 		sqlite_close(db); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	unload_config(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-01 23:24:10 +00:00
										 |  |  | /*!
 | 
					
						
							|  |  |  |  * \brief Load the module | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Module loading including tests for configuration or dependencies. | 
					
						
							|  |  |  |  * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, | 
					
						
							|  |  |  |  * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails | 
					
						
							| 
									
										
										
										
											2017-12-22 09:23:22 -05:00
										 |  |  |  * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the | 
					
						
							|  |  |  |  * configuration file or other non-critical problem return | 
					
						
							| 
									
										
										
										
											2012-10-01 23:24:10 +00:00
										 |  |  |  * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | static int load_module(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 	char *errormsg = NULL; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 	int error; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	db = NULL; | 
					
						
							|  |  |  | 	cdr_registered = 0; | 
					
						
							|  |  |  | 	cli_status_registered = 0; | 
					
						
							|  |  |  | 	dbfile = NULL; | 
					
						
							|  |  |  | 	config_table = NULL; | 
					
						
							|  |  |  | 	cdr_table = NULL; | 
					
						
							|  |  |  | 	error = load_config(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (error) | 
					
						
							|  |  |  | 		return AST_MODULE_LOAD_DECLINE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!(db = sqlite_open(dbfile, 0660, &errormsg))) { | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "%s\n", S_OR(errormsg, sqlite_error_string(error))); | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 		sqlite_freemem(errormsg); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		unload_module(); | 
					
						
							| 
									
										
										
										
											2017-04-11 10:07:39 -06:00
										 |  |  | 		return AST_MODULE_LOAD_DECLINE; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 	sqlite_freemem(errormsg); | 
					
						
							|  |  |  | 	errormsg = NULL; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 	ast_config_engine_register(&sqlite_engine); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (use_cdr) { | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 		char *query; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* \cond DOXYGEN_CAN_PARSE_THIS */ | 
					
						
							|  |  |  | #undef QUERY
 | 
					
						
							|  |  |  | #define QUERY "SELECT COUNT(id) FROM %Q;"
 | 
					
						
							|  |  |  | /* \endcond */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		query = sqlite_mprintf(QUERY, cdr_table); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!query) { | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "Unable to allocate SQL query\n"); | 
					
						
							|  |  |  | 			unload_module(); | 
					
						
							| 
									
										
										
										
											2017-04-11 10:07:39 -06:00
										 |  |  | 			return AST_MODULE_LOAD_DECLINE; | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ast_debug(1, "SQL query: %s\n", query); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		RES_CONFIG_SQLITE_BEGIN | 
					
						
							|  |  |  | 			error = sqlite_exec(db, query, NULL, NULL, &errormsg); | 
					
						
							|  |  |  | 		RES_CONFIG_SQLITE_END(error) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		sqlite_freemem(query); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (error) { | 
					
						
							|  |  |  | 			/*
 | 
					
						
							|  |  |  | 			 * Unexpected error. | 
					
						
							|  |  |  | 			 */ | 
					
						
							|  |  |  | 			if (error != SQLITE_ERROR) { | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 				ast_log(LOG_ERROR, "%s\n", S_OR(errormsg, sqlite_error_string(error))); | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 				sqlite_freemem(errormsg); | 
					
						
							|  |  |  | 				unload_module(); | 
					
						
							| 
									
										
										
										
											2017-04-11 10:07:39 -06:00
										 |  |  | 				return AST_MODULE_LOAD_DECLINE; | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			sqlite_freemem(errormsg); | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 			errormsg = NULL; | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 			query = sqlite_mprintf(sql_create_cdr_table, cdr_table); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (!query) { | 
					
						
							|  |  |  | 				ast_log(LOG_ERROR, "Unable to allocate SQL query\n"); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 				unload_module(); | 
					
						
							| 
									
										
										
										
											2017-04-11 10:07:39 -06:00
										 |  |  | 				return AST_MODULE_LOAD_DECLINE; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 			ast_debug(1, "SQL query: %s\n", query); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			RES_CONFIG_SQLITE_BEGIN | 
					
						
							|  |  |  | 				error = sqlite_exec(db, query, NULL, NULL, &errormsg); | 
					
						
							|  |  |  | 			RES_CONFIG_SQLITE_END(error) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			sqlite_freemem(query); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if (error) { | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 				ast_log(LOG_ERROR, "%s\n", S_OR(errormsg, sqlite_error_string(error))); | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 				sqlite_freemem(errormsg); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 				unload_module(); | 
					
						
							| 
									
										
										
										
											2017-04-11 10:07:39 -06:00
										 |  |  | 				return AST_MODULE_LOAD_DECLINE; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-31 19:43:02 +00:00
										 |  |  | 		sqlite_freemem(errormsg); | 
					
						
							|  |  |  | 		errormsg = NULL; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-13 15:26:40 +00:00
										 |  |  | 		error = ast_cdr_register(RES_CONFIG_SQLITE_NAME, RES_CONFIG_SQLITE_DESCRIPTION, cdr_handler); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (error) { | 
					
						
							|  |  |  | 			unload_module(); | 
					
						
							| 
									
										
										
										
											2017-04-11 10:07:39 -06:00
										 |  |  | 			return AST_MODULE_LOAD_DECLINE; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		cdr_registered = 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-05 10:31:25 +00:00
										 |  |  | 	error = ast_cli_register_multiple(cli_status, ARRAY_LEN(cli_status)); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (error) { | 
					
						
							|  |  |  | 		unload_module(); | 
					
						
							| 
									
										
										
										
											2017-04-11 10:07:39 -06:00
										 |  |  | 		return AST_MODULE_LOAD_DECLINE; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cli_status_registered = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-11 10:07:39 -06:00
										 |  |  | 	return AST_MODULE_LOAD_SUCCESS; | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-16 22:11:42 -05:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * This module should require "cdr" to enforce startup/shutdown ordering but it | 
					
						
							|  |  |  |  * loads at REALTIME_DRIVER priority which would cause "cdr" to load too early. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ast_cdr_register / ast_cdr_unregister is safe for use while "cdr" is not running. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2010-07-20 19:35:02 +00:00
										 |  |  | AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Realtime SQLite configuration", | 
					
						
							| 
									
										
										
										
											2018-03-08 13:53:09 -06:00
										 |  |  | 	.support_level = AST_MODULE_SUPPORT_DEPRECATED, | 
					
						
							| 
									
										
										
										
											2015-05-05 20:49:04 -04:00
										 |  |  | 	.load = load_module, | 
					
						
							|  |  |  | 	.unload = unload_module, | 
					
						
							|  |  |  | 	.load_pri = AST_MODPRI_REALTIME_DRIVER, | 
					
						
							| 
									
										
										
										
											2018-02-16 22:11:42 -05:00
										 |  |  | 	.requires = "extconfig", | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | ); |