From a5459ee55432775e47d4ee1e1d126aa88c373d6b Mon Sep 17 00:00:00 2001
From: Edward Rudd
Date: Wed, 19 Mar 2008 05:01:05 +0000
Subject: updated API to support mod_log_sql_dbd APR DBD driver.
---
 .project            |  60 +++++++++++-------------
 Makefile.in         |  28 +++++++++--
 TODO.in             |   3 +-
 configure.ac        |  12 +++++
 mod_log_sql.c       |  26 +++++------
 mod_log_sql.h       |   4 +-
 mod_log_sql_dbd.c   | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 mod_log_sql_dbi.c   |   2 +-
 mod_log_sql_mysql.c |   2 +-
 9 files changed, 211 insertions(+), 58 deletions(-)
 create mode 100644 mod_log_sql_dbd.c
diff --git a/.project b/.project
index db2ba74..9af17e9 100644
--- a/.project
+++ b/.project
@@ -3,19 +3,16 @@
 	mod_log_sql
 	
 	
+		includes
 	
 	
 		
-			org.eclipse.cdt.make.core.makeBuilder
+			org.eclipse.cdt.managedbuilder.core.genmakebuilder
 			clean,full,incremental,
 			
 				
-					org.eclipse.cdt.make.core.build.arguments
-					
-				
-				
-					org.eclipse.cdt.core.errorOutputParser
-					org.eclipse.cdt.core.MakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.VCErrorParser;
+					org.eclipse.cdt.make.core.fullBuildTarget
+					all
 				
 				
 					org.eclipse.cdt.make.core.enableAutoBuild
@@ -26,47 +23,47 @@
 					
 				
 				
-					org.eclipse.cdt.make.core.enableFullBuild
-					true
+					org.eclipse.cdt.make.core.buildLocation
+					${workspace_loc:/mod_log_sql/Linux GCC}
 				
 				
-					org.eclipse.cdt.make.core.build.target.inc
-					all
+					?name?
+					
 				
 				
-					org.eclipse.cdt.make.core.enabledIncrementalBuild
+					org.eclipse.cdt.make.core.enableFullBuild
 					true
 				
 				
-					org.eclipse.cdt.make.core.build.location
-					
+					org.eclipse.cdt.make.core.enableCleanBuild
+					true
 				
 				
-					org.eclipse.cdt.make.core.build.target.clean
+					org.eclipse.cdt.make.core.cleanBuildTarget
 					clean
 				
-				
-					org.eclipse.cdt.make.core.build.command
-					sshmake
-				
-				
-					org.eclipse.cdt.make.core.enableCleanBuild
-					true
-				
 				
 					org.eclipse.cdt.make.core.append_environment
 					true
 				
 				
-					org.eclipse.cdt.make.core.build.target.full
-					clean all
+					org.eclipse.cdt.make.core.contents
+					org.eclipse.cdt.make.core.activeConfigSettings
 				
 				
 					org.eclipse.cdt.make.core.useDefaultBuildCmd
 					false
 				
 				
-					org.eclipse.cdt.make.core.build.target.auto
+					org.eclipse.cdt.make.core.buildArguments
+					${project_name} make -k
+				
+				
+					org.eclipse.cdt.make.core.buildCommand
+					${HOME}/bin/sshmake
+				
+				
+					org.eclipse.cdt.make.core.autoBuildTarget
 					all
 				
 				
@@ -76,19 +73,14 @@
 			
 		
 		
-			org.eclipse.cdt.make.core.ScannerConfigBuilder
-			
-			
-		
-		
-			de.loskutov.FileSync.FSBuilder
+			org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
 			
 			
 		
 	
 	
 		org.eclipse.cdt.core.cnature
-		org.eclipse.cdt.make.core.makeNature
-		org.eclipse.cdt.make.core.ScannerConfigNature
+		org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+		org.eclipse.cdt.managedbuilder.core.managedBuildNature
 	
 
diff --git a/Makefile.in b/Makefile.in
index 2865d5f..2647d2e 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -77,6 +77,16 @@ ifeq (@WANT_DBI_MOD@,1)
 TARGETS += $(dbiTARGET)
 endif
 
+dbdSOURCES = @PACKAGE_NAME@_dbd.c
+dbdTARGET = @PACKAGE_NAME@_dbd@APXS_EXTENSION@
+dbdLDADD = 
+dbdCFLAGS = 
+dbdNAME = log_sql_dbd
+
+ifeq (@WANT_DBD_MOD@,1)
+TARGETS += $(dbdTARGET)
+endif
+
 #Don't modify anything below here
 
 PROVIDERS_SUBDIRS = @subdirs@
@@ -85,13 +95,13 @@ srcdir = @abs_srcdir@
 builddir = @abs_builddir@
 
 OBJ = $(coreSOURCES:.c=.o) $(logioSOURCES:.c=.o) $(sslSOURCES:.c=.o) $(mysqlSOURCES:.c=.o) \
-	$(dbiSOURCES:.c=.o) $(pgsqlSOURCES:.c=.o)
+	$(dbiSOURCES:.c=.o) $(pgsqlSOURCES:.c=.o) $(dbdSOURCES:.c=.o)
 
 LO = $(coreSOURCES:.c=.lo) $(logioSOURCES:.c=.lo) $(sslSOURCES:.c=.lo) $(mysqlSOURCES:.c=.lo) \
-	$(dbiSOURCES:.c=.lo) $(pgsqlSOURCES:.c=.lo)
+	$(dbiSOURCES:.c=.lo) $(pgsqlSOURCES:.c=.lo) $(dbdSOURCES:.c=.lo)
 
 SLO = $(coreSOURCES:.c=.slo) $(logioSOURCES:.c=.slo) $(sslSOURCES:.c=.slo) $(mysqlSOURCES:.c=.slo) \
-	$(dbiSOURCES:.c=.slo) $(pgsqlSOURCES:.c=.slo)
+	$(dbiSOURCES:.c=.slo) $(pgsqlSOURCES:.c=.slo) $(dbdSOURCES:.c=.slo)
 
 STD_DIST = install-sh \
 	config.sub \
@@ -104,7 +114,7 @@ STD_DIST = install-sh \
 	config.h.in
 
 DISTFILES = $(STD_DIST) $(EXTRA_DIST) $(coreSOURCES) $(HEADERS) \
-    $(sslSOURCES) $(logioSOURCES) $(mysqlSOURCES) $(pgsqlSOURCES) $(dbiSOURCES)
+    $(sslSOURCES) $(logioSOURCES) $(mysqlSOURCES) $(pgsqlSOURCES) $(dbiSOURCES) $(dbdSOURCES)
 
 all: $(TARGETS) all-subdirs
 
@@ -150,6 +160,11 @@ $(dbiTARGET): $(dbiSOURCES) $(HEADERS)
 	@@APXS_BIN@ -c -o $(dbiTARGET) $(dbiCFLAGS) $(CFLAGS) \
 		@DEFS@ @AP_DEFS@ $(dbiLDADD) $(dbiSOURCES)
 
+$(dbdTARGET): $(dbdSOURCES) $(HEADERS)
+	@@APXS_BIN@ -c -o $(dbdTARGET) $(dbdCFLAGS) $(CFLAGS) \
+		@DEFS@ @AP_DEFS@ $(dbdLDADD) $(dbdSOURCES)
+
+
 install: $(TARGETS) install-subdirs
 	@@APXS_BIN@ -n $(coreNAME) -i $(coreTARGET); \
 	if test @WANT_MYSQL_MOD@ -eq 1; then \
@@ -160,6 +175,9 @@ install: $(TARGETS) install-subdirs
     fi; \
 	if test @WANT_DBI_MOD@ -eq 1; then \
 	    @APXS_BIN@ -n $(dbiNAME) -i $(dbiTARGET); \
+    fi; \
+	if test @WANT_DBD_MOD@ -eq 1; then \
+	    @APXS_BIN@ -n $(dbdNAME) -i $(dbdTARGET); \
     fi; \
 	if test @WANT_SSL_MOD@ -eq 1; then \
 		@APXS_BIN@ -n $(sslNAME) -i $(sslTARGET); \
@@ -241,7 +259,7 @@ stamp-h: config.h.in config.status
 	./config.status
 
 $(srcdir)/configure: configure.ac aclocal.m4
-	cd $(srcdir) && autoconf-2.53
+	cd $(srcdir) && autoconf
 
 Makefile: Makefile.in config.status
 	./config.status
diff --git a/TODO.in b/TODO.in
index 0d871f6..bf6b624 100644
--- a/TODO.in
+++ b/TODO.in
@@ -1,5 +1,5 @@
 TODO:
-* verify a db driver has been loaded.
+* restructure to be more friendly toward DBD pooling
 * validate table names before trying to log them.
 * write alternate DB driver (PostgreSQL, libDBI, mod_*_pool)
 * look at forcing table name to ServerName instead of on of the names in 
@@ -7,7 +7,6 @@ TODO:
 * LogSQLRotateLogs directive with daily/monthly/weekly/etc.
 * socket-based middleman daemon with configurable conns, or connect/disconnect.
 * DBI connection pooling.
-* apr_dbd backend driver
 * ignore by cookie
 * investigate thread safety issues 
 	Use libmysqlclient_r for threaded MPM (or always?)
diff --git a/configure.ac b/configure.ac
index 8a348dc..55de120 100644
--- a/configure.ac
+++ b/configure.ac
@@ -26,8 +26,17 @@ if test $AP_VERSION = "2.0"; then
 else
     WANT_LOGIO_MOD=0
 fi
+
 AC_SUBST(WANT_LOGIO_MOD)
 
+if test $AP_VERSION = "2.0"; then
+	WANT_DBD_MOD=1
+else
+	WANT_DBD_MOD=0	
+fi
+
+AC_SUBST(WANT_DBD_MOD)
+
 CHECK_MYSQL(
         WANT_MYSQL_MOD=1,
         AC_MSG_WARN([*** Mysql client libraries not found!])
@@ -105,6 +114,9 @@ fi
 if test $WANT_DBI_MOD -eq 1; then
     AC_MSG_RESULT([      libDBI Driver])
 fi
+if test $WANT_DBD_MOD -eq 1; then
+    AC_MSG_RESULT([      APR DBD Driver])
+fi
 if test $OOO_MAINTAIN -eq 1; then
     AC_MSG_RESULT([Maintainer mode is on. -Werror is in effect])
 fi
diff --git a/mod_log_sql.c b/mod_log_sql.c
index b6a5c83..d319e97 100644
--- a/mod_log_sql.c
+++ b/mod_log_sql.c
@@ -1201,7 +1201,7 @@ static int log_sql_transaction(request_rec *orig)
 			fields = apr_pstrcat(r->pool, fields, (showcomma ? "," : ""),
 						 item->sql_field_name, NULL);
 			values = apr_pstrcat(r->pool, values, (showcomma ? "," : ""),
-					     global_config.driver->escape(formatted_item, r->pool,&global_config.db), NULL);
+					     global_config.driver->escape(r, formatted_item, r->pool,&global_config.db), NULL);
 			showcomma = 1;
 		}
 
@@ -1216,11 +1216,11 @@ static int log_sql_transaction(request_rec *orig)
 				itemsets = apr_pstrcat(r->pool, itemsets,
 									  (i > 0 ? "," : ""),
 									  "(",
-									  global_config.driver->escape(unique_id, r->pool, &global_config.db),
+									  global_config.driver->escape(r, unique_id, r->pool, &global_config.db),
 									  ",",
-									  global_config.driver->escape(*ptrptr, r->pool,&global_config.db),
+									  global_config.driver->escape(r, *ptrptr, r->pool,&global_config.db),
 									  ",",
-									  global_config.driver->escape(theitem, r->pool,&global_config.db),
+									  global_config.driver->escape(r, theitem, r->pool,&global_config.db),
 									  ")",
 									  NULL);
 				i++;
@@ -1244,11 +1244,11 @@ static int log_sql_transaction(request_rec *orig)
 				itemsets = apr_pstrcat(r->pool, itemsets,
 									  (i > 0 ? "," : ""),
 									  "(",
-									  global_config.driver->escape(unique_id, r->pool, &global_config.db),
+									  global_config.driver->escape(r,unique_id, r->pool, &global_config.db),
 									  ",",
-									  global_config.driver->escape(*ptrptr, r->pool,&global_config.db),
+									  global_config.driver->escape(r,*ptrptr, r->pool,&global_config.db),
 									  ",",
-									  global_config.driver->escape(theitem, r->pool,&global_config.db),
+									  global_config.driver->escape(r,theitem, r->pool,&global_config.db),
 									  ")",
 									  NULL);
 				i++;
@@ -1273,11 +1273,11 @@ static int log_sql_transaction(request_rec *orig)
 				itemsets = apr_pstrcat(r->pool, itemsets,
 									  (i > 0 ? "," : ""),
 									  "(",
-									  global_config.driver->escape(unique_id, r->pool, &global_config.db),
+									  global_config.driver->escape(r,unique_id, r->pool, &global_config.db),
 									  ",",
-									  global_config.driver->escape(*ptrptr, r->pool,&global_config.db),
+									  global_config.driver->escape(r,*ptrptr, r->pool,&global_config.db),
 									  ",",
-									  global_config.driver->escape(theitem, r->pool,&global_config.db),
+									  global_config.driver->escape(r,theitem, r->pool,&global_config.db),
 									  ")",
 									  NULL);
 				i++;
@@ -1302,11 +1302,11 @@ static int log_sql_transaction(request_rec *orig)
 				itemsets = apr_pstrcat(r->pool, itemsets,
 									  (i > 0 ? "," : ""),
 									  "(",
-									  global_config.driver->escape(unique_id, r->pool, &global_config.db),
+									  global_config.driver->escape(r,unique_id, r->pool, &global_config.db),
 									  ",",
-									  global_config.driver->escape(*ptrptr, r->pool,&global_config.db),
+									  global_config.driver->escape(r,*ptrptr, r->pool,&global_config.db),
 									  ",",
-									  global_config.driver->escape(theitem, r->pool,&global_config.db),
+									  global_config.driver->escape(r,theitem, r->pool,&global_config.db),
 									  ")",
 									  NULL);
 				i++;
diff --git a/mod_log_sql.h b/mod_log_sql.h
index 2d20374..c1d9bff 100644
--- a/mod_log_sql.h
+++ b/mod_log_sql.h
@@ -24,7 +24,7 @@
 #define LOGSQL_DECLARE_DATA             __declspec(dllimport)
 #endif
 
-#define LOG_SQL_PLUGIN_VERSION 20070704
+#define LOG_SQL_PLUGIN_VERSION 20080318
 
 /* Registration function for extract functions */
 
@@ -115,7 +115,7 @@ typedef struct {
 	/* disconnect from the underlying database layer */
 	void (*disconnect)(logsql_dbconnection *db);
 	/* escape the SQL statement according to database rules */
-	const char *(*escape)(const char *from_str, apr_pool_t *p,
+	const char *(*escape)(request_rec *r,const char *from_str, apr_pool_t *p,
 		logsql_dbconnection *db);
 	/* insert a SQL query statement */
 	logsql_query_ret (*insert)(request_rec *r,logsql_dbconnection *db,
diff --git a/mod_log_sql_dbd.c b/mod_log_sql_dbd.c
new file mode 100644
index 0000000..c78a128
--- /dev/null
+++ b/mod_log_sql_dbd.c
@@ -0,0 +1,132 @@
+/* $Id: mod_log_sql_dbi.c 120 2004-04-17 15:14:12Z urkle@drip.ws $ */
+
+#if defined(WITH_APACHE20)
+#	include "apache20.h"
+#else
+#	error Unsupported Apache version
+#endif
+
+
+#ifdef HAVE_CONFIG_H
+/* Undefine these to prevent conflicts between Apache ap_config_auto.h and 
+ * my config.h. Only really needed for Apache < 2.0.48, but it can't hurt.
+ */
+#undef PACKAGE_BUGREPORT
+#undef PACKAGE_NAME
+#undef PACKAGE_STRING
+#undef PACKAGE_TARNAME
+#undef PACKAGE_VERSION
+
+#include "config.h"
+#endif
+
+#include "mod_log_sql.h"
+
+#include "apr_dbd.h"
+#include "mod_dbd.h"
+
+typedef struct {
+	ap_dbd_t *dbd;
+} request_config_t;
+
+LOGSQL_MODULE_FORWARD(dbd);
+
+static ap_dbd_t *(*dbd_acquire_fn)(request_rec*) = NULL;
+
+static ap_dbd_t *log_sql_dbd_getconnection(request_rec *r)
+{
+	request_config_t *rconf = ap_get_module_config(r->request_config, &LOGSQL_MODULE(dbd));
+	if (!rconf) {
+		rconf = apr_pcalloc(r->pool, sizeof(request_config_t));
+		ap_set_module_config(r->request_config, &LOGSQL_MODULE(dbd), (void *)rconf);
+		rconf->dbd = dbd_acquire_fn(r);
+	}
+	return rconf->dbd;
+}
+
+/* Connect to the database */
+static logsql_opendb_ret log_sql_dbd_connect(server_rec *s, logsql_dbconnection *db)
+{
+	// We are using mod_dbd so we don't do anything here
+	if (!dbd_acquire_fn) {
+		// no mod_dbd return failure
+		log_error(APLOG_MARK,APLOG_ERR,0, s,"mod_log_sql_dbd: mod_dbd is not loaded or available");
+		return LOGSQL_OPENDB_FAIL;
+	} else {
+		return LOGSQL_OPENDB_SUCCESS;
+	}
+}
+
+/* Close the DB link */
+static void log_sql_dbd_close(logsql_dbconnection *db)
+{
+	// mod_dbd handles this, so do nothing
+}
+
+/* Routine to escape the 'dangerous' characters that would otherwise
+ * corrupt the INSERT string: ', \, and "
+ */
+static const char *log_sql_dbd_escape(request_rec *r, const char *from_str, apr_pool_t *p, 
+								logsql_dbconnection *db)
+{
+	// Acquire a DBD connection from mod_dbd
+	ap_dbd_t *dbd = log_sql_dbd_getconnection(r);
+	if (!dbd) return NULL;
+
+	if (!from_str)
+		return NULL;
+
+	return apr_pstrcat(p, "'",apr_dbd_escape(dbd->driver, p, from_str, dbd->handle),"'",NULL);
+}
+
+/* Run an insert query and return a categorized error or success */
+static logsql_query_ret log_sql_dbd_query(request_rec *r,logsql_dbconnection *db,
+								const char *query)
+{
+	int ret;
+	const char *err;
+	int affected;
+	// Acquire a DBD connection from mod_dbd
+	ap_dbd_t *dbd = log_sql_dbd_getconnection(r);
+	if (!dbd) return LOGSQL_QUERY_NOLINK;
+
+	// Run the query 
+	ret = apr_dbd_query(dbd->driver, dbd->handle, &affected, query);
+	if (ret == 0) {
+		return LOGSQL_QUERY_SUCCESS;
+	} else {
+		// attempt to detect error message
+		err = apr_dbd_error(dbd->driver, dbd->handle, ret);
+		log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "DB Returned error: (%d) %s", ret, err);
+		// Unable to check if "NO SUCH TABLE" due to apr_dbd not mapping error codes to a standard set.
+		return LOGSQL_QUERY_FAIL;
+	}
+}
+
+/* Create table table_name of type table_type. */
+static logsql_table_ret log_sql_dbd_create(request_rec *r, logsql_dbconnection *db,
+						logsql_tabletype table_type, const char *table_name)
+{
+	return LOGSQL_TABLE_FAIL;
+}
+
+static const char *supported_drivers[] = {"dbd",NULL};
+static logsql_dbdriver log_sql_dbd_driver = {
+    "dbd",
+	supported_drivers,
+	log_sql_dbd_connect,/* open DB connection */
+	log_sql_dbd_close,	/* close DB connection */
+	log_sql_dbd_escape,	/* escape query */
+	log_sql_dbd_query,	/* insert query */
+	log_sql_dbd_create	/* create table */
+};
+
+LOGSQL_REGISTER(dbd) {
+	dbd_acquire_fn = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_acquire);
+	if (dbd_acquire_fn == NULL) {
+		log_error(APLOG_MARK,APLOG_ERR,0,s,"You must load mod_dbd to enable AuthDBD functions");
+    }
+
+	log_sql_register_driver(p,&log_sql_dbd_driver);
+	LOGSQL_REGISTER_RETURN;
+}
diff --git a/mod_log_sql_dbi.c b/mod_log_sql_dbi.c
index 8afd844..40a972b 100644
--- a/mod_log_sql_dbi.c
+++ b/mod_log_sql_dbi.c
@@ -90,7 +90,7 @@ static void log_sql_dbi_close(logsql_dbconnection *db)
 /* Routine to escape the 'dangerous' characters that would otherwise
  * corrupt the INSERT string: ', \, and "
  */
-static const char *log_sql_dbi_escape(const char *from_str, apr_pool_t *p, 
+static const char *log_sql_dbi_escape(request_rec *r,const char *from_str, apr_pool_t *p, 
 								logsql_dbconnection *db)
 {
     dbi_conn_rec *dblink = db->handle;
diff --git a/mod_log_sql_mysql.c b/mod_log_sql_mysql.c
index 8202672..942c03a 100644
--- a/mod_log_sql_mysql.c
+++ b/mod_log_sql_mysql.c
@@ -74,7 +74,7 @@ static void log_sql_mysql_close(logsql_dbconnection *db)
 /* Routine to escape the 'dangerous' characters that would otherwise
  * corrupt the INSERT string: ', \, and "
  */
-static const char *log_sql_mysql_escape(const char *from_str, apr_pool_t *p,
+static const char *log_sql_mysql_escape(request_rec *r, const char *from_str, apr_pool_t *p,
 								logsql_dbconnection *db)
 {
         /* Return "NULL" for empty strings */
-- 
cgit