From ba30ceeb705e9b4d40ce0d98f6a4e047d47ce919 Mon Sep 17 00:00:00 2001 From: Edward Rudd Date: Sun, 21 Sep 2008 15:54:12 +0000 Subject: moved all modules source to src subdirectory.. Moved header files into include subdirectory cleaned up makefiles. --- Makefile.in | 170 +---- apache13.h | 101 --- apache20.h | 25 - configure.ac | 24 +- contrib/Makefile.in | 53 +- docs/Makefile.in | 24 - functions.h | 261 -------- functions13.h | 58 -- functions20.h | 116 ---- gen_todo.pl | 64 -- include/apache13.h | 101 +++ include/apache20.h | 25 + include/mod_log_sql.h | 166 +++++ include/winconfig.h | 78 +++ mod_log_sql.c | 1578 ----------------------------------------------- mod_log_sql.h | 166 ----- mod_log_sql_dbd.c | 132 ---- mod_log_sql_dbi.c | 263 -------- mod_log_sql_logio.c | 146 ----- mod_log_sql_mysql.c | 269 -------- mod_log_sql_pgsql.c | 247 -------- mod_log_sql_ssl.c | 106 ---- src/Makefile.in | 165 +++++ src/functions.h | 261 ++++++++ src/functions13.h | 58 ++ src/functions20.h | 116 ++++ src/mod_log_sql.c | 1578 +++++++++++++++++++++++++++++++++++++++++++++++ src/mod_log_sql_dbd.c | 132 ++++ src/mod_log_sql_dbi.c | 263 ++++++++ src/mod_log_sql_logio.c | 146 +++++ src/mod_log_sql_mysql.c | 269 ++++++++ src/mod_log_sql_pgsql.c | 247 ++++++++ src/mod_log_sql_ssl.c | 106 ++++ winconfig.h | 78 --- 34 files changed, 3740 insertions(+), 3852 deletions(-) delete mode 100644 apache13.h delete mode 100644 apache20.h delete mode 100644 functions.h delete mode 100644 functions13.h delete mode 100644 functions20.h delete mode 100755 gen_todo.pl create mode 100644 include/apache13.h create mode 100644 include/apache20.h create mode 100644 include/mod_log_sql.h create mode 100644 include/winconfig.h delete mode 100644 mod_log_sql.c delete mode 100644 mod_log_sql.h delete mode 100644 mod_log_sql_dbd.c delete mode 100644 mod_log_sql_dbi.c delete mode 100644 mod_log_sql_logio.c delete mode 100644 mod_log_sql_mysql.c delete mode 100644 mod_log_sql_pgsql.c delete mode 100644 mod_log_sql_ssl.c create mode 100644 src/Makefile.in create mode 100644 src/functions.h create mode 100644 src/functions13.h create mode 100644 src/functions20.h create mode 100644 src/mod_log_sql.c create mode 100644 src/mod_log_sql_dbd.c create mode 100644 src/mod_log_sql_dbi.c create mode 100644 src/mod_log_sql_logio.c create mode 100644 src/mod_log_sql_mysql.c create mode 100644 src/mod_log_sql_pgsql.c create mode 100644 src/mod_log_sql_ssl.c delete mode 100644 winconfig.h diff --git a/Makefile.in b/Makefile.in index 2647d2e..fb4ea42 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,108 +1,17 @@ # @configure_input@ # Modify these top variables. -SUBDIRS = docs contrib - -HEADERS = mod_log_sql.h \ - functions.h \ - functions13.h \ - functions20.h \ - apache13.h \ - apache20.h \ - winconfig.h - -CFLAGS = -Wc,-Wall -Wc,-fno-strict-aliasing - -ifeq (@OOO_MAINTAIN@,1) -CFLAGS += -Wc,-Werror -endif +SUBDIRS = docs contrib src EXTRA_DIST = AUTHORS INSTALL TODO LICENSE CHANGELOG \ build-apache13.bat build-apache2.bat \ -coreSOURCES = @PACKAGE_NAME@.c -coreTARGET = @PACKAGE_NAME@@APXS_EXTENSION@ -coreLDADD = @RT_LIBS@ -coreCFLAGS = -coreNAME = log_sql -TARGETS = $(coreTARGET) - -sslSOURCES = @PACKAGE_NAME@_ssl.c -sslTARGET = @PACKAGE_NAME@_ssl@APXS_EXTENSION@ -sslLDADD = -sslCFLAGS = @MOD_SSL_CFLAGS@ -sslNAME = log_sql_ssl - -ifeq (@WANT_SSL_MOD@,1) -TARGETS += $(sslTARGET) -endif - -logioSOURCES = @PACKAGE_NAME@_logio.c -logioTARGET = @PACKAGE_NAME@_logio@APXS_EXTENSION@ -logioLDADD = -logioCFLAGS = -logioNAME = log_sql_logio - -ifeq (@WANT_LOGIO_MOD@,1) -TARGETS += $(logioTARGET) -endif - -mysqlSOURCES = @PACKAGE_NAME@_mysql.c -mysqlTARGET = @PACKAGE_NAME@_mysql@APXS_EXTENSION@ -mysqlLDADD = @MYSQL_LDFLAGS@ @MYSQL_LIBS@ -mysqlCFLAGS = @MYSQL_CFLAGS@ -mysqlNAME = log_sql_mysql - -ifeq (@WANT_MYSQL_MOD@,1) -TARGETS += $(mysqlTARGET) -endif - -pgsqlSOURCES = @PACKAGE_NAME@_pgsql.c -pgsqlTARGET = @PACKAGE_NAME@_pgsql@APXS_EXTENSION@ -pgsqlLDADD = @PGSQL_LDFLAGS@ @PGSQL_LIBS@ -pgsqlCFLAGS = @PGSQL_CFLAGS@ -pgsqlNAME = log_sql_pgsql - -ifeq (@WANT_PGSQL_MOD@,1) -TARGETS += $(pgsqlTARGET) -endif - -dbiSOURCES = @PACKAGE_NAME@_dbi.c -dbiTARGET = @PACKAGE_NAME@_dbi@APXS_EXTENSION@ -dbiLDADD = @DBI_LDFLAGS@ @DBI_LIBS@ -dbiCFLAGS = @DBI_CFLAGS@ -dbiNAME = log_sql_dbi - -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@ - +top_srcdir = @top_srcdir@ 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) $(dbdSOURCES:.c=.o) - -LO = $(coreSOURCES:.c=.lo) $(logioSOURCES:.c=.lo) $(sslSOURCES:.c=.lo) $(mysqlSOURCES:.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) $(dbdSOURCES:.c=.slo) - STD_DIST = install-sh \ config.sub \ config.guess \ @@ -111,16 +20,15 @@ STD_DIST = install-sh \ configure.ac \ configure \ stamp-h.in \ - config.h.in + include/config.h.in -DISTFILES = $(STD_DIST) $(EXTRA_DIST) $(coreSOURCES) $(HEADERS) \ - $(sslSOURCES) $(logioSOURCES) $(mysqlSOURCES) $(pgsqlSOURCES) $(dbiSOURCES) $(dbdSOURCES) +DISTFILES = $(STD_DIST) $(EXTRA_DIST) -all: $(TARGETS) all-subdirs +all: all-subdirs all-subdirs install-subdirs activate-subdirs clean-subdirs distclean-subdirs: @otarget=`echo $@|sed s/-subdirs//`; \ - list=' $(PROVIDERS_SUBDIRS) $(SUBDIRS)'; \ + list=' $(SUBDIRS)'; \ for i in $$list; do \ if test -d "$$i"; then \ target="$$otarget"; \ @@ -134,57 +42,9 @@ all-subdirs install-subdirs activate-subdirs clean-subdirs distclean-subdirs: done; TODO: TODO.in - @./gen_todo.pl - -$(coreTARGET): $(coreSOURCES) $(HEADERS) - @@APXS_BIN@ -c -o $(coreTARGET) $(coreCFLAGS) $(CFLAGS) \ - @DEFS@ @AP_DEFS@ $(coreLDADD) $(coreSOURCES) - -$(logioTARGET): $(logioSOURCES) $(HEADERS) - @@APXS_BIN@ -c -o $(logioTARGET) $(logioCFLAGS) $(CFLAGS) \ - @DEFS@ @AP_DEFS@ $(logioLDADD) $(logioSOURCES) + @./m4/scripts/gen_todo.pl -$(sslTARGET): $(sslSOURCES) $(HEADERS) - @@APXS_BIN@ -c -o $(sslTARGET) $(sslCFLAGS) $(CFLAGS) \ - @DEFS@ @AP_DEFS@ $(sslLDADD) $(sslSOURCES) - -$(mysqlTARGET): $(mysqlSOURCES) $(HEADERS) - @@APXS_BIN@ -c -o $(mysqlTARGET) $(mysqlCFLAGS) $(CFLAGS) \ - @DEFS@ @AP_DEFS@ $(mysqlLDADD) $(mysqlSOURCES) - -$(pgsqlTARGET): $(pgsqlSOURCES) $(HEADERS) - @@APXS_BIN@ -c -o $(pgsqlTARGET) $(pgsqlCFLAGS) $(CFLAGS) \ - @DEFS@ @AP_DEFS@ $(pgsqlLDADD) $(pgsqlSOURCES) - -$(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 \ - @APXS_BIN@ -n $(mysqlNAME) -i $(mysqlTARGET); \ - fi; \ - if test @WANT_PGSQL_MOD@ -eq 1; then \ - @APXS_BIN@ -n $(pgsqlNAME) -i $(pgsqlTARGET); \ - 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); \ - fi; \ - if test @WANT_LOGIO_MOD@ -eq 1; then \ - @APXS_BIN@ -n $(logioNAME) -i $(logioTARGET); \ - fi; \ +install: install-subdirs echo "*************************************************************************"; \ echo "*** The mod_log_sql modules have been installed."; \ echo "*** Please edit your Apache configuration files and"; \ @@ -201,17 +61,11 @@ install: $(TARGETS) install-subdirs echo "*************************************************************************"; activate: activate-subdirs - @@APXS_BIN@ -n $(coreNAME) -i -a $(coreTARGET); \ - if test @WANT_SSL_MOD@ -eq 1; then \ - @APXS_BIN@ -n $(sslNAME) -i -a $(sslTARGET); \ - fi clean: clean-subdirs - $(RM) $(OBJ) $(SLO) $(LO) $(TARGETS) - $(RM) -r .libs distclean: clean distclean-subdirs - $(RM) config.status config.log config.h config.h.in \ + $(RM) config.status config.log include/config.h include/config.h.in \ configure stamp-h stamp-h.in Makefile aclocal.m4 $(RM) -r autom4te-2.53.cache @@ -219,7 +73,7 @@ DESTDIR = @PACKAGE_NAME@-@PACKAGE_VERSION@ DESTTGZ = $(DESTDIR).tar.gz dist: @rm -rf $(DESTDIR); \ - list=' $(PROVIDERS_SUBDIRS) $(SUBDIRS)'; \ + list=' $(SUBDIRS)'; \ for i in $$list; do \ if test -d "$$i"; then \ target=local-dist; \ @@ -240,8 +94,8 @@ dist: rm -rf $(DESTDIR); \ local-dist: $(DISTFILES) - @mkdir -p $(DESTDIR); \ - cp -dp --parents $(DISTFILES) $(DESTDIR); + mkdir -p $(DESTDIR) + cp -dp --parents $(DISTFILES) $(DESTDIR) .PHONY: include all-subdirs activate-subdirs install-subdirs \ clean-subdirs distclean-subdirs dist diff --git a/apache13.h b/apache13.h deleted file mode 100644 index 8174263..0000000 --- a/apache13.h +++ /dev/null @@ -1,101 +0,0 @@ -/* $Id$ */ -#ifndef APACHE13_H -#define APACHE13_H - -#include "httpd.h" -#include "http_config.h" -#include "http_log.h" -#include "http_core.h" - -/* Defines */ -#define AP_MODULE_DECLARE_DATA MODULE_VAR_EXPORT -#define APR_OFF_T_FMT "ld" -#define APR_PID_T_FMT "d" -#define APR_SUCCESS 0 -#define APR_OFFSETOF XtOffsetOf - -/** method of declaring a directive with raw argument parsing */ -# define AP_INIT_RAW_ARGS(directive, func, mconfig, where, help) \ - { directive, func, mconfig, where, RAW_ARGS, help } -/** method of declaring a directive which takes 1 argument */ -# define AP_INIT_TAKE1(directive, func, mconfig, where, help) \ - { directive, func, mconfig, where, TAKE1, help } -/** method of declaring a directive which takes 2 argument */ -# define AP_INIT_TAKE2(directive, func, mconfig, where, help) \ - { directive, func, mconfig, where, TAKE2, help } -/** method of declaring a directive which takes multiple arguments */ -# define AP_INIT_ITERATE(directive, func, mconfig, where, help) \ - { directive, func, mconfig, where, ITERATE, help } -/** method of declaring a directive which takes 1 or 3 arguments */ -# define AP_INIT_TAKE13(directive, func, mconfig, where, help) \ - { directive, func, mconfig, where, TAKE13, help } -/** method of declaring a directive which takes 3 arguments */ -# define AP_INIT_TAKE3(directive, func, mconfig, where, help) \ - { directive, func, mconfig, where, TAKE3, help } -/** method of declaring a directive which takes a flag (on/off) as an argument */ -# define AP_INIT_FLAG(directive, func, mconfig, where, help) \ - { directive, func, mconfig, where, FLAG, help } - -/* Types */ -#define apr_pool_t pool -#define apr_array_header_t array_header -#define apr_table_t table - -#define apr_status_t int -#define apr_uri_t uri_components - -/* Functions */ -#define ap_get_remote_host(a,b,c,d) ap_get_remote_host(a,b,c) -#define ap_set_deprecated NULL - -#define apr_uri_unparse ap_unparse_uri_components -#define apr_uri_parse ap_parse_uri_components -#define ap_add_version_component(p,s) ap_add_version_component(s) - -#define apr_pool_create(a,b) *(a) = ap_make_sub_pool(b) -#define apr_pool_destroy ap_destroy_pool -#define apr_pool_cleanup_register ap_register_cleanup -#define apr_palloc ap_palloc -#define apr_pcalloc ap_pcalloc -#define apr_pstrdup ap_pstrdup -#define apr_pstrcat ap_pstrcat -#define apr_psprintf ap_psprintf -#define apr_snprintf ap_snprintf -#define ap_strchr strchr -#define ap_strchr_c strchr -#define ap_strstr strstr -#define ap_strstr_c strstr - -#define apr_table_set ap_table_set -#define apr_table_get ap_table_get -#define apr_table_make ap_make_table - -#define apr_array_push ap_push_array -#define apr_array_make ap_make_array -#define apr_array_cat ap_array_cat -#define apr_is_empty_array(t) (((t) == NULL)||((t)->nelts == 0)) - -#define apr_file_t FILE -#define apr_file_printf fprintf - -#define apr_tolower ap_tolower - -void log_error(char *file, int line, int level, apr_status_t status, - const server_rec *s, const char *fmt, ...) __attribute__ ((format (printf, 6,7))); - -#ifndef WIN32 -inline -#endif -void log_error(char *file, int line, int level, - apr_status_t status, const server_rec *s, const char *fmt, ...) -{ - static char buff[MAX_STRING_LEN]; - va_list args; - va_start(args, fmt); - ap_vsnprintf(buff,MAX_STRING_LEN, fmt,args); - ap_log_error(file,line,level | APLOG_NOERRNO ,s,"%s",buff); - va_end(args); -} - - -#endif /* APACHE13_H */ diff --git a/apache20.h b/apache20.h deleted file mode 100644 index 9d87588..0000000 --- a/apache20.h +++ /dev/null @@ -1,25 +0,0 @@ -/* $Id$ */ -#ifndef APACHE20_H -#define APACHE20_H - -#include "apr_strings.h" -#include "apr_lib.h" -#include "apr_hash.h" -#include "apr_optional.h" -#define APR_WANT_STRFUNC -#include "apr_want.h" -#include "apr_tables.h" - -#include "ap_config.h" - -#include "httpd.h" -#include "http_config.h" -#include "http_core.h" -#include "http_log.h" -#include "http_protocol.h" - -#include "util_time.h" - -#define log_error ap_log_error - -#endif /* APACHE20_H */ diff --git a/configure.ac b/configure.ac index 55de120..07ac486 100644 --- a/configure.ac +++ b/configure.ac @@ -1,9 +1,9 @@ dnl Required initializer -AC_INIT(mod_log_sql, 1.102) +AC_INIT([mod_log_sql],[1.102]) OOO_CONFIG_NICE(config.nice) -AC_PREREQ(2.53) -AC_CONFIG_HEADERS(config.h) -AC_CONFIG_SRCDIR(mod_log_sql.c) +AC_PREREQ(2.59) +AC_CONFIG_HEADERS(include/config.h) +AC_CONFIG_SRCDIR(src/mod_log_sql.c) OOO_MAINTAIN_MODE @@ -18,7 +18,7 @@ CHECK_APACHE($APACHE13_VERSION,$APACHE20_VERSION, :, AC_MSG_ERROR([*** The correct version Apache was not found!]) AC_MSG_ERROR([*** You need either Apache 1.3 version $APACHE13_VERSION or greater]) - AC_MSG_ERROR([*** or Apache 2.0/2.1 version $APACHE20_VERSION or greater!]) + AC_MSG_ERROR([*** or Apache 2.0/2.2 version $APACHE20_VERSION or greater!]) ) if test $AP_VERSION = "2.0"; then @@ -29,11 +29,9 @@ fi AC_SUBST(WANT_LOGIO_MOD) -if test $AP_VERSION = "2.0"; then - WANT_DBD_MOD=1 -else - WANT_DBD_MOD=0 -fi +CHECK_APU_HEADERS([apr_dbd.h], + WANT_DBD_MOD=1, + WANT_DBD_MOD=0) AC_SUBST(WANT_DBD_MOD) @@ -84,9 +82,11 @@ AC_CONFIG_FILES([stamp-h], [echo timestamp > stamp-h]) dnl Write config.status and the Makefile -AC_OUTPUT(Makefile +AC_CONFIG_FILES([Makefile +src/Makefile docs/Makefile -contrib/Makefile) +contrib/Makefile]) +AC_OUTPUT AC_MSG_RESULT([------------------------------------]) diff --git a/contrib/Makefile.in b/contrib/Makefile.in index b384fd0..c2bd203 100644 --- a/contrib/Makefile.in +++ b/contrib/Makefile.in @@ -17,60 +17,17 @@ STD_DIST = Makefile.in DISTFILES = $(STD_DIST) $(EXTRA_DIST) -all: all-subdirs +all: -all-subdirs install-subdirs update-subdirs clean-subdirs distclean-subdirs: - @otarget=`echo $@|sed s/-subdirs//`; \ - list=' $(SUBDIRS)'; \ - for i in $$list; do \ - if test -d "$$i"; then \ - target="$$otarget"; \ - echo "Making $$target in $$i"; \ - if test "$$i" = "."; then \ - made_local=yes; \ - target="local-$$target"; \ - fi; \ - (cd $$i && $(MAKE) $$target) || exit 1; \ - fi; \ - done; \ +install: -include: - rm -rf include - ln -s @APACHE_INCDIR@ include +update: -install: install-subdirs +clean: -update: update-subdirs - -clean: clean-subdirs - -distclean: clean distclean-subdirs +distclean: clean $(RM) Makefile -DESTDIR = @PACKAGE_NAME@-@PACKAGE_VERSION@ -DESTTGZ = $(DESTDIR).tar.gz -dist: - @rm -rf $(DESTDIR); \ - list=' $(SUBDIRS)'; \ - for i in $$list; do \ - if test -d "$$i"; then \ - target=local-dist; \ - echo "Making $$target in $$i"; \ - if test "$$i" = "."; then \ - made_local=yes; \ - target="local-dist"; \ - fi; \ - NEWDESTDIR=$(builddir)/$(DESTDIR)/$$i; \ - echo $(NEWDESTDIR); \ - (cd $$i && $(MAKE) DESTDIR=$(builddir)/$(DESTDIR)/$$i $$target) || exit 1; \ - fi; \ - done; - if test "$$made_local" != "yes"; then \ - $(MAKE) "local-dist" || exit 1; \ - fi - tar -zcf $(DESTTGZ) $(DESTDIR) - rm -rf $(DESTDIR) - local-dist: $(DISTFILES) mkdir -p $(DESTDIR) cp -dp --parents $(DISTFILES) $(DESTDIR) diff --git a/docs/Makefile.in b/docs/Makefile.in index fa1bd2e..d88e72b 100644 --- a/docs/Makefile.in +++ b/docs/Makefile.in @@ -52,30 +52,6 @@ clean: clean-subdirs distclean: clean distclean-subdirs $(RM) Makefile -DESTDIR = @PACKAGE_NAME@-@PACKAGE_VERSION@ -DESTTGZ = $(DESTDIR).tar.gz -dist: - @rm -rf $(DESTDIR); \ - list=' $(SUBDIRS)'; \ - for i in $$list; do \ - if test -d "$$i"; then \ - target=local-dist; \ - echo "Making $$target in $$i"; \ - if test "$$i" = "."; then \ - made_local=yes; \ - target="local-dist"; \ - fi; \ - NEWDESTDIR=$(builddir)/$(DESTDIR)/$$i; \ - echo $(NEWDESTDIR); \ - (cd $$i && $(MAKE) DESTDIR=$(builddir)/$(DESTDIR)/$$i $$target) || exit 1; \ - fi; \ - done; - if test "$$made_local" != "yes"; then \ - $(MAKE) "local-dist" || exit 1; \ - fi - tar -zcf $(DESTTGZ) $(DESTDIR) - rm -rf $(DESTDIR) - local-dist: $(DISTFILES) mkdir -p $(DESTDIR) cp -dp --parents $(DISTFILES) $(DESTDIR) diff --git a/functions.h b/functions.h deleted file mode 100644 index 07711d2..0000000 --- a/functions.h +++ /dev/null @@ -1,261 +0,0 @@ -/* $Id$ */ - -/* Begin the individual functions that, given a request r, - * extract the needed information from it and return the - * value to the calling entity. - */ - -static const char *extract_remote_host(request_rec *r, char *a) -{ - return (char *) ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME, NULL); -} - -static const char *extract_remote_address(request_rec *r, char *a) __attribute__((unused)); - -static const char *extract_remote_address(request_rec *r, char *a) -{ - return r->connection->remote_ip; -} - -static const char *extract_local_address(request_rec *r, char *a) __attribute__((unused)); - -static const char *extract_local_address(request_rec *r, char *a) -{ - return r->connection->local_ip; -} - -static const char *extract_remote_logname(request_rec *r, char *a) -{ - return (char *) ap_get_remote_logname(r); -} - -static const char *extract_remote_user(request_rec *r, char *a) -{ - #ifdef WITH_APACHE13 - char *rvalue = r->connection->user; - #else - char *rvalue = r->user; - #endif - if (rvalue == NULL) { - rvalue = "-"; - } else if (strlen(rvalue) == 0) { - rvalue = "\"\""; - } - return rvalue; -} - -static const char *extract_request_line(request_rec *r, char *a) -{ - /* Upddated to mod_log_config logic */ - /* NOTE: If the original request contained a password, we - * re-write the request line here to contain XXXXXX instead: - * (note the truncation before the protocol string for HTTP/0.9 requests) - * (note also that r->the_request contains the unmodified request) - */ - return (r->parsed_uri.password) - ? apr_pstrcat(r->pool, r->method, " ", - apr_uri_unparse(r->pool, - &r->parsed_uri, 0), - r->assbackwards ? NULL : " ", - r->protocol, NULL) - : r->the_request; -} - -static const char *extract_request_file(request_rec *r, char *a) -{ - return r->filename; -} - -static const char *extract_request_uri(request_rec *r, char *a) -{ - return r->uri; -} - -static const char *extract_request_method(request_rec *r, char *a) -{ - return r->method; -} - -static const char *extract_request_protocol(request_rec *r, char *a) -{ - return r->protocol; -} - -static const char *extract_request_query(request_rec *r, char *a) -{ - return (r->args) ? apr_pstrcat(r->pool, "?", - r->args, NULL) - : ""; -} - -static const char *extract_status(request_rec *r, char *a) -{ - if (r->status <= 0) { - return "-"; - } else { - return apr_psprintf(r->pool, "%d", r->status); - } -} - -static const char *extract_virtual_host(request_rec *r, char *a) -{ - return r->server->server_hostname; -} - -static const char *extract_server_name(request_rec *r, char *a) -{ - return ap_get_server_name(r); -} - -static const char *extract_machine_id(request_rec *r, char *a) -{ - if (!global_config.machid) - return "-"; - else - return global_config.machid; -} - -static const char *extract_server_port(request_rec *r, char *a) -{ - return apr_psprintf(r->pool, "%u", - r->server->port ? r->server->port : ap_default_port(r)); -} - -/* This respects the setting of UseCanonicalName so that - * the dynamic mass virtual hosting trick works better. - */ -static const char *log_server_name(request_rec *r, char *a) __attribute__((unused)); -static const char *log_server_name(request_rec *r, char *a) -{ - return ap_get_server_name(r); -} - -static const char *extract_child_pid(request_rec *r, char *a) -{ - if (*a == '\0' || !strcmp(a, "pid")) { - return apr_psprintf(r->pool, "%" APR_PID_T_FMT, getpid()); - } - else if (!strcmp(a, "tid")) { -#if APR_HAS_THREADS - apr_os_thread_t tid = apr_os_thread_current(); -#else - int tid = 0; /* APR will format "0" anyway but an arg is needed */ -#endif - return apr_psprintf(r->pool, "%pT", &tid); - } - /* bogus format */ - return a; -} - -static const char *extract_referer(request_rec *r, char *a) -{ - const char *tempref; - - tempref = apr_table_get(r->headers_in, "Referer"); - if (!tempref) - { - return "-"; - } else { - return tempref; - } -} - -static const char *extract_agent(request_rec *r, char *a) -{ - const char *tempag; - - tempag = apr_table_get(r->headers_in, "User-Agent"); - if (!tempag) - { - return "-"; - } else { - return tempag; - } -} - -static const char *extract_specific_cookie(request_rec *r, char *a) -{ - const char *cookiestr; - char *cookieend; - char *isvalid; - char *cookiebuf; - - if (a != NULL) { - log_error(APLOG_MARK,APLOG_DEBUG, 0, r->server, - "watching for cookie '%s'", a); - - /* Fetch out the cookie header */ - cookiestr = (char *)apr_table_get(r->headers_in, "cookie2"); - if (cookiestr != NULL) { - log_error(APLOG_MARK,APLOG_DEBUG, 0, r->server, - "Cookie2: [%s]", cookiestr); - /* Does the cookie string contain one with our name? */ - isvalid = ap_strstr_c(cookiestr, a); - if (isvalid != NULL) { - /* Move past the cookie name and equal sign */ - isvalid += strlen(a) + 1; - /* Duplicate it into the pool */ - cookiebuf = apr_pstrdup(r->pool, isvalid); - /* Segregate just this cookie out of the string - * with a terminating nul at the first semicolon */ - cookieend = ap_strchr(cookiebuf, ';'); - if (cookieend != NULL) - *cookieend = '\0'; - return cookiebuf; - } - } - - cookiestr = (char *)apr_table_get(r->headers_in, "cookie"); - if (cookiestr != NULL) { - log_error(APLOG_MARK,APLOG_DEBUG, 0, r->server, - "Cookie: [%s]", cookiestr); - isvalid = ap_strstr_c(cookiestr, a); - if (isvalid != NULL) { - isvalid += strlen(a) + 1; - cookiebuf = apr_pstrdup(r->pool, isvalid); - cookieend = ap_strchr(cookiebuf, ';'); - if (cookieend != NULL) - *cookieend = '\0'; - return cookiebuf; - } - } - - cookiestr = apr_table_get(r->headers_out, "set-cookie"); - if (cookiestr != NULL) { - log_error(APLOG_MARK,APLOG_DEBUG, 0, r->server, - "Set-Cookie: [%s]", cookiestr); - isvalid = ap_strstr_c(cookiestr, a); - if (isvalid != NULL) { - isvalid += strlen(a) + 1; - cookiebuf = apr_pstrdup(r->pool, isvalid); - cookieend = ap_strchr(cookiebuf, ';'); - if (cookieend != NULL) - *cookieend = '\0'; - return cookiebuf; - } - } - } - - return "-"; -} - -/*static const char *extract_cookie(request_rec *r, char *a) -{ - logsql_state *cls = ap_get_module_config(r->server->module_config, - &log_sql_module); - - return extract_specific_cookie(r, (char *)cls->cookie_name); -}*/ - -static const char *extract_unique_id(request_rec *r, char *a) -{ - const char *tempid; - - tempid = apr_table_get(r->subprocess_env, "UNIQUE_ID"); - if (!tempid) - return "-"; - else - return tempid; -} - -/* End declarations of various extract_ functions */ diff --git a/functions13.h b/functions13.h deleted file mode 100644 index 54e3138..0000000 --- a/functions13.h +++ /dev/null @@ -1,58 +0,0 @@ -/* $Id$ */ - -static const char *extract_bytes_sent(request_rec *r, char *a) -{ - if (!r->sent_bodyct) { - return "-"; - } - else { - long int bs; - ap_bgetopt(r->connection->client, BO_BYTECT, &bs); - return ap_psprintf(r->pool, "%ld", bs); - } -} - -static const char *extract_request_time(request_rec *r, char *a) -{ - int timz; - struct tm *t; - char tstr[MAX_STRING_LEN]; - - t = ap_get_gmtoff(&timz); - - if (a && *a) { /* Custom format */ - strftime(tstr, MAX_STRING_LEN, a, t); - } else { /* CLF format */ - char sign = (timz < 0 ? '-' : '+'); - - if (timz < 0) { - timz = -timz; - } - strftime(tstr, MAX_STRING_LEN, "[%d/%b/%Y:%H:%M:%S ", t); - ap_snprintf(tstr + strlen(tstr), sizeof(tstr) - strlen(tstr), "%c%.2d%.2d]", sign, timz / 60, timz % 60); - } - - return ap_pstrdup(r->pool, tstr); -} - -static const char *extract_request_duration(request_rec *r, char *a) -{ - return ap_psprintf(r->pool, "%ld", time(NULL) - r->request_time); -} - -static const char *extract_request_timestamp(request_rec *r, char *a) -{ - return ap_psprintf(r->pool, "%ld", (long) time(NULL)); -} -static const char *extract_connection_status(request_rec *r, char *a) __attribute__((unused)); -static const char *extract_connection_status(request_rec *r, char *a) -{ - if (r->connection->aborted) - return "X"; - - if ((r->connection->keepalive) && - ((r->server->keep_alive_max - r->connection->keepalives) > 0)) { - return "+"; - } - return "-"; -} diff --git a/functions20.h b/functions20.h deleted file mode 100644 index 5220b7c..0000000 --- a/functions20.h +++ /dev/null @@ -1,116 +0,0 @@ -/* $Id$ */ - -static const char *extract_bytes_sent(request_rec *r, char *a) -{ - if (!r->sent_bodyct || !r->bytes_sent) { - return "-"; - } else { - return apr_psprintf(r->pool, "%" APR_OFF_T_FMT, r->bytes_sent); - } -} - -static const char *extract_request_time_custom(request_rec *r, char *a, - apr_time_exp_t *xt) -{ - apr_size_t retcode; - char tstr[MAX_STRING_LEN]; - apr_strftime(tstr, &retcode, sizeof(tstr), a, xt); - return apr_pstrdup(r->pool, tstr); -} - -#define DEFAULT_REQUEST_TIME_SIZE 32 -typedef struct { - unsigned t; - char timestr[DEFAULT_REQUEST_TIME_SIZE]; - unsigned t_validate; -} cached_request_time; - -#define TIME_CACHE_SIZE 4 -#define TIME_CACHE_MASK 3 -static cached_request_time request_time_cache[TIME_CACHE_SIZE]; - -static const char *extract_request_time(request_rec *r, char *a) -{ - apr_time_exp_t xt; - - /* Please read comments in mod_log_config.h for more info about - * the I_INSIST....COMPLIANCE define - */ - if (a && *a) { /* Custom format */ -#ifdef I_INSIST_ON_EXTRA_CYCLES_FOR_CLF_COMPLIANCE - ap_explode_recent_localtime(&xt, apr_time_now()); -#else - ap_explode_recent_localtime(&xt, r->request_time); -#endif - return extract_request_time_custom(r, a, &xt); - } else { /* CLF format */ - /* This code uses the same technique as ap_explode_recent_localtime(): - * optimistic caching with logic to detect and correct race conditions. - * See the comments in server/util_time.c for more information. - */ - cached_request_time* cached_time = apr_palloc(r->pool, - sizeof(*cached_time)); -#ifdef I_INSIST_ON_EXTRA_CYCLES_FOR_CLF_COMPLIANCE - apr_time_t request_time = apr_time_now(); -#else - apr_time_t request_time = r->request_time; -#endif - unsigned t_seconds = (unsigned)apr_time_sec(request_time); - unsigned i = t_seconds & TIME_CACHE_MASK; - memcpy(cached_time, &(request_time_cache[i]), sizeof(*cached_time)); - if ((t_seconds != cached_time->t) || - (t_seconds != cached_time->t_validate)) { - - /* Invalid or old snapshot, so compute the proper time string - * and store it in the cache - */ - char sign; - int timz; - - ap_explode_recent_localtime(&xt, r->request_time); - timz = xt.tm_gmtoff; - if (timz < 0) { - timz = -timz; - sign = '-'; - } - else { - sign = '+'; - } - cached_time->t = t_seconds; - apr_snprintf(cached_time->timestr, DEFAULT_REQUEST_TIME_SIZE, - "[%02d/%s/%d:%02d:%02d:%02d %c%.2d%.2d]", - xt.tm_mday, apr_month_snames[xt.tm_mon], - xt.tm_year+1900, xt.tm_hour, xt.tm_min, xt.tm_sec, - sign, timz / (60*60), timz % (60*60)); - cached_time->t_validate = t_seconds; - memcpy(&(request_time_cache[i]), cached_time, - sizeof(*cached_time)); - } - return cached_time->timestr; - } -} - -static const char *extract_request_duration(request_rec *r, char *a) -{ - apr_time_t duration = apr_time_now() - r->request_time; - return apr_psprintf(r->pool, "%" APR_TIME_T_FMT, apr_time_sec(duration)); -} - -static const char *extract_request_timestamp(request_rec *r, char *a) -{ - return apr_psprintf(r->pool, "%"APR_TIME_T_FMT, apr_time_sec(apr_time_now())); -} - -static const char *extract_connection_status(request_rec *r, char *a) __attribute__((unused)); -static const char *extract_connection_status(request_rec *r, char *a) -{ - if (r->connection->aborted) - return "X"; - - if (r->connection->keepalive == AP_CONN_KEEPALIVE && - (!r->server->keep_alive_max || - (r->server->keep_alive_max - r->connection->keepalives) > 0)) { - return "+"; - } - return "-"; -} diff --git a/gen_todo.pl b/gen_todo.pl deleted file mode 100755 index 20b0894..0000000 --- a/gen_todo.pl +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/perl - -# Copyright 2003-2004 Edward Rudd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -use strict; -my $rootdir = "."; -opendir(MYDIR, $rootdir) or die "Unable to open directory"; -print "Building TODO file for source directory\n"; -my $todo_header = "* Things TODO *\n\n"; -if (open ( TODOFILE, "TODO.in")) { - $todo_header = do { local $/; }; - close (TODOFILE); -} -open (TODOFILE, "> TODO"); -print TODOFILE $todo_header; -print "Parsing..."; -while (my $entry = readdir(MYDIR)) { - next if (!($entry =~ /\.[ch]$/)); - print "$entry..."; - open(DAFILE, $rootdir.'/'.$entry) or die "Unable to open file\n"; - my $linenumber = 0; - my $status = 0; # 0=no comment 1=comment 2=in todo block - while (my $line = ) { - $linenumber++; - if ($status==0) { - if ( ($line =~ /\/\/\s+TODO: (.*)/) || ($line =~ /\/\*\s+TODO: (.*)\s*\*\//) ){ - print TODOFILE $entry.":".$linenumber.": ".$1."\n"; - } else { - if ($line =~ /\/\*\*/) { - $status = 1; - } - } - } else { - if ($line =~ /\*\//) { - $status = 0; - } else { - if ($status==1) { - if ($line =~ /TODO:/) { - $status=2; - } - } else { - if ($line =~ /\* \s+-?\s*(.*)/) { - print TODOFILE $entry.":".$linenumber.": ".$1."\n"; - } - } - } - } - } - close(DAFILE); -} -print "\n"; -closedir(MYDIR); diff --git a/include/apache13.h b/include/apache13.h new file mode 100644 index 0000000..5659420 --- /dev/null +++ b/include/apache13.h @@ -0,0 +1,101 @@ +/* $Id: apache13.h 175 2007-10-20 13:18:20Z urkle@drip.ws $ */ +#ifndef APACHE13_H +#define APACHE13_H + +#include "httpd.h" +#include "http_config.h" +#include "http_log.h" +#include "http_core.h" + +/* Defines */ +#define AP_MODULE_DECLARE_DATA MODULE_VAR_EXPORT +#define APR_OFF_T_FMT "ld" +#define APR_PID_T_FMT "d" +#define APR_SUCCESS 0 +#define APR_OFFSETOF XtOffsetOf + +/** method of declaring a directive with raw argument parsing */ +# define AP_INIT_RAW_ARGS(directive, func, mconfig, where, help) \ + { directive, func, mconfig, where, RAW_ARGS, help } +/** method of declaring a directive which takes 1 argument */ +# define AP_INIT_TAKE1(directive, func, mconfig, where, help) \ + { directive, func, mconfig, where, TAKE1, help } +/** method of declaring a directive which takes 2 argument */ +# define AP_INIT_TAKE2(directive, func, mconfig, where, help) \ + { directive, func, mconfig, where, TAKE2, help } +/** method of declaring a directive which takes multiple arguments */ +# define AP_INIT_ITERATE(directive, func, mconfig, where, help) \ + { directive, func, mconfig, where, ITERATE, help } +/** method of declaring a directive which takes 1 or 3 arguments */ +# define AP_INIT_TAKE13(directive, func, mconfig, where, help) \ + { directive, func, mconfig, where, TAKE13, help } +/** method of declaring a directive which takes 3 arguments */ +# define AP_INIT_TAKE3(directive, func, mconfig, where, help) \ + { directive, func, mconfig, where, TAKE3, help } +/** method of declaring a directive which takes a flag (on/off) as an argument */ +# define AP_INIT_FLAG(directive, func, mconfig, where, help) \ + { directive, func, mconfig, where, FLAG, help } + +/* Types */ +#define apr_pool_t pool +#define apr_array_header_t array_header +#define apr_table_t table + +#define apr_status_t int +#define apr_uri_t uri_components + +/* Functions */ +#define ap_get_remote_host(a,b,c,d) ap_get_remote_host(a,b,c) +#define ap_set_deprecated NULL + +#define apr_uri_unparse ap_unparse_uri_components +#define apr_uri_parse ap_parse_uri_components +#define ap_add_version_component(p,s) ap_add_version_component(s) + +#define apr_pool_create(a,b) *(a) = ap_make_sub_pool(b) +#define apr_pool_destroy ap_destroy_pool +#define apr_pool_cleanup_register ap_register_cleanup +#define apr_palloc ap_palloc +#define apr_pcalloc ap_pcalloc +#define apr_pstrdup ap_pstrdup +#define apr_pstrcat ap_pstrcat +#define apr_psprintf ap_psprintf +#define apr_snprintf ap_snprintf +#define ap_strchr strchr +#define ap_strchr_c strchr +#define ap_strstr strstr +#define ap_strstr_c strstr + +#define apr_table_set ap_table_set +#define apr_table_get ap_table_get +#define apr_table_make ap_make_table + +#define apr_array_push ap_push_array +#define apr_array_make ap_make_array +#define apr_array_cat ap_array_cat +#define apr_is_empty_array(t) (((t) == NULL)||((t)->nelts == 0)) + +#define apr_file_t FILE +#define apr_file_printf fprintf + +#define apr_tolower ap_tolower + +void log_error(char *file, int line, int level, apr_status_t status, + const server_rec *s, const char *fmt, ...) __attribute__ ((format (printf, 6,7))); + +#ifndef WIN32 +inline +#endif +void log_error(char *file, int line, int level, + apr_status_t status, const server_rec *s, const char *fmt, ...) +{ + static char buff[MAX_STRING_LEN]; + va_list args; + va_start(args, fmt); + ap_vsnprintf(buff,MAX_STRING_LEN, fmt,args); + ap_log_error(file,line,level | APLOG_NOERRNO ,s,"%s",buff); + va_end(args); +} + + +#endif /* APACHE13_H */ diff --git a/include/apache20.h b/include/apache20.h new file mode 100644 index 0000000..4c755ab --- /dev/null +++ b/include/apache20.h @@ -0,0 +1,25 @@ +/* $Id: apache20.h 125 2004-04-29 18:05:25Z urkle@drip.ws $ */ +#ifndef APACHE20_H +#define APACHE20_H + +#include "apr_strings.h" +#include "apr_lib.h" +#include "apr_hash.h" +#include "apr_optional.h" +#define APR_WANT_STRFUNC +#include "apr_want.h" +#include "apr_tables.h" + +#include "ap_config.h" + +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_log.h" +#include "http_protocol.h" + +#include "util_time.h" + +#define log_error ap_log_error + +#endif /* APACHE20_H */ diff --git a/include/mod_log_sql.h b/include/mod_log_sql.h new file mode 100644 index 0000000..c1d9bff --- /dev/null +++ b/include/mod_log_sql.h @@ -0,0 +1,166 @@ +/* $Id$ */ + +#ifndef MOD_LOG_SQL_H +#define MOD_LOG_SQL_H + +/* Create a set of LOGSQL_DECLARE(type), LOGSQL_DECLARE_NONSTD(type) and + * LOGSQL_DECLARE_DATA with appropriate export and import tags for the platform + */ +#if !defined(WIN32) +#define LOGSQL_DECLARE(type) type +#define LOGSQL_DECLARE_NONSTD(type) type +#define LOGSQL_DECLARE_DATA +#elif defined(LOGSQL_DECLARE_STATIC) +#define LOGSQL_DECLARE(type) type __stdcall +#define LOGSQL_DECLARE_NONSTD(type) type +#define LOGSQL_DECLARE_DATA +#elif defined(LOGSQL_DECLARE_EXPORT) +#define LOGSQL_DECLARE(type) __declspec(dllexport) type __stdcall +#define LOGSQL_DECLARE_NONSTD(type) __declspec(dllexport) type +#define LOGSQL_DECLARE_DATA __declspec(dllexport) +#else +#define LOGSQL_DECLARE(type) __declspec(dllimport) type __stdcall +#define LOGSQL_DECLARE_NONSTD(type) __declspec(dllimport) type +#define LOGSQL_DECLARE_DATA __declspec(dllimport) +#endif + +#define LOG_SQL_PLUGIN_VERSION 20080318 + +/* Registration function for extract functions */ + +typedef const char *logsql_item_func(request_rec *r, char *a); + + +typedef enum { + LOGSQL_FUNCTION_REQ_FINAL = 0, + LOGSQL_FUNCTION_REQ_ORIG +} logsql_function_req; + +LOGSQL_DECLARE(void) log_sql_register_function(apr_pool_t *p, + const char *alias, logsql_item_func *func, + logsql_function_req want_orig_default); + +LOGSQL_DECLARE(void) log_sql_register_alias(server_rec *s, apr_pool_t *p, + char key, const char *alias); + +typedef enum { + LOGSQL_DATATYPE_INT = 0, + LOGSQL_DATATYPE_SMALLINT, + LOGSQL_DATATYPE_VARCHAR, + LOGSQL_DATATYPE_CHAR, + LOGSQL_DATATYPE_BIGINT +} logsql_field_datatype; + +LOGSQL_DECLARE(void) log_sql_register_field(apr_pool_t *p, + const char *alias, + const char *funcalias, const char *param, + const char *sql_field_name, + logsql_field_datatype datatype, apr_size_t size); + +LOGSQL_DECLARE(void) log_sql_register_finish(server_rec *s); + +/* DB Connection structure holds connection handle */ +typedef struct { + int connected; /* Are we connected to the DB */ + void *handle; /* DB specific connection pointer */ + apr_pool_t *p; /* Pool to allocate handle off of */ + apr_table_t *parms; /* DB connection parameters */ +} logsql_dbconnection; + +/* open db handle return values*/ +typedef enum { + LOGSQL_OPENDB_FAIL = 0, + LOGSQL_OPENDB_SUCCESS, + LOGSQL_OPENDB_ALREADY, + LOGSQL_OPENDB_PRESERVE +} logsql_opendb_ret; + +typedef enum { + LOGSQL_QUERY_SUCCESS = 0, + LOGSQL_QUERY_FAIL, + LOGSQL_QUERY_NOLINK, + LOGSQL_QUERY_NOTABLE, + LOGSQL_QUERY_PRESERVED +} logsql_query_ret; + +typedef enum { + LOGSQL_TABLE_SUCCESS = 0, + LOGSQL_TABLE_FAIL +} logsql_table_ret; + +/* Table type to create/log to */ +typedef enum { + LOGSQL_TABLE_ACCESS = 0, + LOGSQL_TABLE_NOTES, + LOGSQL_TABLE_HEADERSOUT, + LOGSQL_TABLE_HEADERSIN, + LOGSQL_TABLE_COOKIES +} logsql_tabletype; + +/* All Tables */ +#define LOGSQL_TABLE_ALL LOGSQL_TABLE_ACCESS | LOGSQL_TABLE_NOTES | \ + LOGSQL_TABLE_HEADERSIN | LOGSQL_TABLE_HEADERSOUT | LOGSQL_TABLE_COOKIES + +/* MySQL module calls */ + +/* Registration function for database drivers */ + +typedef struct { + /* name of the provider */ + const char *providername; + /* NULL terminated list of drivers strings */ + const char **provided_drivers; + /* create a connection to the underlying database layer */ + logsql_opendb_ret (*connect)(server_rec *s, logsql_dbconnection *db); + /* disconnect from the underlying database layer */ + void (*disconnect)(logsql_dbconnection *db); + /* escape the SQL statement according to database rules */ + 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, + const char *query); + /* create a SQL table named table_name of table_type */ + logsql_table_ret (*create_table)(request_rec *r, logsql_dbconnection *db, + logsql_tabletype table_type, const char *table_name); +} logsql_dbdriver; + +LOGSQL_DECLARE(void) log_sql_register_driver(apr_pool_t *p, + logsql_dbdriver *driver); + +/* Module initialization Macros */ +#define LOGSQL_MODULE(driver) log_sql_##driver##_module +#if defined(WITH_APACHE20) +# define LOGSQL_MODULE_FORWARD(driver) module AP_MODULE_DECLARE_DATA LOGSQL_MODULE(driver) +# define LOGSQL_REGISTER(driver) \ + static int post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s); \ + static void register_hooks(apr_pool_t *p) { \ + ap_hook_post_config(post_config, NULL, NULL, APR_HOOK_REALLY_FIRST); \ + } \ + \ + LOGSQL_MODULE_FORWARD(driver) = { \ + STANDARD20_MODULE_STUFF, \ + NULL, NULL, NULL, NULL, NULL, register_hooks }; \ + static int post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) +#elif defined(WITH_APACHE13) +# define LOGSQL_MODULE_FORWARD(driver) module MODULE_VAR_EXPORT LOGSQL_MODULE(driver) +# define LOGSQL_REGISTER(driver) \ + static void module_init(server_rec *s, apr_pool_t *p); \ + LOGSQL_MODULE_FORWARD(driver) = { \ + STANDARD_MODULE_STUFF, module_init }; \ + static void module_init(server_rec *s, apr_pool_t *p) +#endif + +#if defined(WITH_APACHE20) +# define LOGSQL_SHUTDOWN \ + static +#endif + + +#if defined(WITH_APACHE20) +#define LOGSQL_REGISTER_RETURN log_sql_register_finish(s); return OK; +#elif defined(WITH_APACHE13) +#define LOGSQL_REGISTER_RETURN log_sql_register_finish(s); +#endif + +#endif /* MOD_LOG_SQL_H */ diff --git a/include/winconfig.h b/include/winconfig.h new file mode 100644 index 0000000..702c35f --- /dev/null +++ b/include/winconfig.h @@ -0,0 +1,78 @@ +/* config.h. Generated by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_INTTYPES_H */ + +/* Define to 1 if you have the `m' library (-lm). */ +/* #undef HAVE_LIBM */ + +/* Define to 1 if you have the `mysqlclient' library (-lmysqlclient). */ +#define HAVE_LIBMYSQLCLIENT 1 + +/* Define to 1 if you have the `z' library (-lz). */ +/* #undef HAVE_LIBZ */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MOD_SSL_H */ + +/* Define to 1 if you have the `mysql_real_escape_string' function. */ +#define HAVE_MYSQL_REAL_ESCAPE_STRING 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STDINT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STRINGS_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STRING_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_STAT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_TYPES_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_UNISTD_H */ + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "mod_log_sql" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "mod_log_sql 1.100" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "mod-log-sql" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.100" + +/* Define to 1 if you have the ANSI C header files. */ +/* #undef STDC_HEADERS */ + +/* Define if we want to compile in SSL support. */ +/* #undef WANT_SSL_LOGGING */ + +/* Define to 1 if we are compiling with Apache 1.3.x */ +/* #undef WITH_APACHE13 */ + +/* Define to 1 if we are compiling with Apache 2.0.x */ +/* #undef WITH_APACHE20 */ + +/* Define to 1 if we are compiling with mysql */ +#define WITH_MYSQL 1 + diff --git a/mod_log_sql.c b/mod_log_sql.c deleted file mode 100644 index d319e97..0000000 --- a/mod_log_sql.c +++ /dev/null @@ -1,1578 +0,0 @@ -/* $Id$ */ - -#if defined(WITH_APACHE20) -# include "apache20.h" -#elif defined(WITH_APACHE13) -# include "apache13.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 - -#if APR_HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_LIMITS_H -#include -#endif - -#include "mod_log_sql.h" - -/* Configuratino Defaults */ -#define DEFAULT_TRANSFER_LOG_FMT "AbHhmRSsTUuv" -#define DEFAULT_NOTES_TABLE_NAME "notes" -#define DEFAULT_HIN_TABLE_NAME "headers_in" -#define DEFAULT_HOUT_TABLE_NAME "headers_out" -#define DEFAULT_COOKIE_TABLE_NAME "cookies" -#define DEFAULT_PRESERVE_FILE "logs/mod_log_sql-preserve" - -/* -------------* - * DECLARATIONS * - * -------------*/ - -/* Declare ourselves so the configuration routines can find and know us. */ -module AP_MODULE_DECLARE_DATA log_sql_module; - -/* The contents of these are known 'Apache wide' and are not variable - * on a per-virtual-server basis. Every virtual server 'knows' the - * same versions of these variables. - */ - -typedef struct { - int massvirtual; - int createtables; - int forcepreserve; - int disablepreserve; - char *machid; - int announce; - logsql_dbconnection db; - logsql_dbdriver *driver; - /** Show config support */ - char *showconfig; - apr_file_t *showconfig_fp; -} global_config_t; - -static global_config_t global_config; - -/* structure to hold helper function info */ -typedef struct { - const char *alias; /* The function alias */ - logsql_item_func *func; /* The extraction function pointer */ - int want_orig_req; /* if it requires the original request prior to internal redirection */ -} logsql_function; - -/* list of logsql_functions's for log types */ -static apr_array_header_t *logsql_function_list; - -/* structure to hold sqlfield mappings */ -typedef struct { - const char *alias; /* long name for item */ - const char *funcalias; /* The function alias */ - logsql_function *func; /* its extraction function */ - char *param; /* Parameter for function */ - const char *sql_field_name; /* its column in SQL */ - char string_contents; /* Whether this is a string field or not */ - logsql_field_datatype datatype; /* the field data type */ - apr_size_t size; /* The size of the data type */ -} logsql_field; - -/* list of logsql_item's for log types */ -static apr_array_header_t *logsql_field_list; - -/* But the contents of this structure will vary by virtual server. - * This permits each virtual server to vary its configuration slightly - * for per-server customization. - * - * Each child process has its own segregated copy of this structure. - */ -typedef struct { - apr_array_header_t *transfer_ignore_list; - apr_array_header_t *transfer_accept_list; - apr_array_header_t *remhost_ignore_list; - apr_array_header_t *notes_list; - apr_array_header_t *hout_list; - apr_array_header_t *hin_list; - apr_array_header_t *cookie_list; - const char *notes_table_name; - const char *hout_table_name; - const char *hin_table_name; - const char *cookie_table_name; - const char *transfer_table_name; - apr_array_header_t *transfer_log_format; - apr_pool_t *parsed_pool; - logsql_field **parsed_log_format; - const char *preserve_file; - const char *cookie_name; -} logsql_state; - -/** Registration function for extract functions - * - * This functions registers an alias for a function - * - * @note This is exported from the module - */ -LOGSQL_DECLARE(void) log_sql_register_function(apr_pool_t *p, - const char *alias, logsql_item_func *func, - logsql_function_req want_orig_req) -{ - logsql_function *item; - if (!logsql_function_list) - logsql_function_list = apr_array_make(p,10, sizeof(logsql_function)); - - item = apr_array_push(logsql_function_list); - item->alias = alias; - item->func = func; - item->want_orig_req = want_orig_req; - if (global_config.showconfig_fp) { - apr_file_printf(global_config.showconfig_fp," Function : %s\n",alias); - } -} -/** Register a old style sql mapping to the new style - * - * @note This is exported from the module - */ -LOGSQL_DECLARE(void) log_sql_register_alias(server_rec *s, apr_pool_t *p, - char key, const char *alias) -{ - server_rec *ts; - for (ts = s; ts; ts = ts->next) { - logsql_state *cfg = ap_get_module_config(ts->module_config, - &log_sql_module); - int itr; - for (itr = 0; itr < cfg->transfer_log_format->nelts; itr++) { - const char *logformat = ((const char **)cfg->transfer_log_format->elts)[itr]; - //log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Testing Logformat %s against %c for %s",logformat,key,alias); - // Check if it is only one character AND it is our key - if (logformat[1]=='\0' && logformat[0]==key) { - ((const char **)cfg->transfer_log_format->elts)[itr] = alias; - } - } - } -} - - -/** Registration sqlfield aliases to functions - * - * And update parse cache for transfer_log_format - * - * @note This is exported from the module - */ -LOGSQL_DECLARE(void) log_sql_register_field(apr_pool_t *p, - const char *alias, - const char *funcalias, const char *param, - const char *sql_field_name, - logsql_field_datatype datatype, apr_size_t size) -{ - logsql_field *item; - - if (!logsql_field_list) - logsql_field_list = apr_array_make(p,10, sizeof(logsql_field)); - - item = apr_array_push(logsql_field_list); - item->func = NULL; - item->alias = apr_pstrdup(p, alias); - item->funcalias = apr_pstrdup(p, funcalias); - item->param = apr_pstrdup(p, param); - item->sql_field_name = apr_pstrdup(p,sql_field_name); - item->datatype = datatype; - item->string_contents = 0; - if (datatype == LOGSQL_DATATYPE_CHAR || datatype == LOGSQL_DATATYPE_VARCHAR) { - item->string_contents = 1; - } - item->size = size; -} - -/** - * Links sql field items with their functions - */ -LOGSQL_DECLARE(void) log_sql_register_finish(server_rec *s) -{ - server_rec *ts; - int itr, f; - logsql_field *item; - logsql_function *func; - for (itr = 0; itr < logsql_field_list->nelts; itr++) { - item = &((logsql_field *)logsql_field_list->elts)[itr]; - if (item->func) continue; - /* Find function alias in function list */ - for (f = 0; f < logsql_function_list->nelts; f++) { - func = &((logsql_function *)logsql_function_list->elts)[f]; - if (strcmp(func->alias,item->funcalias)==0) { - item->func = func; - if (global_config.showconfig_fp) { - apr_file_printf(global_config.showconfig_fp," Item : %s using function %s(%s)\n" - "\tStoring in field %s of type %s(%"APR_SIZE_T_FMT")\n", - item->alias, item->funcalias, item->param, - item->sql_field_name, item->string_contents ? "TEXT":"NUMERIC", item->size); - } - break; - } - } - if (!item->func) { - log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "Could not find function %s for item %s",item->funcalias, item->alias); - } - } - /* some voodoo here to post parse logitems in all servers * - * so a "cached" list is used in the main logging loop for speed */ - for (ts = s; ts; ts = ts->next) { - logsql_state *cfg = ap_get_module_config(ts->module_config, - &log_sql_module); - - if (!cfg->parsed_log_format) { - cfg->parsed_log_format = apr_pcalloc(cfg->parsed_pool, - cfg->transfer_log_format->nelts * sizeof(logsql_field *)); - } - - for (itr = 0; itr < cfg->transfer_log_format->nelts; itr++) { - const char *logformat = ((char **)cfg->transfer_log_format->elts)[itr]; - for (f = 0; f < logsql_field_list->nelts; f++) { - item = &((logsql_field *)logsql_field_list->elts)[f]; - if (item->func && strcmp(logformat,item->alias)==0) { - cfg->parsed_log_format[itr] = item; - break; - } - } - } - } -} - -/* Registration function for database drivers */ -LOGSQL_DECLARE(void) log_sql_register_driver(apr_pool_t *p, - logsql_dbdriver *driver) -{ - global_config.driver = driver; -} - -/* Include all the core extract functions */ -#include "functions.h" -#if defined(WITH_APACHE13) -# include "functions13.h" -#elif defined(WITH_APACHE20) -# include "functions20.h" -#endif - -static logsql_opendb_ret log_sql_opendb_link(server_rec* s) -{ - logsql_opendb_ret result; - if (global_config.driver == NULL) { - return LOGSQL_OPENDB_FAIL; - } - if (global_config.forcepreserve) { - /*global_config.db.connected = 1;*/ - return LOGSQL_OPENDB_PRESERVE; - } - if (global_config.db.connected) { - return LOGSQL_OPENDB_ALREADY; - } - /* database - host - user - passwd - */ - if (global_config.db.parms) { - result = global_config.driver->connect(s, &global_config.db); - if (result==LOGSQL_OPENDB_FAIL) { - global_config.db.connected = 0; - } else { - global_config.db.connected = 1; - } - return result; - } else { - log_error(APLOG_MARK, APLOG_ERR, 0, s, - "mod_log_sql: insufficient configuration info to establish database link"); - return LOGSQL_OPENDB_FAIL; - } -} - -static void preserve_entry(request_rec *r, const char *query) -{ - logsql_state *cls = ap_get_module_config(r->server->module_config, - &log_sql_module); - apr_status_t result; - apr_file_t *fp; - - /* If preserve file is disabled bail out */ - if (global_config.disablepreserve) - return; - #if defined(WITH_APACHE20) - result = apr_file_open(&fp, cls->preserve_file,APR_APPEND | APR_WRITE | APR_CREATE, APR_OS_DEFAULT, r->pool); - #elif defined(WITH_APACHE13) - fp = ap_pfopen(r->pool, cls->preserve_file, "a"); - result = (fp)?0:errno; - #endif - if (result != APR_SUCCESS) { - log_error(APLOG_MARK, APLOG_ERR, result, r->server, - "attempted append of local preserve file '%s' but failed.",cls->preserve_file); - } else { - apr_file_printf(fp,"%s;\n", query); - #if defined(WITH_APACHE20) - apr_file_close(fp); - #elif defined(WITH_APACHE13) - ap_pfclose(r->pool, fp); - #endif - log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, - "mod_log_sql: entry preserved in %s", cls->preserve_file); - } -} - - -/* ------------------------------------------------* - * Command handlers that are called according * - * to the directives found at Apache runtime. * - * ------------------------------------------------*/ - - -static const char *set_global_flag_slot(cmd_parms *cmd, - void *struct_ptr, - int flag) -{ - void *ptr = &global_config; - int offset = (int)(long)cmd->info; - - *(int *)((char *)ptr + offset) = flag ? 1 : 0; - - return NULL; -} - -static const char *set_global_nmv_flag_slot(cmd_parms *cmd, - void *struct_ptr, - int flag) -{ - if (global_config.massvirtual) { - return apr_psprintf(cmd->pool, - "mod_log_sql: do not set %s when LogSQLMassVirtualHosting(%d) is On.%d:%d", - cmd->cmd->name, global_config.massvirtual, - (int)(long)&global_config, (int)(long)struct_ptr); - } else { - return set_global_flag_slot(cmd,struct_ptr,flag); - } -} - -static const char *set_global_string_slot(cmd_parms *cmd, - void *struct_ptr, - const char *arg) -{ - void *ptr = &global_config; - int offset = (int)(long)cmd->info; - - *(const char **)((char *)ptr + offset) = apr_pstrdup(cmd->pool,arg); - return NULL; -} - -static const char *set_server_string_slot(cmd_parms *cmd, - void *struct_ptr, - const char *arg) -{ - void *ptr = ap_get_module_config(cmd->server->module_config, - &log_sql_module); - int offset = (int)(long)cmd->info; - - *(const char **)((char *)ptr + offset) = arg; - - return NULL; -} - -static const char *set_server_file_slot(cmd_parms *cmd, - void *struct_ptr, - const char *arg) -{ - void *ptr = ap_get_module_config(cmd->server->module_config, - &log_sql_module); - int offset = (int)(long)cmd->info; - const char *path; - - path = ap_server_root_relative(cmd->pool, (char *)arg); - - if (!path) { - return apr_pstrcat(cmd->pool, "Invalid file path ", - arg, NULL); - } - - *(const char **)((char*)ptr + offset) = path; - - return NULL; -} - -static apr_array_header_t *create_logformat_default(apr_pool_t *p) -{ - apr_array_header_t *logformat; - char **addme; - - logformat = apr_array_make(p, 12, sizeof(char *)); - addme = apr_array_push(logformat); *addme = "useragent"; - addme = apr_array_push(logformat); *addme = "bytes_sent"; - addme = apr_array_push(logformat); *addme = "request_protocol"; - addme = apr_array_push(logformat); *addme = "remote_host"; - addme = apr_array_push(logformat); *addme = "request_method"; - addme = apr_array_push(logformat); *addme = "referer"; - addme = apr_array_push(logformat); *addme = "timestamp"; - addme = apr_array_push(logformat); *addme = "status"; - addme = apr_array_push(logformat); *addme = "request_duration"; - addme = apr_array_push(logformat); *addme = "request_uri"; - addme = apr_array_push(logformat); *addme = "remote_user"; - addme = apr_array_push(logformat); *addme = "virtual_host"; - return logformat; -} - -static const char *set_server_nmv_string_slot(cmd_parms *parms, - void *struct_ptr, - const char *arg) -{ - if (global_config.massvirtual) - return apr_psprintf(parms->pool, - "mod_log_sql: do not set %s when LogSQLMassVirtualHosting is On.", - parms->cmd->name); - else - return set_server_string_slot(parms,struct_ptr,arg); -} - -/* Set a DB connection parameter */ -static const char *set_dbparam(cmd_parms *cmd, - void *struct_ptr, - const char *key, - const char *val) -{ - if (!global_config.db.parms) { - global_config.db.parms = apr_table_make(cmd->pool,5); - } - apr_table_set(global_config.db.parms,key,val); - return NULL; -} - -static const char *set_dbparam_slot(cmd_parms *cmd, - void *struct_ptr, - const char *arg) -{ - const char *param = (char *)cmd->info; - set_dbparam(cmd,NULL,param,arg); - return NULL; -} - -/* Sets basic connection info */ -static const char *set_log_sql_info(cmd_parms *cmd, void *dummy, - const char *host, const char *user, const char *pwd) -{ - if (!user) { /* user is null, so only one arg passed */ - /* TODO: to more error checking/force all params to be set */ - apr_uri_t uri; - apr_uri_parse(cmd->pool, host, &uri); - if (uri.scheme) { - set_dbparam(cmd, NULL, "driver", uri.scheme); - } - if (uri.hostname) { - set_dbparam(cmd, NULL, "hostname", uri.hostname); - } - if (uri.user) { - set_dbparam(cmd, NULL, "username", uri.user); - } - if (uri.password) { - set_dbparam(cmd, NULL, "password", uri.password); - } - if (uri.port_str) { - set_dbparam(cmd, NULL, "port", uri.port_str); - } - if (uri.path) { - /* extract Database name */ - char *off = ap_strchr(++uri.path,'/'); - if (off) - *off='\0'; - set_dbparam(cmd, NULL, "database", uri.path); - - } - } else { - if (*host != '.') { - set_dbparam(cmd, NULL, "hostname", host); - } - if (*user != '.') { - set_dbparam(cmd, NULL, "username", user); - } - if (*pwd != '.') { - set_dbparam(cmd, NULL, "password", pwd); - } - } - return NULL; -} - -static const char *add_server_string_slot(cmd_parms *cmd, - void *struct_ptr, - const char *arg) -{ - char **addme; - void *ptr = ap_get_module_config(cmd->server->module_config, - &log_sql_module); - int offset = (int)(long)cmd->info; - apr_array_header_t *ary = *(apr_array_header_t **)((char *)ptr + offset); - addme = apr_array_push(ary); - *addme = apr_pstrdup(ary->pool, arg); - - return NULL; -} - -static const char *set_logformat_slot(cmd_parms *cmd, - void *struct_ptr, - const char *arg) -{ - const char *t; - char t2[2] = {'\0','\0'}; - for (t = arg; *t != '\0'; t++) { - t2[0] = *t; - add_server_string_slot(cmd, NULL, t2); - } - return NULL; -} - -static const char *set_register_field(cmd_parms *cmd, - void *struct_ptr, - const char *arg) -{ - char *alias, *funcalias, *param, *field, *datatype_s, *size_s; - logsql_field_datatype datatype; - apr_size_t size; - - alias = ap_getword_white(cmd->pool, &arg); - funcalias = ap_getword_white(cmd->pool, &arg); - param = ap_getword_conf(cmd->pool, &arg); - field = ap_getword_white(cmd->pool, &arg); - datatype_s = ap_getword_white(cmd->pool, &arg); - size_s = ap_getword_white(cmd->pool, &arg); - - if (strcasecmp("VARCHAR",datatype_s)==0) { - datatype = LOGSQL_DATATYPE_VARCHAR; - } else if (strcasecmp("INT",datatype_s)==0) { - datatype = LOGSQL_DATATYPE_INT; - } else if (strcasecmp("CHAR",datatype_s)==0) { - datatype = LOGSQL_DATATYPE_CHAR; - } else if (strcasecmp("SMALLINT",datatype_s)==0) { - datatype = LOGSQL_DATATYPE_SMALLINT; - } else if (strcasecmp("BIGINT",datatype_s)==0) { - datatype = LOGSQL_DATATYPE_BIGINT; - } else { - return apr_psprintf(cmd->pool, "Unknown data type %s",datatype_s); - } - - size = atoi(size_s); - - log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server, - "%s, %s, %s, %s, %s(%d), %s(%"APR_SIZE_T_FMT")", - alias, funcalias, param, field, datatype_s, datatype, size_s, size); - - log_sql_register_field(cmd->pool, alias, funcalias, param, - field, datatype, size); - - return NULL; -} - -/*------------------------------------------------------------* - * Apache-specific hooks into the module code * - * that are defined in the array 'mysql_lgog_module' (at EOF) * - *------------------------------------------------------------*/ -/* Closing mysql link: child_exit(1.3), pool registration(2.0) */ -#if defined(WITH_APACHE20) -static apr_status_t log_sql_close_link(void *data) -{ - if (global_config.driver) - global_config.driver->disconnect(&global_config.db); - return APR_SUCCESS; -} -#elif defined(WITH_APACHE13) -static void log_sql_child_exit(server_rec *s, apr_pool_t *p) -{ - if (global_config.driver) - global_config.driver->disconnect(&global_config.db); -} -#endif - -/* Child Init */ -#if defined(WITH_APACHE20) -static void log_sql_child_init(apr_pool_t *p, server_rec *s) -#elif defined(WITH_APACHE13) -static void log_sql_child_init(server_rec *s, apr_pool_t *p) -#endif -{ - logsql_opendb_ret retval; -# if defined(WITH_APACHE20) - /* Register cleanup hook to close DDB connection (apache 2 doesn't have child_exit) */ - apr_pool_cleanup_register(p, NULL, log_sql_close_link, log_sql_close_link); -# endif - /* Open a link to the database */ - retval = log_sql_opendb_link(s); - switch (retval) { - case LOGSQL_OPENDB_FAIL: - if (global_config.driver==NULL) { - log_error(APLOG_MARK, APLOG_ERR, 0, s, - "mod_log_sql: Driver module not loaded"); - } else { - log_error(APLOG_MARK, APLOG_ERR, 0, s, - "mod_log_sql: child spawned but unable to open database link"); - } - break; - case LOGSQL_OPENDB_SUCCESS: - case LOGSQL_OPENDB_ALREADY: - log_error(APLOG_MARK,APLOG_DEBUG,0, s, - "mod_log_sql: open_logdb_link successful"); - break; - case LOGSQL_OPENDB_PRESERVE: - log_error(APLOG_MARK,APLOG_DEBUG, 0, s, - "mod_log_sql: open_logdb_link said that preservation is forced"); - break; - } -} - -static apr_array_header_t *do_merge_array(apr_array_header_t *parent, apr_array_header_t *child, apr_pool_t *p); - -/* post_config / module_init */ -#if defined(WITH_APACHE20) -static int log_sql_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) -#elif defined(WITH_APACHE13) -static void log_sql_module_init(server_rec *s, apr_pool_t *p) -#endif -{ - server_rec *cur_s; - const char *default_p = ap_server_root_relative(p, DEFAULT_PRESERVE_FILE); - apr_array_header_t *parent = NULL; - - if (global_config.showconfig != NULL) { - const char *tempfile = ap_server_root_relative(p, global_config.showconfig); - apr_status_t result; - #if defined(WITH_APACHE20) - result = apr_file_open(&global_config.showconfig_fp, tempfile,APR_TRUNCATE | APR_WRITE | APR_CREATE, APR_OS_DEFAULT, p); - #elif defined(WITH_APACHE13) - global_config.showconfig_fp = ap_pfopen(p, tempfile, "w"); - result = (fp)?0:errno; - #endif - if (result != APR_SUCCESS) { - log_error(APLOG_MARK, APLOG_ERR, result, s, - "attempted open of showconfig file '%s' failed.",tempfile); - global_config.showconfig_fp = NULL; - } else { - #if defined(WITH_APACHE20) - char temp_time[APR_RFC822_DATE_LEN]; - apr_rfc822_date(temp_time,apr_time_now()); - #elif defined(WITH_APACHE13) - char *temp_time = ap_get_time()); - #endif - apr_file_printf(global_config.showconfig_fp,"Mod_log_sql Config dump created on %s\n", temp_time); - } - } - - for (cur_s = s; cur_s != NULL; cur_s= cur_s->next) { - logsql_state *cls = ap_get_module_config(cur_s->module_config, - &log_sql_module); - /* ap_server_root_relative any default preserve file locations */ - if (cls->preserve_file == DEFAULT_PRESERVE_FILE) - cls->preserve_file = default_p; - - /* Post-process logformats */ - if (!cur_s->is_virtual) { - parent = create_logformat_default(p); - cls->transfer_log_format = do_merge_array(parent, cls->transfer_log_format, p); - parent = cls->transfer_log_format; - } else { - cls->transfer_log_format = do_merge_array(parent, cls->transfer_log_format, p); - } - } - - /* TODO: Add local_address, remote_address, connection_status */ - /** Register functions */ - /** register_function(p, funcname, func_ptr, which request_rec); */ - log_sql_register_function(p, "useragent", extract_agent, LOGSQL_FUNCTION_REQ_ORIG); - log_sql_register_function(p, "request_args", extract_request_query, LOGSQL_FUNCTION_REQ_ORIG); - log_sql_register_function(p, "bytes_sent", extract_bytes_sent, LOGSQL_FUNCTION_REQ_FINAL); - log_sql_register_function(p, "cookie", extract_specific_cookie,LOGSQL_FUNCTION_REQ_FINAL); - log_sql_register_function(p, "request_file", extract_request_file, LOGSQL_FUNCTION_REQ_FINAL); - log_sql_register_function(p, "request_protocol",extract_request_protocol,LOGSQL_FUNCTION_REQ_FINAL); - log_sql_register_function(p, "remote_host", extract_remote_host, LOGSQL_FUNCTION_REQ_FINAL); - log_sql_register_function(p, "unique_id", extract_unique_id, LOGSQL_FUNCTION_REQ_FINAL); - log_sql_register_function(p, "remote_logname", extract_remote_logname, LOGSQL_FUNCTION_REQ_FINAL); - log_sql_register_function(p, "request_method", extract_request_method, LOGSQL_FUNCTION_REQ_FINAL); - log_sql_register_function(p, "machine_id", extract_machine_id, LOGSQL_FUNCTION_REQ_FINAL); - log_sql_register_function(p, "child_pid", extract_child_pid, LOGSQL_FUNCTION_REQ_FINAL); - log_sql_register_function(p, "server_port", extract_server_port, LOGSQL_FUNCTION_REQ_FINAL); - log_sql_register_function(p, "referrer", extract_referer, LOGSQL_FUNCTION_REQ_ORIG); - log_sql_register_function(p, "request_line", extract_request_line, LOGSQL_FUNCTION_REQ_ORIG); - log_sql_register_function(p, "timestamp", extract_request_timestamp,LOGSQL_FUNCTION_REQ_FINAL); - log_sql_register_function(p, "status", extract_status, LOGSQL_FUNCTION_REQ_ORIG); - log_sql_register_function(p, "request_duration",extract_request_duration,LOGSQL_FUNCTION_REQ_ORIG); - log_sql_register_function(p, "request_time", extract_request_time, LOGSQL_FUNCTION_REQ_FINAL); - log_sql_register_function(p, "remote_user", extract_remote_user, LOGSQL_FUNCTION_REQ_FINAL); - log_sql_register_function(p, "request_uri", extract_request_uri, LOGSQL_FUNCTION_REQ_ORIG); - log_sql_register_function(p, "virtual_host", extract_virtual_host, LOGSQL_FUNCTION_REQ_FINAL); - log_sql_register_function(p, "server_name", extract_server_name, LOGSQL_FUNCTION_REQ_FINAL); - - /** Old style aliases */ - /** register_alias(s, shortname, longname) */ - log_sql_register_alias(s,p,'A',"useragent"); - log_sql_register_alias(s,p,'a',"request_args"); - log_sql_register_alias(s,p,'b',"bytes_sent"); - log_sql_register_alias(s,p,'c',"cookie"); - log_sql_register_alias(s,p,'f',"request_file"); - log_sql_register_alias(s,p,'H',"request_protocol"); - log_sql_register_alias(s,p,'h',"remote_host"); - log_sql_register_alias(s,p,'I',"unique_id"); - log_sql_register_alias(s,p,'l',"remote_logname"); - log_sql_register_alias(s,p,'m',"request_method"); - log_sql_register_alias(s,p,'M',"machine_id"); - log_sql_register_alias(s,p,'P',"child_pid"); - log_sql_register_alias(s,p,'p',"server_port"); - log_sql_register_alias(s,p,'R',"referrer"); - log_sql_register_alias(s,p,'r',"request_line"); - log_sql_register_alias(s,p,'S',"timestamp"); - log_sql_register_alias(s,p,'s',"status"); - log_sql_register_alias(s,p,'T',"request_duration"); - log_sql_register_alias(s,p,'t',"request_time"); - log_sql_register_alias(s,p,'u',"remote_user"); - log_sql_register_alias(s,p,'U',"request_uri"); - log_sql_register_alias(s,p,'v',"virtual_host"); - log_sql_register_alias(s,p,'V',"server_name"); - - /* Register handlers */ - /** register_field(s,p, longname, funcalias, arg, - * sqlfieldname, DATATYPE, DATA LENGTH); */ - log_sql_register_field(p,"useragent", "useragent",NULL, - "agent", LOGSQL_DATATYPE_VARCHAR, 0); - log_sql_register_field(p,"request_args", "request_args",NULL, - "request_args",LOGSQL_DATATYPE_VARCHAR,0); - log_sql_register_field(p,"bytes_sent", "bytes_sent",NULL, - "bytes_sent",LOGSQL_DATATYPE_INT,0); - log_sql_register_field(p,"cookie", "cookie","Apache", - "cookie",LOGSQL_DATATYPE_VARCHAR,0); - log_sql_register_field(p,"request_file", "request_file",NULL, - "request_file",LOGSQL_DATATYPE_VARCHAR,0); - log_sql_register_field(p,"request_protocol", "request_protocol",NULL, - "request_protocol",LOGSQL_DATATYPE_VARCHAR,0); - log_sql_register_field(p,"remote_host", "remote_host",NULL, - "remote_host",LOGSQL_DATATYPE_VARCHAR,0); - log_sql_register_field(p,"unique_id", "unique_id",NULL, - "id",LOGSQL_DATATYPE_VARCHAR,0); - log_sql_register_field(p,"remote_logname", "remote_logname",NULL, - "remote_logname",LOGSQL_DATATYPE_VARCHAR,0); - log_sql_register_field(p,"request_method", "request_method",NULL, - "request_method",LOGSQL_DATATYPE_VARCHAR,0); - log_sql_register_field(p,"machine_id", "machine_id",NULL, - "machine_id",LOGSQL_DATATYPE_VARCHAR,0); - log_sql_register_field(p,"child_pid", "child_pid",NULL, - "child_pid",LOGSQL_DATATYPE_INT,0); - log_sql_register_field(p,"server_port", "server_port",NULL, - "server_port",LOGSQL_DATATYPE_INT,0); - log_sql_register_field(p,"referer", "referrer",NULL, - "referer",LOGSQL_DATATYPE_VARCHAR,0); - log_sql_register_field(p,"referrer", "referrer",NULL, - "referer",LOGSQL_DATATYPE_VARCHAR,0); - log_sql_register_field(p,"request_line", "request_line",NULL, - "request_line",LOGSQL_DATATYPE_VARCHAR,0); - log_sql_register_field(p,"timestamp", "timestamp",NULL, - "time_stamp",LOGSQL_DATATYPE_INT,0); - log_sql_register_field(p,"status", "status",NULL, - "status",LOGSQL_DATATYPE_INT,0); - log_sql_register_field(p,"request_duration", "request_duration",NULL, - "request_duration",LOGSQL_DATATYPE_INT,0); - log_sql_register_field(p,"request_time", "request_time",NULL, - "request_time",LOGSQL_DATATYPE_VARCHAR,0); - log_sql_register_field(p,"remote_user", "remote_user",NULL, - "remote_user",LOGSQL_DATATYPE_VARCHAR,0); - log_sql_register_field(p,"request_uri", "request_uri",NULL, - "request_uri",LOGSQL_DATATYPE_VARCHAR,0); - log_sql_register_field(p,"virtual_host", "virtual_host",NULL, - "virtual_host",LOGSQL_DATATYPE_VARCHAR,0); - log_sql_register_field(p,"server_name", "server_name",NULL, - "virtual_host",LOGSQL_DATATYPE_VARCHAR,0); - - log_sql_register_finish(s); - - if (global_config.announce) { - ap_add_version_component(p, PACKAGE_NAME"/"PACKAGE_VERSION); - } - global_config.db.p = p; - -#if defined(WITH_APACHE20) - return OK; -#endif -} - -/* This function handles calling the DB module, handling errors - * of missing tables and lost DB connections, and falling back to - * preserving the DB query. - * - * Parms: request record, table type, table name, and the full SQL command - */ - -static logsql_query_ret safe_sql_insert(request_rec *r, logsql_tabletype table_type, - const char *table_name, const char *query) { - - logsql_query_ret result; - logsql_state *cls = ap_get_module_config(r->server->module_config, - &log_sql_module); - - if (!global_config.db.connected || global_config.driver == NULL) { - /* preserve query */ - return LOGSQL_QUERY_NOLINK; - } - - result = global_config.driver->insert(r,&global_config.db,query); - - /* If we ran the query and it returned an error, try to be robust. - * (After all, the module thought it had a valid mysql_log connection but the query - * could have failed for a number of reasons, so we have to be extra-safe and check.) */ - switch (result) { - case LOGSQL_QUERY_SUCCESS: - return LOGSQL_QUERY_SUCCESS; - case LOGSQL_QUERY_NOLINK: - return LOGSQL_QUERY_FAIL; - /* TODO: What do we do here */ - case LOGSQL_QUERY_FAIL: - global_config.driver->disconnect(&global_config.db); - global_config.db.connected = 0; - /* re-open the connection and try again */ - if (log_sql_opendb_link(r->server) != LOGSQL_OPENDB_FAIL) { - log_error(APLOG_MARK,APLOG_NOTICE,0, r->server,"db reconnect successful"); -# if defined(WITH_APACHE20) - apr_sleep(apr_time_from_sec(0.25)); /* pause for a quarter second */ -# elif defined(WITH_APACHE13) -# if defined(WIN32) - Sleep((DWORD)0.25); -# else - { - struct timespec delay, remainder; - int nanoret; - delay.tv_sec = 0; - delay.tv_nsec = 250000000; /* pause for a quarter second */ - nanoret = nanosleep(&delay, &remainder); - if (nanoret && errno != EINTR) { - log_error(APLOG_MARK,APLOG_ERR, errno, r->server,"nanosleep unsuccessful"); - } - } -# endif /* win32 */ -# endif - result = global_config.driver->insert(r,&global_config.db,query); - if (result == LOGSQL_QUERY_SUCCESS) { - return LOGSQL_QUERY_SUCCESS; - } else { - log_error(APLOG_MARK,APLOG_ERR,0,r->server,"second attempt failed"); - preserve_entry(r, query); - return LOGSQL_QUERY_PRESERVED; - } - } else { - log_error(APLOG_MARK,APLOG_ERR,0,r->server, - "reconnect failed, unable to reach database. SQL logging stopped until child regains a db connection."); - log_error(APLOG_MARK,APLOG_ERR,0,r->server, - "log entries are being preserved in %s",cls->preserve_file); - preserve_entry(r, query); - return LOGSQL_QUERY_PRESERVED; - } - break; - case LOGSQL_QUERY_NOTABLE: - if (global_config.createtables) { - log_error(APLOG_MARK,APLOG_ERR,0,r->server, - "table doesn't exist...creating now"); - if ((result = global_config.driver->create_table(r, &global_config.db, table_type, - table_name))!=LOGSQL_TABLE_SUCCESS) { - log_error(APLOG_MARK,APLOG_ERR,result,r->server, - "child attempted but failed to create one or more tables for %s, preserving query", ap_get_server_name(r)); - preserve_entry(r, query); - return LOGSQL_QUERY_PRESERVED; - } else { - log_error(APLOG_MARK,APLOG_ERR,result, r->server, - "tables successfully created - retrying query"); - if ((result = global_config.driver->insert(r,&global_config.db,query))!=LOGSQL_QUERY_SUCCESS) { - log_error(APLOG_MARK,APLOG_ERR,result, r->server, - "giving up, preserving query"); - preserve_entry(r, query); - return LOGSQL_QUERY_PRESERVED; - } else { - log_error(APLOG_MARK,APLOG_NOTICE,0, r->server, - "query successful after table creation"); - return LOGSQL_QUERY_SUCCESS; - } - } - } else { - log_error(APLOG_MARK,APLOG_ERR,0,r->server, - "table doesn't exist, creation denied by configuration, preserving query"); - preserve_entry(r, query); - return LOGSQL_QUERY_PRESERVED; - } - break; - default: - log_error(APLOG_MARK,APLOG_ERR,0, r->server, - "Invalid return code from mog_log_query"); - return LOGSQL_QUERY_FAIL; - break; - } - return LOGSQL_QUERY_FAIL; -} - -/* This function gets called to create a per-server configuration - * record. It will always be called for the main server and - * for each virtual server that is established. Each server maintains - * its own state that is separate from the others' states. - * - * The return value is a pointer to the created module-specific - * structure. - */ -static void *log_sql_make_state(apr_pool_t *p, server_rec *s) -{ - logsql_state *cls = (logsql_state *) apr_pcalloc(p, sizeof(logsql_state)); - - /* These defaults are overridable in the httpd.conf file. */ - cls->transfer_log_format = apr_array_make(p, 1, sizeof(char *)); - cls->parsed_pool = p; - - cls->notes_table_name = DEFAULT_NOTES_TABLE_NAME; - cls->hin_table_name = DEFAULT_HIN_TABLE_NAME; - cls->hout_table_name = DEFAULT_HOUT_TABLE_NAME; - cls->cookie_table_name = DEFAULT_COOKIE_TABLE_NAME; - cls->preserve_file = DEFAULT_PRESERVE_FILE; - - cls->transfer_ignore_list = apr_array_make(p, 1, sizeof(char *)); - cls->transfer_accept_list = apr_array_make(p, 1, sizeof(char *)); - cls->remhost_ignore_list = apr_array_make(p, 1, sizeof(char *)); - cls->notes_list = apr_array_make(p, 1, sizeof(char *)); - cls->hin_list = apr_array_make(p, 1, sizeof(char *)); - cls->hout_list = apr_array_make(p, 1, sizeof(char *)); - cls->cookie_list = apr_array_make(p, 1, sizeof(char *)); - return (void *) cls; -} - - -/* Iterates through an array of char* and searches for a matching element - * Returns 0 if not found, 1 if found */ -static int in_array(apr_array_header_t *ary, const char *elem) -{ - int itr; - for (itr = 0; itr < ary->nelts; itr++) { - if (!strcmp(elem,((char **)ary->elts)[itr])) { - return 1; - } - } - return 0; -} - - -/* Parse through lists and merge based on +/- prefixes */ -static apr_array_header_t *do_merge_array(apr_array_header_t *parent, apr_array_header_t *child, apr_pool_t *p) -{ - apr_array_header_t *ret; - ret = apr_array_make(p, 1, sizeof(char *)); - if (apr_is_empty_array(child)) { - apr_array_cat(ret, parent); - } else { - apr_array_header_t *addlist, *dellist; - apr_pool_t *subp; - char **elem, **ptr = (char **)(child->elts); - int itr, overwrite = 0; - - apr_pool_create(&subp,p); - - addlist = apr_array_make(subp,5,sizeof(char *)); - dellist = apr_array_make(subp,5,sizeof(char *)); - - for (itr=0; itrnelts; itr++) { - if (*ptr[itr] == '+') { - elem = (char **)apr_array_push(addlist); - *elem = (ptr[itr]+1); - } else if (*ptr[itr] == '-') { - elem = (char **)apr_array_push(dellist); - *elem = (ptr[itr]+1); - } else { - overwrite = 1; - elem = (char **)apr_array_push(addlist); - *elem = ptr[itr]; - } - } - child = apr_array_make(p,1,sizeof(char *)); - ptr = (char **)(parent->elts); - if (overwrite==0) { - /* if we are not overwriting the existing then prepare for merge */ - for (itr=0; itrnelts; itr++) { - if (!in_array(addlist, ptr[itr]) && !in_array(dellist,ptr[itr])) { - elem = apr_array_push(ret); - *elem = apr_pstrdup(p, ptr[itr]); - } - } - } - apr_array_cat(ret, addlist); - apr_pool_destroy(subp); - } - return ret; -} - -static void *log_sql_merge_state(apr_pool_t *p, void *basev, void *addv) -{ - /* Fetch the two states to merge */ - logsql_state *parent = (logsql_state *) basev; - logsql_state *child = (logsql_state *) addv; - - /* Child can override these, otherwise they default to parent's choice. - * If the parent didn't set them, create reasonable defaults for the - * ones that should have such default settings. Leave the others null. */ - - /* No default for transfer_table_name because we want its absence - * to disable logging. */ - if (!child->transfer_table_name) { - child->transfer_table_name = parent->transfer_table_name; - } - - if (child->preserve_file == DEFAULT_PRESERVE_FILE) - child->preserve_file = parent->preserve_file; - /* server_root_relative the preserve file location */ - if (child->preserve_file == DEFAULT_PRESERVE_FILE) - child->preserve_file = ap_server_root_relative(p, DEFAULT_PRESERVE_FILE); - - if (child->notes_table_name == DEFAULT_NOTES_TABLE_NAME) - child->notes_table_name = parent->notes_table_name; - - if (child->hin_table_name == DEFAULT_HIN_TABLE_NAME) - child->hin_table_name = parent->hin_table_name; - - if (child->hout_table_name == DEFAULT_HOUT_TABLE_NAME) - child->hout_table_name = parent->hout_table_name; - - if (child->cookie_table_name == DEFAULT_COOKIE_TABLE_NAME) - child->cookie_table_name = parent->cookie_table_name; - - child->transfer_ignore_list = do_merge_array(parent->transfer_ignore_list, child->transfer_ignore_list, p); - child->transfer_accept_list = do_merge_array(parent->transfer_accept_list, child->transfer_accept_list, p); - child->remhost_ignore_list = do_merge_array(parent->remhost_ignore_list, child->remhost_ignore_list, p); - child->notes_list = do_merge_array(parent->notes_list, child->notes_list, p); - child->hin_list = do_merge_array(parent->hin_list, child->hin_list, p); - child->hout_list = do_merge_array(parent->hout_list, child->hout_list, p); - child->cookie_list = do_merge_array(parent->cookie_list,child->cookie_list, p); - - if (!child->cookie_name) - child->cookie_name = parent->cookie_name; - - - return (void*) child; -} - -/* Routine to perform the actual construction and execution of the relevant - * INSERT statements. - */ -static int log_sql_transaction(request_rec *orig) -{ - char **ptrptr, **ptrptr2; - logsql_state *cls = ap_get_module_config(orig->server->module_config, &log_sql_module); - const char *access_query; - request_rec *r; - const char *transfer_tablename = cls->transfer_table_name; - const char *notes_tablename = cls->notes_table_name; - const char *hout_tablename = cls->hout_table_name; - const char *hin_tablename = cls->hin_table_name; - const char *cookie_tablename = cls->cookie_table_name; - if (global_config.driver == NULL) { - return OK; - } - /* We handle mass virtual hosting differently. Dynamically determine the name - * of the table from the virtual server's name, and flag it for creation. - */ - if (global_config.massvirtual) { - /* TODO: Make these configurable? */ - char *access_base = "access_"; - char *notes_base = "notes_"; - char *hout_base = "headout_"; - char *hin_base = "headin_"; - char *cookie_base = "cookies_"; - - - /* Determine the hostname and convert it to all lower-case; */ - char *servername = apr_pstrdup(orig->pool,(char *)ap_get_server_name(orig)); - - char *p=servername; - while (*p) { - *p = apr_tolower(*p); - if (*p == '.') *p = '_'; - if (*p == '-') *p = '_'; - ++p; - } - - /* Find memory long enough to hold the table name + \0. */ - transfer_tablename = apr_pstrcat(orig->pool, access_base, servername, NULL); - notes_tablename = apr_pstrcat(orig->pool, notes_base, servername, NULL); - hin_tablename = apr_pstrcat(orig->pool, hin_base, servername, NULL); - hout_tablename = apr_pstrcat(orig->pool, hout_base, servername, NULL); - cookie_tablename = apr_pstrcat(orig->pool, cookie_base, servername, NULL); - - /* Tell this virtual server its transfer table name, and - * turn on create_tables, which is implied by massvirtual. - */ - - global_config.createtables = 1; - } - - /* Do we have enough info to log? */ - if (!transfer_tablename) { - return DECLINED; - } else { - const char *thehost; - const char *theitem; - char *fields = "", *values = ""; - char *itemsets = ""; - char *note_query = NULL; - char *hin_query = NULL; - char *hout_query = NULL; - char *cookie_query = NULL; - const char *unique_id; - const char *formatted_item; - int i, showcomma; - int proceed; - - for (r = orig; r->next; r = r->next) { - continue; - } - - /* The following is a stolen upsetting mess of pointers, I'm sorry. - * Anyone with the motiviation and/or the time should feel free - * to make this cleaner. :) */ - ptrptr2 = (char **) (cls->transfer_accept_list->elts + (cls->transfer_accept_list->nelts * cls->transfer_accept_list->elt_size)); - - /* Go through each element of the accept list and compare it to the - * request_uri. If we don't get a match, return without logging */ - if ((r->uri) && (cls->transfer_accept_list->nelts)) { - proceed = 0; - for (ptrptr = (char **) cls->transfer_accept_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->transfer_accept_list->elt_size)) - if (ap_strstr(r->uri, *ptrptr)) { - proceed = 1; - break; - } - if (!proceed) - return OK; - } - - /* Go through each element of the ignore list and compare it to the - * request_uri. If we get a match, return without logging */ - ptrptr2 = (char **) (cls->transfer_ignore_list->elts + (cls->transfer_ignore_list->nelts * cls->transfer_ignore_list->elt_size)); - if (r->uri) { - for (ptrptr = (char **) cls->transfer_ignore_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->transfer_ignore_list->elt_size)) - if (ap_strstr(r->uri, *ptrptr)) { - return OK; - } - } - - /* Go through each element of the ignore list and compare it to the - * remote host. If we get a match, return without logging */ - ptrptr2 = (char **) (cls->remhost_ignore_list->elts + (cls->remhost_ignore_list->nelts * cls->remhost_ignore_list->elt_size)); - thehost = ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME, NULL); - if (thehost) { - for (ptrptr = (char **) cls->remhost_ignore_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->remhost_ignore_list->elt_size)) - if (ap_strstr_c(thehost, *ptrptr)) { - return OK; - } - } - - - /* Iterate through the format characters and set up the INSERT string according to - * what the user has configured. */ - showcomma = 0; - for (i = 0; itransfer_log_format->nelts; i++) { - logsql_field *item = cls->parsed_log_format[i]; - if (item==NULL || item->func==NULL) { - log_error(APLOG_MARK, APLOG_ERR, 0, orig->server, - "Log Format '%s' unknown or incomplete",((char **)cls->transfer_log_format->elts)[i]); - continue; - } - - /* Yes, this key is one of the configured keys. - * Call the key's function and put the returned value into 'formatted_item' */ - formatted_item = item->func->func(item->func->want_orig_req ? orig : r, - item->param ? item->param : ""); - - /* Massage 'formatted_item' for proper SQL eligibility... */ - if (!formatted_item) { - formatted_item = ""; - } else if (formatted_item[0] == '-' && formatted_item[1] == '\0' && !item->string_contents) { - /* If apache tried to log a '-' character for a numeric field, convert that to a zero - * because the database expects a numeral and will reject the '-' character. */ - formatted_item = "0"; - } - - /* Append the fieldname and value-to-insert to the appropriate strings, quoting stringvals with ' as appropriate */ - fields = apr_pstrcat(r->pool, fields, (showcomma ? "," : ""), - item->sql_field_name, NULL); - values = apr_pstrcat(r->pool, values, (showcomma ? "," : ""), - global_config.driver->escape(r, formatted_item, r->pool,&global_config.db), NULL); - showcomma = 1; - } - - /* Work through the list of notes defined by LogSQLWhichNotes */ - i = 0; - unique_id = extract_unique_id(r, ""); - - ptrptr2 = (char **) (cls->notes_list->elts + (cls->notes_list->nelts * cls->notes_list->elt_size)); - for (ptrptr = (char **) cls->notes_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->notes_list->elt_size)) { - /* If the specified note (*ptrptr) exists for the current request... */ - if ((theitem = apr_table_get(r->notes, *ptrptr))) { - itemsets = apr_pstrcat(r->pool, itemsets, - (i > 0 ? "," : ""), - "(", - global_config.driver->escape(r, unique_id, r->pool, &global_config.db), - ",", - global_config.driver->escape(r, *ptrptr, r->pool,&global_config.db), - ",", - global_config.driver->escape(r, theitem, r->pool,&global_config.db), - ")", - NULL); - i++; - } - } - if ( *itemsets != '\0' ) { - note_query = apr_psprintf(r->pool, "insert %s into %s (id, item, val) values %s", - /*global_config.insertdelayed?"delayed":*/"", notes_tablename, itemsets); - - log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: note string: %s", note_query); - } - - /* Work through the list of headers-out defined by LogSQLWhichHeadersOut*/ - i = 0; - itemsets = ""; - - ptrptr2 = (char **) (cls->hout_list->elts + (cls->hout_list->nelts * cls->hout_list->elt_size)); - for (ptrptr = (char **) cls->hout_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->hout_list->elt_size)) { - /* If the specified header (*ptrptr) exists for the current request... */ - if ((theitem = apr_table_get(r->headers_out, *ptrptr))) { - itemsets = apr_pstrcat(r->pool, itemsets, - (i > 0 ? "," : ""), - "(", - global_config.driver->escape(r,unique_id, r->pool, &global_config.db), - ",", - global_config.driver->escape(r,*ptrptr, r->pool,&global_config.db), - ",", - global_config.driver->escape(r,theitem, r->pool,&global_config.db), - ")", - NULL); - i++; - } - } - if ( *itemsets != '\0' ) { - hout_query = apr_psprintf(r->pool, "insert %s into %s (id, item, val) values %s", - /*global_config.insertdelayed?"delayed":*/"", hout_tablename, itemsets); - - log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: header_out string: %s", hout_query); - } - - - /* Work through the list of headers-in defined by LogSQLWhichHeadersIn */ - i = 0; - itemsets = ""; - - ptrptr2 = (char **) (cls->hin_list->elts + (cls->hin_list->nelts * cls->hin_list->elt_size)); - for (ptrptr = (char **) cls->hin_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->hin_list->elt_size)) { - /* If the specified header (*ptrptr) exists for the current request... */ - if ((theitem = apr_table_get(r->headers_in, *ptrptr))) { - itemsets = apr_pstrcat(r->pool, itemsets, - (i > 0 ? "," : ""), - "(", - global_config.driver->escape(r,unique_id, r->pool, &global_config.db), - ",", - global_config.driver->escape(r,*ptrptr, r->pool,&global_config.db), - ",", - global_config.driver->escape(r,theitem, r->pool,&global_config.db), - ")", - NULL); - i++; - } - } - if ( *itemsets != '\0' ) { - hin_query = apr_psprintf(r->pool, "insert %s into %s (id, item, val) values %s", - /*global_config.insertdelayed?"delayed":*/"", hin_tablename, itemsets); - - log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: header_in string: %s", hin_query); - } - - - /* Work through the list of cookies defined by LogSQLWhichCookies */ - i = 0; - itemsets = ""; - - ptrptr2 = (char **) (cls->cookie_list->elts + (cls->cookie_list->nelts * cls->cookie_list->elt_size)); - for (ptrptr = (char **) cls->cookie_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->cookie_list->elt_size)) { - /* If the specified cookie (*ptrptr) exists for the current request... */ - if ( strncmp((theitem = extract_specific_cookie(r, *ptrptr)), "-", 1) ) { - itemsets = apr_pstrcat(r->pool, itemsets, - (i > 0 ? "," : ""), - "(", - global_config.driver->escape(r,unique_id, r->pool, &global_config.db), - ",", - global_config.driver->escape(r,*ptrptr, r->pool,&global_config.db), - ",", - global_config.driver->escape(r,theitem, r->pool,&global_config.db), - ")", - NULL); - i++; - } - - } - if ( *itemsets != '\0' ) { - cookie_query = apr_psprintf(r->pool, "insert %s into %s (id, item, val) values %s", - /*global_config.insertdelayed?"delayed":*/"", cookie_tablename, itemsets); - - log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: cookie string: %s", cookie_query); - } - - - /* Set up the actual INSERT statement */ - access_query = apr_psprintf(r->pool, "insert %s into %s (%s) values (%s)", - /*global_config.insertdelayed?"delayed":*/"", transfer_tablename, fields, values); - - log_error(APLOG_MARK,APLOG_DEBUG,0, r->server,"mod_log_sql: access string: %s", access_query); - - /* If the person activated force-preserve, go ahead and push all the entries - * into the preserve file, then return. - */ - if (global_config.forcepreserve) { - log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: preservation forced"); - preserve_entry(orig, access_query); - if ( note_query != NULL ) - preserve_entry(orig, note_query); - if ( hin_query != NULL ) - preserve_entry(orig, hin_query); - if ( hout_query != NULL ) - preserve_entry(orig, hout_query); - if ( cookie_query != NULL ) - preserve_entry(orig, cookie_query); - return OK; - } - - /* How's our mysql link integrity? */ - if (!global_config.db.connected) { - if (!global_config.forcepreserve) { - /* Make a try to establish the link */ - log_sql_opendb_link(r->server); - } - if (!global_config.db.connected) { - /* Unable to re-establish a DB link, so assume that it's really - * gone and send the entry to the preserve file instead. - * This short-circuits safe_sql_query() during a db outage and therefore - * we don't keep logging the db error over and over. - */ - preserve_entry(orig, access_query); - if ( note_query != NULL ) - preserve_entry(orig, note_query); - if ( hin_query != NULL ) - preserve_entry(orig, hin_query); - if ( hout_query != NULL ) - preserve_entry(orig, hout_query); - if ( cookie_query != NULL ) - preserve_entry(orig, cookie_query); - - return OK; - } else { - /* Whew, we got the DB link back */ - log_error(APLOG_MARK,APLOG_NOTICE,0, orig->server,"mod_log_sql: child established database connection"); - } - } - - - /* ---> So as of here we have a non-null value of mysql_log. <--- */ - /* ---> i.e. we have a good MySQL connection. <--- */ - - /* Make the access-table insert */ - safe_sql_insert(orig,LOGSQL_TABLE_ACCESS,transfer_tablename,access_query); - - /* Log the optional notes, headers, etc. */ - if (note_query) - safe_sql_insert(orig, LOGSQL_TABLE_NOTES,notes_tablename,note_query); - - if (hout_query) - safe_sql_insert(orig, LOGSQL_TABLE_HEADERSOUT,hout_tablename,hout_query); - - if (hin_query) - safe_sql_insert(orig, LOGSQL_TABLE_HEADERSIN,hin_tablename,hin_query); - - if (cookie_query) - safe_sql_insert(orig, LOGSQL_TABLE_COOKIES,cookie_tablename,cookie_query); - - return OK; - } -} - - -/* Setup of the available httpd.conf configuration commands. - * Structure: command, function called, NULL, where available, how many arguments, verbose description - */ -static const command_rec log_sql_cmds[] = { - AP_INIT_FLAG("LogSQLAnnounce", set_global_flag_slot, - (void *)APR_OFFSETOF(global_config_t, announce), RSRC_CONF, - "Whether to announce that mod_log_sql is loaded in the server header") - , - /* DB connection parameters */ - AP_INIT_TAKE13("LogSQLLoginInfo", set_log_sql_info, NULL, RSRC_CONF, - "The database connection URI in the form "driver://user:password@hostname:port/database"") - , - AP_INIT_TAKE2("LogSQLDBParam", set_dbparam, NULL, RSRC_CONF, - "First argument is the DB parameter, second is the value to assign") - , - AP_INIT_FLAG("LogSQLForcePreserve", set_global_flag_slot, - (void *)APR_OFFSETOF(global_config_t, forcepreserve), RSRC_CONF, - "Forces logging to preserve file and bypasses database") - , - AP_INIT_FLAG("LogSQLDisablePreserve", set_global_flag_slot, - (void *)APR_OFFSETOF(global_config_t, disablepreserve), RSRC_CONF, - "Completely disables use of the preserve file") - , - AP_INIT_TAKE1("LogSQLPreserveFile", set_server_file_slot, - (void *)APR_OFFSETOF(logsql_state,preserve_file), RSRC_CONF, - "Name of the file to use for data preservation during database downtime") - , - AP_INIT_FLAG("LogSQLCreateTables", set_global_nmv_flag_slot, - (void *)APR_OFFSETOF(global_config_t, createtables), RSRC_CONF, - "Turn on module's capability to create its SQL tables on the fly") - , - /* Table names */ - AP_INIT_FLAG("LogSQLMassVirtualHosting", set_global_flag_slot, - (void *)APR_OFFSETOF(global_config_t, massvirtual), RSRC_CONF, - "Activates option(s) useful for ISPs performing mass virutal hosting") - , - AP_INIT_TAKE1("LogSQLTransferLogTable", set_server_nmv_string_slot, - (void *)APR_OFFSETOF(logsql_state, transfer_table_name), RSRC_CONF, - "The database table that holds the transfer log") - , - AP_INIT_TAKE1("LogSQLNotesLogTable", set_server_nmv_string_slot, - (void *)APR_OFFSETOF(logsql_state, notes_table_name), RSRC_CONF, - "The database table that holds the notes") - , - AP_INIT_TAKE1("LogSQLHeadersOutLogTable", set_server_nmv_string_slot, - (void *)APR_OFFSETOF(logsql_state, hout_table_name), RSRC_CONF, - "The database table that holds the outbound headers") - , - AP_INIT_TAKE1("LogSQLHeadersInLogTable", set_server_nmv_string_slot, - (void *)APR_OFFSETOF(logsql_state, hin_table_name), RSRC_CONF, - "The database table that holds the inbound headers") - , - AP_INIT_TAKE1("LogSQLCookieLogTable", set_server_nmv_string_slot, - (void *)APR_OFFSETOF(logsql_state, cookie_table_name), RSRC_CONF, - "The database table that holds the cookie info") - , - /* New Log Format */ - AP_INIT_ITERATE("LogSQLTransferLogItems", add_server_string_slot, - (void *)APR_OFFSETOF(logsql_state, transfer_log_format), RSRC_CONF, - "What fields to log to the database transfer log") - , - AP_INIT_RAW_ARGS("LogSQLRegisterItem", set_register_field, - NULL, RSRC_CONF, - "Register a new Item for logging, Arguments: ItemName function argument sqlfield datatype datalen
" - "datatypes are INT, SMALLINT, VARCHAR, CHAR
") - , - AP_INIT_TAKE1("LogSQLShowConfig", set_global_string_slot, - (void *)APR_OFFSETOF(global_config_t, showconfig), RSRC_CONF, - "Add this to export the entire running function and dfield configuration to the named file") - , - /* Machine ID */ - AP_INIT_TAKE1("LogSQLMachineID", set_global_string_slot, - (void *)APR_OFFSETOF(global_config_t, machid), RSRC_CONF, - "Machine ID that the module will log, useful in web clusters to differentiate machines") - , - /* Limits on logging */ - AP_INIT_ITERATE("LogSQLRequestAccept", add_server_string_slot, - (void *)APR_OFFSETOF(logsql_state, transfer_accept_list), RSRC_CONF, - "List of URIs to accept for logging. Accesses that don't match will not be logged") - , - AP_INIT_ITERATE("LogSQLRequestIgnore", add_server_string_slot, - (void *)APR_OFFSETOF(logsql_state, transfer_ignore_list), RSRC_CONF, - "List of URIs to ignore. Accesses that match will not be logged to database") - , - AP_INIT_ITERATE("LogSQLRemhostIgnore", add_server_string_slot, - (void *)APR_OFFSETOF(logsql_state, remhost_ignore_list), RSRC_CONF, - "List of remote hosts to ignore. Accesses that match will not be logged to database") - , - /* Special logging table configuration */ - AP_INIT_TAKE1("LogSQLWhichCookie", set_server_string_slot, - (void *)APR_OFFSETOF(logsql_state, cookie_name), RSRC_CONF, - "The single cookie that you want logged in the access_log when using the 'c' config directive") - , - AP_INIT_ITERATE("LogSQLWhichNotes", add_server_string_slot, - (void *)APR_OFFSETOF(logsql_state, notes_list), RSRC_CONF, - "Notes that you would like to log in a separate table") - , - AP_INIT_ITERATE("LogSQLWhichHeadersOut", add_server_string_slot, - (void *)APR_OFFSETOF(logsql_state, hout_list), RSRC_CONF, - "Outbound headers that you would like to log in a separate table") - , - AP_INIT_ITERATE("LogSQLWhichHeadersIn", add_server_string_slot, - (void *)APR_OFFSETOF(logsql_state, hin_list), RSRC_CONF, - "Inbound headers that you would like to log in a separate table") - , - AP_INIT_ITERATE("LogSQLWhichCookies", add_server_string_slot, - (void *)APR_OFFSETOF(logsql_state, cookie_list), RSRC_CONF, - "The cookie(s) that you would like to log in a separate table") - , - AP_INIT_RAW_ARGS("LogSQLDeprecated", ap_set_deprecated, NULL, RSRC_CONF, - "
Deprecated
The following Commands are deprecated and should not be used..
Read the documentation for more information
Deprecated") - , - /* Deprecated commands */ - AP_INIT_TAKE1("LogSQLTransferLogFormat", set_logformat_slot, - (void *)APR_OFFSETOF(logsql_state, transfer_log_format), RSRC_CONF, - "(Deprecated) Use LogSQLTransferLogItem to specify symbolic log items instead") - , - AP_INIT_TAKE1("LogSQLDatabase", set_dbparam_slot, - (void *)"database", RSRC_CONF, - "(Deprecated) Use LogSQLDBParam database dbname. The name of the database database for logging") - , - AP_INIT_TAKE1("LogSQLTableType", set_dbparam_slot, - (void *)"tabletype", RSRC_CONF, - "(Deprecated) Use LogSQLDBParam tabletype type. What kind of table to create (MyISAM, InnoDB,...) when creating tables") - , - AP_INIT_TAKE1("LogSQLSocketFile", set_dbparam_slot, - (void *)"socketfile", RSRC_CONF, - "(Deprecated) Use LogSQLDBParam socketfile socket. Name of the file to employ for socket connections to database") - , - AP_INIT_TAKE1("LogSQLTCPPort", set_dbparam_slot, - (void *)"port", RSRC_CONF, - "(Deprecated) Use LogSQLDBParam port port. Port number to use for TCP connections to database, defaults to 3306 if not set") - , - {NULL} -}; -/* The configuration array that sets up the hooks into the module. */ -#if defined(WITH_APACHE20) -static void register_hooks(apr_pool_t *p) { - ap_hook_post_config(log_sql_post_config, NULL, NULL, APR_HOOK_REALLY_FIRST); - ap_hook_child_init(log_sql_child_init, NULL, NULL, APR_HOOK_MIDDLE); - ap_hook_log_transaction(log_sql_transaction, NULL, NULL, APR_HOOK_MIDDLE); -} - -module AP_MODULE_DECLARE_DATA log_sql_module = { - STANDARD20_MODULE_STUFF, - NULL, /* create per-directory config structures */ - NULL, /* merge per-directory config structures */ - log_sql_make_state, /* create per-server config structures */ - log_sql_merge_state, /* merge per-server config structures */ - log_sql_cmds, /* command handlers */ - register_hooks /* register hooks */ -}; -#elif defined(WITH_APACHE13) -module MODULE_VAR_EXPORT log_sql_module = { - STANDARD_MODULE_STUFF, - log_sql_module_init, /* module initializer */ - NULL, /* create per-dir config */ - NULL, /* merge per-dir config */ - log_sql_make_state, /* create server config */ - log_sql_merge_state, /* merge server config */ - log_sql_cmds, /* config directive table */ - NULL, /* [9] content handlers */ - NULL, /* [2] URI-to-filename translation */ - NULL, /* [5] check/validate user_id */ - NULL, /* [6] check authorization */ - NULL, /* [4] check access by host */ - NULL, /* [7] MIME type checker/setter */ - NULL, /* [8] fixups */ - log_sql_transaction, /* [10] logger */ - NULL /* [3] header parser */ -#if MODULE_MAGIC_NUMBER >= 19970728 /* 1.3-dev or later support these additionals... */ - ,log_sql_child_init, /* child process initializer */ - log_sql_child_exit, /* process exit/cleanup */ - NULL /* [1] post read-request */ -#endif - -}; -#endif diff --git a/mod_log_sql.h b/mod_log_sql.h deleted file mode 100644 index c1d9bff..0000000 --- a/mod_log_sql.h +++ /dev/null @@ -1,166 +0,0 @@ -/* $Id$ */ - -#ifndef MOD_LOG_SQL_H -#define MOD_LOG_SQL_H - -/* Create a set of LOGSQL_DECLARE(type), LOGSQL_DECLARE_NONSTD(type) and - * LOGSQL_DECLARE_DATA with appropriate export and import tags for the platform - */ -#if !defined(WIN32) -#define LOGSQL_DECLARE(type) type -#define LOGSQL_DECLARE_NONSTD(type) type -#define LOGSQL_DECLARE_DATA -#elif defined(LOGSQL_DECLARE_STATIC) -#define LOGSQL_DECLARE(type) type __stdcall -#define LOGSQL_DECLARE_NONSTD(type) type -#define LOGSQL_DECLARE_DATA -#elif defined(LOGSQL_DECLARE_EXPORT) -#define LOGSQL_DECLARE(type) __declspec(dllexport) type __stdcall -#define LOGSQL_DECLARE_NONSTD(type) __declspec(dllexport) type -#define LOGSQL_DECLARE_DATA __declspec(dllexport) -#else -#define LOGSQL_DECLARE(type) __declspec(dllimport) type __stdcall -#define LOGSQL_DECLARE_NONSTD(type) __declspec(dllimport) type -#define LOGSQL_DECLARE_DATA __declspec(dllimport) -#endif - -#define LOG_SQL_PLUGIN_VERSION 20080318 - -/* Registration function for extract functions */ - -typedef const char *logsql_item_func(request_rec *r, char *a); - - -typedef enum { - LOGSQL_FUNCTION_REQ_FINAL = 0, - LOGSQL_FUNCTION_REQ_ORIG -} logsql_function_req; - -LOGSQL_DECLARE(void) log_sql_register_function(apr_pool_t *p, - const char *alias, logsql_item_func *func, - logsql_function_req want_orig_default); - -LOGSQL_DECLARE(void) log_sql_register_alias(server_rec *s, apr_pool_t *p, - char key, const char *alias); - -typedef enum { - LOGSQL_DATATYPE_INT = 0, - LOGSQL_DATATYPE_SMALLINT, - LOGSQL_DATATYPE_VARCHAR, - LOGSQL_DATATYPE_CHAR, - LOGSQL_DATATYPE_BIGINT -} logsql_field_datatype; - -LOGSQL_DECLARE(void) log_sql_register_field(apr_pool_t *p, - const char *alias, - const char *funcalias, const char *param, - const char *sql_field_name, - logsql_field_datatype datatype, apr_size_t size); - -LOGSQL_DECLARE(void) log_sql_register_finish(server_rec *s); - -/* DB Connection structure holds connection handle */ -typedef struct { - int connected; /* Are we connected to the DB */ - void *handle; /* DB specific connection pointer */ - apr_pool_t *p; /* Pool to allocate handle off of */ - apr_table_t *parms; /* DB connection parameters */ -} logsql_dbconnection; - -/* open db handle return values*/ -typedef enum { - LOGSQL_OPENDB_FAIL = 0, - LOGSQL_OPENDB_SUCCESS, - LOGSQL_OPENDB_ALREADY, - LOGSQL_OPENDB_PRESERVE -} logsql_opendb_ret; - -typedef enum { - LOGSQL_QUERY_SUCCESS = 0, - LOGSQL_QUERY_FAIL, - LOGSQL_QUERY_NOLINK, - LOGSQL_QUERY_NOTABLE, - LOGSQL_QUERY_PRESERVED -} logsql_query_ret; - -typedef enum { - LOGSQL_TABLE_SUCCESS = 0, - LOGSQL_TABLE_FAIL -} logsql_table_ret; - -/* Table type to create/log to */ -typedef enum { - LOGSQL_TABLE_ACCESS = 0, - LOGSQL_TABLE_NOTES, - LOGSQL_TABLE_HEADERSOUT, - LOGSQL_TABLE_HEADERSIN, - LOGSQL_TABLE_COOKIES -} logsql_tabletype; - -/* All Tables */ -#define LOGSQL_TABLE_ALL LOGSQL_TABLE_ACCESS | LOGSQL_TABLE_NOTES | \ - LOGSQL_TABLE_HEADERSIN | LOGSQL_TABLE_HEADERSOUT | LOGSQL_TABLE_COOKIES - -/* MySQL module calls */ - -/* Registration function for database drivers */ - -typedef struct { - /* name of the provider */ - const char *providername; - /* NULL terminated list of drivers strings */ - const char **provided_drivers; - /* create a connection to the underlying database layer */ - logsql_opendb_ret (*connect)(server_rec *s, logsql_dbconnection *db); - /* disconnect from the underlying database layer */ - void (*disconnect)(logsql_dbconnection *db); - /* escape the SQL statement according to database rules */ - 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, - const char *query); - /* create a SQL table named table_name of table_type */ - logsql_table_ret (*create_table)(request_rec *r, logsql_dbconnection *db, - logsql_tabletype table_type, const char *table_name); -} logsql_dbdriver; - -LOGSQL_DECLARE(void) log_sql_register_driver(apr_pool_t *p, - logsql_dbdriver *driver); - -/* Module initialization Macros */ -#define LOGSQL_MODULE(driver) log_sql_##driver##_module -#if defined(WITH_APACHE20) -# define LOGSQL_MODULE_FORWARD(driver) module AP_MODULE_DECLARE_DATA LOGSQL_MODULE(driver) -# define LOGSQL_REGISTER(driver) \ - static int post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s); \ - static void register_hooks(apr_pool_t *p) { \ - ap_hook_post_config(post_config, NULL, NULL, APR_HOOK_REALLY_FIRST); \ - } \ - \ - LOGSQL_MODULE_FORWARD(driver) = { \ - STANDARD20_MODULE_STUFF, \ - NULL, NULL, NULL, NULL, NULL, register_hooks }; \ - static int post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) -#elif defined(WITH_APACHE13) -# define LOGSQL_MODULE_FORWARD(driver) module MODULE_VAR_EXPORT LOGSQL_MODULE(driver) -# define LOGSQL_REGISTER(driver) \ - static void module_init(server_rec *s, apr_pool_t *p); \ - LOGSQL_MODULE_FORWARD(driver) = { \ - STANDARD_MODULE_STUFF, module_init }; \ - static void module_init(server_rec *s, apr_pool_t *p) -#endif - -#if defined(WITH_APACHE20) -# define LOGSQL_SHUTDOWN \ - static -#endif - - -#if defined(WITH_APACHE20) -#define LOGSQL_REGISTER_RETURN log_sql_register_finish(s); return OK; -#elif defined(WITH_APACHE13) -#define LOGSQL_REGISTER_RETURN log_sql_register_finish(s); -#endif - -#endif /* MOD_LOG_SQL_H */ diff --git a/mod_log_sql_dbd.c b/mod_log_sql_dbd.c deleted file mode 100644 index c78a128..0000000 --- a/mod_log_sql_dbd.c +++ /dev/null @@ -1,132 +0,0 @@ -/* $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 deleted file mode 100644 index 40a972b..0000000 --- a/mod_log_sql_dbi.c +++ /dev/null @@ -1,263 +0,0 @@ -/* $Id: mod_log_sql_dbi.c 120 2004-04-17 15:14:12Z urkle@drip.ws $ */ - -#if defined(WITH_APACHE20) -# include "apache20.h" -#elif defined(WITH_APACHE13) -# include "apache13.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 "dbi/dbi.h" - -typedef struct { - dbi_conn conn; -} dbi_conn_rec; - -/* Connect to the MYSQL database */ -static logsql_opendb_ret log_sql_dbi_connect(server_rec *s, logsql_dbconnection *db) -{ - const char *driver = apr_table_get(db->parms,"driver"); - const char *host = apr_table_get(db->parms,"hostname"); - const char *user = apr_table_get(db->parms,"username"); - const char *passwd = apr_table_get(db->parms,"password"); - const char *database = apr_table_get(db->parms,"database"); - const char *s_tcpport = apr_table_get(db->parms,"port"); - unsigned int tcpport = (s_tcpport)?atoi(s_tcpport):0; - const char *socketfile = apr_table_get(db->parms,"socketfile"); - //dbi_result result; - dbi_conn_rec *dblink = db->handle; - if (!dblink) { - dblink = apr_pcalloc(db->p, sizeof(*dblink)); - db->handle = (void *)dblink; - } - - dblink->conn = dbi_conn_new(driver); - - dbi_conn_set_option(dblink->conn, "host", host); - dbi_conn_set_option(dblink->conn, "username", user); - dbi_conn_set_option(dblink->conn, "password", passwd); - dbi_conn_set_option(dblink->conn, "dbname", database); - if (tcpport) { - dbi_conn_set_option_numeric(dblink->conn, "port", tcpport); - } - - if (socketfile && !strcmp(driver,"mysql")) { - dbi_conn_set_option(dblink->conn, "mysql_unix_socket", socketfile); - } - - if (!dbi_conn_connect(dblink->conn)) { - log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "HOST: '%s' PORT: '%d' DB: '%s' USER: '%s' SOCKET: '%s'", - host, tcpport, database, user, socketfile); - return LOGSQL_OPENDB_SUCCESS; - } else { - const char *error; - dbi_conn_error(dblink->conn, &error); - log_error(APLOG_MARK, APLOG_ERR, 0, s, - "DBI Error: %s", error); - log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "HOST: '%s' PORT: '%d' DB: '%s' USER: '%s' SOCKET: '%s'", - host, tcpport, database, user, socketfile); - return LOGSQL_OPENDB_FAIL; - } -} - -/* Close the DB link */ -static void log_sql_dbi_close(logsql_dbconnection *db) -{ - dbi_conn_rec *dblink = db->handle; - dbi_conn_close(dblink->conn); - dblink->conn = NULL; -} - -/* Routine to escape the 'dangerous' characters that would otherwise - * corrupt the INSERT string: ', \, and " - */ -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; - - if (!from_str) - return NULL; - else { - char *to_str = strdup(from_str); - char *retval; - dbi_driver_quote_string(dbi_conn_get_driver(dblink->conn), &to_str); - retval = apr_pstrdup(p, to_str); - free(to_str); - return retval; - } -} - -/* Run a mysql insert query and return a categorized error or success */ -static logsql_query_ret log_sql_dbi_query(request_rec *r,logsql_dbconnection *db, - const char *query) -{ - const char *error; - dbi_result result; - dbi_conn_rec *dblink = db->handle; - - if (!dblink->conn) { - return LOGSQL_QUERY_NOLINK; - } - - /* Run the query */ - if ((result = dbi_conn_query(dblink->conn, query))) { - return LOGSQL_QUERY_SUCCESS; - } - /* Check to see if the error is "nonexistent table" */ - dbi_conn_error(dblink->conn, &error); - log_error(APLOG_MARK, APLOG_ERR, 0, r->server, - "DBI Error: %s", error); -/* if (real_error == ER_NO_SUCH_TABLE) { - log_error(APLOG_MARK,APLOG_ERR,0, r->server,"table does not exist, preserving query"); - return LOGSQL_QUERY_NOTABLE; - }*/ - return LOGSQL_QUERY_FAIL; -} - -/* Create table table_name of type table_type. */ -static logsql_table_ret log_sql_dbi_create(request_rec *r, logsql_dbconnection *db, - logsql_tabletype table_type, const char *table_name) -{ - dbi_result result; - const char *driver = apr_table_get(db->parms,"driver"); - const char *tabletype = apr_table_get(db->parms,"tabletype"); - char *type_suffix = NULL; - - char *create_prefix = "create table if not exists `"; - char *create_suffix = NULL; - char *create_sql; - - dbi_conn_rec *dblink = db->handle; - -/* if (!global_config.createtables) { - return APR_SUCCESS; - }*/ - - switch (table_type) { - case LOGSQL_TABLE_ACCESS: - create_suffix = - "` (id char(19),\ - agent varchar(255),\ - bytes_sent int unsigned,\ - child_pid smallint unsigned,\ - cookie varchar(255),\ - machine_id varchar(25),\ - request_file varchar(255),\ - referer varchar(255),\ - remote_host varchar(50),\ - remote_logname varchar(50),\ - remote_user varchar(50),\ - request_duration smallint unsigned,\ - request_line varchar(255),\ - request_method varchar(10),\ - request_protocol varchar(10),\ - request_time char(28),\ - request_uri varchar(255),\ - request_args varchar(255),\ - server_port smallint unsigned,\ - ssl_cipher varchar(25),\ - ssl_keysize smallint unsigned,\ - ssl_maxkeysize smallint unsigned,\ - status smallint unsigned,\ - time_stamp int unsigned,\ - virtual_host varchar(255))"; - break; - case LOGSQL_TABLE_COOKIES: - case LOGSQL_TABLE_HEADERSIN: - case LOGSQL_TABLE_HEADERSOUT: - case LOGSQL_TABLE_NOTES: - create_suffix = - "` (id char(19),\ - item varchar(80),\ - val varchar(80))"; - break; - } - - if (tabletype && !strcmp(driver,"mysql")) { - type_suffix = apr_pstrcat(r->pool, " TYPE=", - tabletype, NULL); - } - /* Find memory long enough to hold the whole CREATE string + \0 */ - create_sql = apr_pstrcat(r->pool, create_prefix, table_name, create_suffix, - type_suffix, NULL); - - log_error(APLOG_MARK,APLOG_DEBUG,0, r->server,"create string: %s", create_sql); - - if (!dblink) { - return LOGSQL_QUERY_NOLINK; - } - - /* Run the create query */ - if (!(result = dbi_conn_query(dblink, create_sql))) { - const char *error; - dbi_conn_error(dblink->conn, &error); - log_error(APLOG_MARK, APLOG_ERR, 0, r->server, - "DBI Error: %s", error); - return LOGSQL_TABLE_FAIL; - } - - return LOGSQL_TABLE_SUCCESS; -} - -static logsql_dbdriver log_sql_dbi_driver = { - "dbi", - NULL, - log_sql_dbi_connect, /* open DB connection */ - log_sql_dbi_close, /* close DB connection */ - log_sql_dbi_escape, /* escape query */ - log_sql_dbi_query, /* insert query */ - log_sql_dbi_create /* create table */ -}; - -static apr_status_t log_sql_dbi_cleanup(void *data) -{ - dbi_shutdown(); -#if defined(WITH_APACHE20) - return APR_SUCCESS; -#endif -} - -LOGSQL_REGISTER(dbi) { - dbi_driver driver; - const char **driver_list; - int count = 1; - - dbi_initialize(NULL); - - for (driver = dbi_driver_list(NULL); - driver; - driver = dbi_driver_list(driver)) { - count++; - } - driver_list = apr_pcalloc(p, sizeof(char *) * (count)); - count = 0; - for (driver = dbi_driver_list(NULL); - driver; - driver = dbi_driver_list(driver)) { - driver_list[count++] = dbi_driver_get_name(driver); - } - log_sql_dbi_driver.provided_drivers = driver_list; - log_sql_register_driver(p,&log_sql_dbi_driver); - apr_pool_cleanup_register(p, NULL, log_sql_dbi_cleanup, NULL); - LOGSQL_REGISTER_RETURN; -} diff --git a/mod_log_sql_logio.c b/mod_log_sql_logio.c deleted file mode 100644 index ed69acf..0000000 --- a/mod_log_sql_logio.c +++ /dev/null @@ -1,146 +0,0 @@ -/* $Id: mod_log_sql_ssl.c 140 2004-05-14 03:50:47Z 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 "http_connection.h" - -module AP_MODULE_DECLARE_DATA log_sql_logio_module; - -// From apachge 2.2's mod_logio.c to provide logging ACTUAL incoming and outgoing bytes -static const char logio_filter_name[] = "LOG_SQL_INPUT_OUTPUT"; - -typedef struct { - apr_off_t bytes_in; - apr_off_t bytes_out; -} logio_config_t; - -static void ap_logio_add_bytes_out(conn_rec *c, apr_off_t bytes){ - logio_config_t *cf = ap_get_module_config(c->conn_config, &log_sql_logio_module); - - cf->bytes_out += bytes; -} - -static const char *log_bytes_in(request_rec *r, char *a) -{ - logio_config_t *cf = ap_get_module_config(r->connection->conn_config, - &log_sql_logio_module); - - return apr_off_t_toa(r->pool, cf->bytes_in); -} - -static const char *log_bytes_out(request_rec *r, char *a) -{ - logio_config_t *cf = ap_get_module_config(r->connection->conn_config, - &log_sql_logio_module); - - return apr_off_t_toa(r->pool, cf->bytes_out); -} - -static int logio_transaction(request_rec *r) -{ - logio_config_t *cf = ap_get_module_config(r->connection->conn_config, - &log_sql_logio_module); - - cf->bytes_in = cf->bytes_out = 0; - - return OK; -} - -static apr_status_t logio_in_filter(ap_filter_t *f, - apr_bucket_brigade *bb, - ap_input_mode_t mode, - apr_read_type_e block, - apr_off_t readbytes) { - apr_off_t length; - apr_status_t status; - logio_config_t *cf = ap_get_module_config(f->c->conn_config, &log_sql_logio_module); - - status = ap_get_brigade(f->next, bb, mode, block, readbytes); - - apr_brigade_length (bb, 0, &length); - - if (length > 0) - cf->bytes_in += length; - - return status; -} - -static apr_status_t logio_out_filter(ap_filter_t *f, - apr_bucket_brigade *bb) { - apr_bucket *b = APR_BRIGADE_LAST(bb); - - /* End of data, make sure we flush */ - if (APR_BUCKET_IS_EOS(b)) { - APR_BUCKET_INSERT_BEFORE(b, - apr_bucket_flush_create(f->c->bucket_alloc)); - } - - return ap_pass_brigade(f->next, bb); -} - -static int logio_pre_conn(conn_rec *c, void *csd) { - logio_config_t *cf = apr_pcalloc(c->pool, sizeof(logio_config_t)); - - ap_set_module_config(c->conn_config, &log_sql_logio_module, cf); - - ap_add_input_filter(logio_filter_name, NULL, NULL, c); - ap_add_output_filter(logio_filter_name, NULL, NULL, c); - - return OK; -} - -static int post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) -{ - log_sql_register_function(p, "bytes_in", log_bytes_in, LOGSQL_FUNCTION_REQ_FINAL); - log_sql_register_function(p, "bytes_out", log_bytes_out, LOGSQL_FUNCTION_REQ_FINAL); - - log_sql_register_alias(s,p,'i', "bytes_in"); - log_sql_register_alias(s,p,'o', "bytes_out"); - - log_sql_register_field(p, "bytes_in", "bytes_in", NULL, - "bytes_in", LOGSQL_DATATYPE_INT, 0); - log_sql_register_field(p, "bytes_out", "bytes_out", NULL, - "bytes_out", LOGSQL_DATATYPE_INT, 0); - - log_sql_register_finish(s); - return OK; -} - -static void register_hooks(apr_pool_t *p) { - static const char *pre[] = { "mod_log_sql.c", NULL }; - - ap_hook_pre_connection(logio_pre_conn, NULL, NULL, APR_HOOK_MIDDLE); - ap_hook_log_transaction(logio_transaction, pre, NULL, APR_HOOK_MIDDLE); - ap_hook_post_config(post_config, NULL, NULL, APR_HOOK_REALLY_FIRST); - - ap_register_input_filter(logio_filter_name, logio_in_filter, NULL, - AP_FTYPE_NETWORK - 1); - ap_register_output_filter(logio_filter_name, logio_out_filter, NULL, - AP_FTYPE_NETWORK - 1); - - APR_REGISTER_OPTIONAL_FN(ap_logio_add_bytes_out); -} - -module AP_MODULE_DECLARE_DATA log_sql_logio_module = { - STANDARD20_MODULE_STUFF, - NULL, NULL, NULL, NULL, NULL, register_hooks -}; diff --git a/mod_log_sql_mysql.c b/mod_log_sql_mysql.c deleted file mode 100644 index 942c03a..0000000 --- a/mod_log_sql_mysql.c +++ /dev/null @@ -1,269 +0,0 @@ -/* $Id$ */ - -#if defined(WITH_APACHE20) -# include "apache20.h" -#elif defined(WITH_APACHE13) -# include "apache13.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 "mysql.h" -#include "mysqld_error.h" - -/* The enduser won't modify these */ -#define MYSQL_ERROR(mysql) ((mysql)?(mysql_error(mysql)):"MySQL server has gone away") - -/* Connect to the MYSQL database */ -static logsql_opendb_ret log_sql_mysql_connect(server_rec *s, logsql_dbconnection *db) -{ - const char *host = apr_table_get(db->parms,"hostname"); - const char *user = apr_table_get(db->parms,"username"); - const char *passwd = apr_table_get(db->parms,"password"); - const char *database = apr_table_get(db->parms,"database"); - const char *s_tcpport = apr_table_get(db->parms,"port"); - unsigned int tcpport = (s_tcpport)?atoi(s_tcpport):3306; - const char *socketfile = apr_table_get(db->parms,"socketfile"); - MYSQL *dblink = db->handle; - - dblink = mysql_init(dblink); - db->handle = (void *)dblink; - - - if (!socketfile) { - socketfile = "/var/lib/mysql/mysql.sock"; - } - - if (mysql_real_connect(dblink, host, user, passwd, database, tcpport, - socketfile, 0)) { - log_error(APLOG_MARK,APLOG_DEBUG,0, s,"HOST: '%s' PORT: '%d' DB: '%s' USER: '%s' SOCKET: '%s'", - host, tcpport, database, user, socketfile); - return LOGSQL_OPENDB_SUCCESS; - } else { - log_error(APLOG_MARK,APLOG_ERR,0, s,"mod_log_sql_mysql: database connection error: mysql error: %s", - MYSQL_ERROR(dblink)); - log_error(APLOG_MARK,APLOG_DEBUG, 0, s,"HOST: '%s' PORT: '%d' DB: '%s' USER: '%s' SOCKET: '%s'", - host, tcpport, database, user, socketfile); - return LOGSQL_OPENDB_FAIL; - } -} - -/* Close the DB link */ -static void log_sql_mysql_close(logsql_dbconnection *db) -{ - mysql_close((MYSQL *)db->handle); - /* mysql_close frees this data so NULL it out incase we reconnect later */ - db->handle=NULL; -} - -/* Routine to escape the 'dangerous' characters that would otherwise - * corrupt the INSERT string: ', \, and " - */ -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 */ - if (!from_str || strlen(from_str) == 0) - return "NULL"; - else { - char *to_str; - unsigned long length = strlen(from_str); - unsigned long retval; - - /* Pre-allocate a new string that could hold twice the original, which would only - * happen if the whole original string was 'dangerous' characters. - */ - to_str = (char *) apr_palloc(p, length * 2 + 3); - if (!to_str) { - return from_str; - } - strcpy(to_str, "'"); - if (!db->connected) { - /* Well, I would have liked to use the current database charset. mysql is - * unavailable, however, so I fall back to the slightly less respectful - * mysql_escape_string() function that uses the default charset. - */ - retval = mysql_escape_string(to_str+1, from_str, length); - } else { - /* MySQL is available, so I'll go ahead and respect the current charset when - * I perform the escape. - */ - retval = mysql_real_escape_string((MYSQL *)db->handle, to_str+1, from_str, length); - } - strcat(to_str,"'"); - - if (retval) - return to_str; - else - return from_str; - } -} - -#if defined(WIN32) -#define SIGNAL_GRAB -#define SIGNAL_RELEASE -#define SIGNAL_VAR -#else -#define SIGNAL_VAR void (*handler) (int); -#define SIGNAL_GRAB handler = signal(SIGPIPE, SIG_IGN); -#define SIGNAL_RELEASE signal(SIGPIPE, handler); -#endif -/* Run a mysql insert query and return a categorized error or success */ -static logsql_query_ret log_sql_mysql_query(request_rec *r,logsql_dbconnection *db, - const char *query) -{ - int retval; - SIGNAL_VAR - - unsigned int real_error = 0; - /*const char *real_error_str = NULL;*/ - - MYSQL *dblink = (MYSQL *)db->handle; - - if (!dblink) { - return LOGSQL_QUERY_NOLINK; - } - - /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */ - SIGNAL_GRAB - - /* Run the query */ - if (!(retval = mysql_query(dblink, query))) { - SIGNAL_RELEASE - return LOGSQL_QUERY_SUCCESS; - } - real_error = mysql_errno(dblink); - log_error(APLOG_MARK, APLOG_ERR, 0, r->server, - "mysql_query returned (%d) \"%s\"", real_error, MYSQL_ERROR(dblink)); - /* Check to see if the error is "nonexistent table" */ - - if (real_error == ER_NO_SUCH_TABLE) { - log_error(APLOG_MARK,APLOG_ERR,0, r->server,"table does not exist, preserving query"); - /* Restore SIGPIPE to its original handler function */ - SIGNAL_RELEASE - return LOGSQL_QUERY_NOTABLE; - } - - /* Restore SIGPIPE to its original handler function */ - SIGNAL_RELEASE - return LOGSQL_QUERY_FAIL; -} - -/* Create table table_name of type table_type. */ -static logsql_table_ret log_sql_mysql_create(request_rec *r, logsql_dbconnection *db, - logsql_tabletype table_type, const char *table_name) -{ - int retval; - const char *tabletype = apr_table_get(db->parms,"tabletype"); - SIGNAL_VAR - char *type_suffix = NULL; - - char *create_prefix = "create table if not exists `"; - char *create_suffix = NULL; - char *create_sql; - - MYSQL *dblink = (MYSQL *)db->handle; - -/* if (!global_config.createtables) { - return APR_SUCCESS; - }*/ - - switch (table_type) { - case LOGSQL_TABLE_ACCESS: - create_suffix = - "` (id char(19),\ - agent varchar(255),\ - bytes_sent int unsigned,\ - child_pid smallint unsigned,\ - cookie varchar(255),\ - machine_id varchar(25),\ - request_file varchar(255),\ - referer varchar(255),\ - remote_host varchar(50),\ - remote_logname varchar(50),\ - remote_user varchar(50),\ - request_duration smallint unsigned,\ - request_line varchar(255),\ - request_method varchar(10),\ - request_protocol varchar(10),\ - request_time char(28),\ - request_uri varchar(255),\ - request_args varchar(255),\ - server_port smallint unsigned,\ - ssl_cipher varchar(25),\ - ssl_keysize smallint unsigned,\ - ssl_maxkeysize smallint unsigned,\ - status smallint unsigned,\ - time_stamp int unsigned,\ - virtual_host varchar(255),\ - bytes_in int unsigned,\ - bytes_out int unsigned)"; - break; - case LOGSQL_TABLE_COOKIES: - case LOGSQL_TABLE_HEADERSIN: - case LOGSQL_TABLE_HEADERSOUT: - case LOGSQL_TABLE_NOTES: - create_suffix = - "` (id char(19),\ - item varchar(80),\ - val varchar(80))"; - break; - } - - if (tabletype) { - type_suffix = apr_pstrcat(r->pool, " TYPE=", - tabletype, NULL); - } - /* Find memory long enough to hold the whole CREATE string + \0 */ - create_sql = apr_pstrcat(r->pool, create_prefix, table_name, create_suffix, - type_suffix, NULL); - - log_error(APLOG_MARK,APLOG_DEBUG,0, r->server,"create string: %s", create_sql); - - if (!dblink) { - return LOGSQL_QUERY_NOLINK; - } - /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */ - SIGNAL_GRAB - - /* Run the create query */ - if ((retval = mysql_query(dblink, create_sql))) { - log_error(APLOG_MARK,APLOG_ERR,0, r->server,"failed to create table: %s", - table_name); - SIGNAL_RELEASE - return LOGSQL_TABLE_FAIL; - } - SIGNAL_RELEASE - return LOGSQL_TABLE_SUCCESS; -} - -static const char *supported_drivers[] = {"mysql",NULL}; -static logsql_dbdriver mysql_driver = { - "mysql", - supported_drivers, - log_sql_mysql_connect, /* open DB connection */ - log_sql_mysql_close, /* close DB connection */ - log_sql_mysql_escape, /* escape query */ - log_sql_mysql_query, /* insert query */ - log_sql_mysql_create /* create table */ -}; - -LOGSQL_REGISTER(mysql) { - log_sql_register_driver(p,&mysql_driver); - LOGSQL_REGISTER_RETURN; -} diff --git a/mod_log_sql_pgsql.c b/mod_log_sql_pgsql.c deleted file mode 100644 index 4e12920..0000000 --- a/mod_log_sql_pgsql.c +++ /dev/null @@ -1,247 +0,0 @@ -/* $Id$ */ - -#if defined(WITH_APACHE20) -# include "apache20.h" -#elif defined(WITH_APACHE13) -# include "apache13.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 "libpq-fe.h" - -/* Connect to the PGSQL database */ -static logsql_opendb_ret log_sql_pgsql_connect(server_rec *s, logsql_dbconnection *db) -{ - const char *host = apr_table_get(db->parms,"hostname"); - const char *user = apr_table_get(db->parms,"username"); - const char *passwd = apr_table_get(db->parms,"password"); - const char *database = apr_table_get(db->parms,"database"); - const char *s_tcpport = apr_table_get(db->parms,"port"); - - db->handle = PQsetdbLogin(host, s_tcpport, NULL, NULL, database, user, passwd); - - if (PQstatus(db->handle) == CONNECTION_OK) { - log_error(APLOG_MARK,APLOG_DEBUG,0, s,"HOST: '%s' PORT: '%s' DB: '%s' USER: '%s'", - host, s_tcpport, database, user); - return LOGSQL_OPENDB_SUCCESS; - } else { - log_error(APLOG_MARK,APLOG_DEBUG,0, s,"mod_log_sql: database connection error: %s", - PQerrorMessage(db->handle)); - log_error(APLOG_MARK,APLOG_DEBUG, 0, s,"HOST: '%s' PORT: '%s' DB: '%s' USER: '%s'", - host, s_tcpport, database, user); - return LOGSQL_OPENDB_FAIL; - } -} - -/* Close the DB link */ -static void log_sql_pgsql_close(logsql_dbconnection *db) -{ - PQfinish((PGconn*)(db->handle)); -} - -/* Routine to escape the 'dangerous' characters that would otherwise - * corrupt the INSERT string: ', \, and " - * Also PQescapeString does not place the ' around the string. So we have - * to do this manually - */ -static const char *log_sql_pgsql_escape(const char *from_str, apr_pool_t *p, - logsql_dbconnection *db) -{ - char *temp; - if (!from_str) - return NULL; - else { - char *to_str; - unsigned long length = strlen(from_str); - unsigned long retval; - - /* Pre-allocate a new string that could hold twice the original, which would only - * happen if the whole original string was 'dangerous' characters. - * And forsee the space for the 2 ' - */ - temp = to_str = (char *) apr_palloc(p, length * 2 + 3); - if (!to_str) { - return from_str; - } - - *temp = '\''; - temp++; - - retval = PQescapeString(temp, from_str, length); - - /* avoid the string to be tolong for the sql database*/ - if (retval > 250) retval = 250; - - *(temp+retval) = '\''; - *(temp+retval+1) = '\0'; - - /* We must always return the to_str, because we always need the ' added */ -// if (retval) - return to_str; -// else -// return from_str; - } -} - -/* Run a sql insert query and return a categorized error or success */ -static logsql_query_ret log_sql_pgsql_query(request_rec *r,logsql_dbconnection *db, - const char *query) -{ - PGresult *result; - void (*handler) (int); - unsigned int real_error = 0; - /*const char *real_error_str = NULL;*/ - - PGconn *conn = db->handle; - - if (PQstatus(conn) != CONNECTION_OK) { - return LOGSQL_QUERY_NOLINK; - } - /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */ - /* Does postgresql do this also ??? */ - handler = signal(SIGPIPE, SIG_IGN); - - result = PQexec(conn, query); - /* Run the query */ - if (PQresultStatus(result) == PGRES_COMMAND_OK) { - signal(SIGPIPE, handler); - PQclear(result); - return LOGSQL_QUERY_SUCCESS; - } - /* Check to see if the error is "nonexistent table" */ - /* removed ... don't know how ! (sorry) - real_error = mysql_errno(dblink); - - if (real_error == ER_NO_SUCH_TABLE) { - log_error(APLOG_MARK,APLOG_ERR,0, r->server,"table does not exist, preserving query"); - signal(SIGPIPE, handler); - PQclear(result); - return LOGSQL_QUERY_NOTABLE; - }*/ - - /* Restore SIGPIPE to its original handler function */ - signal(SIGPIPE, handler); - PQclear(result); - return LOGSQL_QUERY_FAIL; -} - -/* Create table table_name of type table_type. */ -static logsql_table_ret log_sql_pgsql_create(request_rec *r, logsql_dbconnection *db, - logsql_tabletype table_type, const char *table_name) -{ - PGresult *result; - const char *tabletype = apr_table_get(db->parms,"tabletype"); - void (*handler) (int); - char *type_suffix = NULL; - - char *create_prefix = "create table if not exists `"; - char *create_suffix = NULL; - char *create_sql; - - PGconn *conn = db->handle; - -/* if (!global_config.createtables) { - return APR_SUCCESS; - }*/ - - switch (table_type) { - case LOGSQL_TABLE_ACCESS: - create_suffix = - "` (id char(19),\ - agent varchar(255),\ - bytes_sent int unsigned,\ - child_pid smallint unsigned,\ - cookie varchar(255),\ - machine_id varchar(25),\ - request_file varchar(255),\ - referer varchar(255),\ - remote_host varchar(50),\ - remote_logname varchar(50),\ - remote_user varchar(50),\ - request_duration smallint unsigned,\ - request_line varchar(255),\ - request_method varchar(10),\ - request_protocol varchar(10),\ - request_time char(28),\ - request_uri varchar(255),\ - request_args varchar(255),\ - server_port smallint unsigned,\ - ssl_cipher varchar(25),\ - ssl_keysize smallint unsigned,\ - ssl_maxkeysize smallint unsigned,\ - status smallint unsigned,\ - time_stamp int unsigned,\ - virtual_host varchar(255))"; - break; - case LOGSQL_TABLE_COOKIES: - case LOGSQL_TABLE_HEADERSIN: - case LOGSQL_TABLE_HEADERSOUT: - case LOGSQL_TABLE_NOTES: - create_suffix = - "` (id char(19),\ - item varchar(80),\ - val varchar(80))"; - break; - } - - if (tabletype) { - type_suffix = apr_pstrcat(r->pool, " TYPE=", - tabletype, NULL); - } - /* Find memory long enough to hold the whole CREATE string + \0 */ - create_sql = apr_pstrcat(r->pool, create_prefix, table_name, create_suffix, - type_suffix, NULL); - - log_error(APLOG_MARK,APLOG_DEBUG,0, r->server,"create string: %s", create_sql); - - if (PQstatus(conn) != CONNECTION_OK) { - return LOGSQL_QUERY_NOLINK; - } - /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */ - handler = signal(SIGPIPE, SIG_IGN); - - /* Run the create query */ - result = PQexec(conn, create_sql); - if (PQresultStatus(result) != PGRES_COMMAND_OK) { - log_error(APLOG_MARK,APLOG_ERR,0, r->server,"failed to create table: %s", - table_name); - signal(SIGPIPE, handler); - PQclear(result); - return LOGSQL_TABLE_FAIL; - } - signal(SIGPIPE, handler); - PQclear(result); - return LOGSQL_TABLE_SUCCESS; -} - -static char *supported_drivers[] = {"pgsql",NULL}; -static logsql_dbdriver pgsql_driver = { - supported_drivers, - log_sql_pgsql_connect, /* open DB connection */ - log_sql_pgsql_close, /* close DB connection */ - log_sql_pgsql_escape, /* escape query */ - log_sql_pgsql_query, /* insert query */ - log_sql_pgsql_create /* create table */ -}; - -LOGSQL_REGISTER(pgsql) { - log_sql_register_driver(p,&pgsql_driver); - LOGSQL_REGISTER_RETURN; -} diff --git a/mod_log_sql_ssl.c b/mod_log_sql_ssl.c deleted file mode 100644 index 47bba8b..0000000 --- a/mod_log_sql_ssl.c +++ /dev/null @@ -1,106 +0,0 @@ -/* $Id$ */ - -#if defined(WITH_APACHE20) -# include "apache20.h" -#elif defined(WITH_APACHE13) -# include "apache13.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 "mod_ssl.h" - -#if defined(WITH_APACHE20) -static APR_OPTIONAL_FN_TYPE(ssl_var_lookup) *header_ssl_lookup = NULL; -# define TEST_SSL(r) header_ssl_lookup -#elif defined(WITH_APACHE13) -# define TEST_SSL(r) ap_ctx_get(r->connection->client->ctx, "ssl") -# define header_ssl_lookup ssl_var_lookup -#endif - -static const char *extract_ssl_keysize(request_rec *r, char *a) -{ - char *result = NULL; - if (TEST_SSL(r) != NULL) - { - result = header_ssl_lookup(r->pool, r->server, r->connection, r, "SSL_CIPHER_USEKEYSIZE"); - log_error(APLOG_MARK,APLOG_DEBUG,0, r->server,"SSL_KEYSIZE: %s", result); - if (result && result[0]) - return result; - else - return "0"; - } else { - return "0"; - } -} - -static const char *extract_ssl_maxkeysize(request_rec *r, char *a) -{ - char *result = NULL; - if (TEST_SSL(r) != NULL) - { - result = header_ssl_lookup(r->pool, r->server, r->connection, r, "SSL_CIPHER_ALGKEYSIZE"); - log_error(APLOG_MARK,APLOG_DEBUG,0, r->server,"SSL_ALGKEYSIZE: %s", result); - if (result && result[0]) - return result; - else - return "0"; - } else { - return "0"; - } -} - -static const char *extract_ssl_cipher(request_rec *r, char *a) -{ - char *result = NULL; - if (TEST_SSL(r) != NULL) - { - result = header_ssl_lookup(r->pool, r->server, r->connection, r, "SSL_CIPHER"); - log_error(APLOG_MARK,APLOG_DEBUG,0, r->server,"SSL_CIPHER: %s", result); - if (result && result[0]) - return result; - else - return "0"; - } else { - return "-"; - } -} - - -LOGSQL_REGISTER(ssl) -{ - log_sql_register_function(p, "ssl_keysize", extract_ssl_keysize, LOGSQL_FUNCTION_REQ_FINAL); - log_sql_register_function(p, "ssl_maxkeysize", extract_ssl_maxkeysize, LOGSQL_FUNCTION_REQ_FINAL); - log_sql_register_function(p, "ssl_cipher", extract_ssl_cipher, LOGSQL_FUNCTION_REQ_FINAL); - - log_sql_register_alias(s,p,'q', "ssl_keysize"); - log_sql_register_alias(s,p,'Q', "ssl_maxkeysize"); - log_sql_register_alias(s,p,'z', "ssl_cipher"); - - log_sql_register_field(p, "ssl_keysize", "ssl_keysize", NULL, - "ssl_keysize", LOGSQL_DATATYPE_VARCHAR, 0); - log_sql_register_field(p, "ssl_maxkeysize", "ssl_maxkeysize", NULL, - "ssl_maxkeysize", LOGSQL_DATATYPE_VARCHAR, 0); - log_sql_register_field(p, "ssl_cipher", "ssl_cipher", NULL, - "ssl_cipher", LOGSQL_DATATYPE_VARCHAR, 0); - -#if defined(WITH_APACHE20) - header_ssl_lookup = APR_RETRIEVE_OPTIONAL_FN(ssl_var_lookup); -#endif - LOGSQL_REGISTER_RETURN; -} diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..558b621 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,165 @@ +# @configure_input@ + +top_srcdir = @top_srcdir@ +srcdir = @abs_srcdir@ +builddir = @abs_builddir@ + +HEADERS = ../include/mod_log_sql.h \ + functions.h \ + functions13.h \ + functions20.h \ + ../include/apache13.h \ + ../include/apache20.h \ + ../include/winconfig.h + +CFLAGS = -Wc,-Wall -Wc,-fno-strict-aliasing -I$(top_srcdir)/include + +ifeq (@OOO_MAINTAIN@,1) +CFLAGS += -Wc,-Werror +endif + +coreSOURCES = @PACKAGE_NAME@.c +coreTARGET = @PACKAGE_NAME@@APXS_EXTENSION@ +coreLDADD = @RT_LIBS@ +coreCFLAGS = +coreNAME = log_sql +TARGETS = $(coreTARGET) + +sslSOURCES = @PACKAGE_NAME@_ssl.c +sslTARGET = @PACKAGE_NAME@_ssl@APXS_EXTENSION@ +sslLDADD = +sslCFLAGS = @MOD_SSL_CFLAGS@ +sslNAME = log_sql_ssl + +ifeq (@WANT_SSL_MOD@,1) +TARGETS += $(sslTARGET) +endif + +logioSOURCES = @PACKAGE_NAME@_logio.c +logioTARGET = @PACKAGE_NAME@_logio@APXS_EXTENSION@ +logioLDADD = +logioCFLAGS = +logioNAME = log_sql_logio + +ifeq (@WANT_LOGIO_MOD@,1) +TARGETS += $(logioTARGET) +endif + +mysqlSOURCES = @PACKAGE_NAME@_mysql.c +mysqlTARGET = @PACKAGE_NAME@_mysql@APXS_EXTENSION@ +mysqlLDADD = @MYSQL_LDFLAGS@ @MYSQL_LIBS@ +mysqlCFLAGS = @MYSQL_CFLAGS@ +mysqlNAME = log_sql_mysql + +ifeq (@WANT_MYSQL_MOD@,1) +TARGETS += $(mysqlTARGET) +endif + +pgsqlSOURCES = @PACKAGE_NAME@_pgsql.c +pgsqlTARGET = @PACKAGE_NAME@_pgsql@APXS_EXTENSION@ +pgsqlLDADD = @PGSQL_LDFLAGS@ @PGSQL_LIBS@ +pgsqlCFLAGS = @PGSQL_CFLAGS@ +pgsqlNAME = log_sql_pgsql + +ifeq (@WANT_PGSQL_MOD@,1) +TARGETS += $(pgsqlTARGET) +endif + +dbiSOURCES = @PACKAGE_NAME@_dbi.c +dbiTARGET = @PACKAGE_NAME@_dbi@APXS_EXTENSION@ +dbiLDADD = @DBI_LDFLAGS@ @DBI_LIBS@ +dbiCFLAGS = @DBI_CFLAGS@ +dbiNAME = log_sql_dbi + +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 + +OBJ = $(coreSOURCES:.c=.o) $(logioSOURCES:.c=.o) $(sslSOURCES:.c=.o) $(mysqlSOURCES:.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) $(dbdSOURCES:.c=.lo) + +SLO = $(coreSOURCES:.c=.slo) $(logioSOURCES:.c=.slo) $(sslSOURCES:.c=.slo) $(mysqlSOURCES:.c=.slo) \ + $(dbiSOURCES:.c=.slo) $(pgsqlSOURCES:.c=.slo) $(dbdSOURCES:.c=.slo) + +STD_DIST = Makefile.in + +DISTFILES = $(STD_DIST) $(EXTRA_DIST) $(coreSOURCES) $(HEADERS) \ + $(sslSOURCES) $(logioSOURCES) $(mysqlSOURCES) $(pgsqlSOURCES) $(dbiSOURCES) $(dbdSOURCES) + +all: $(TARGETS) + +$(coreTARGET): $(coreSOURCES) $(HEADERS) + @@APXS_BIN@ -c -o $(coreTARGET) $(coreCFLAGS) $(CFLAGS) \ + @DEFS@ @AP_DEFS@ $(coreLDADD) $(coreSOURCES) + +$(logioTARGET): $(logioSOURCES) $(HEADERS) + @@APXS_BIN@ -c -o $(logioTARGET) $(logioCFLAGS) $(CFLAGS) \ + @DEFS@ @AP_DEFS@ $(logioLDADD) $(logioSOURCES) + +$(sslTARGET): $(sslSOURCES) $(HEADERS) + @@APXS_BIN@ -c -o $(sslTARGET) $(sslCFLAGS) $(CFLAGS) \ + @DEFS@ @AP_DEFS@ $(sslLDADD) $(sslSOURCES) + +$(mysqlTARGET): $(mysqlSOURCES) $(HEADERS) + @@APXS_BIN@ -c -o $(mysqlTARGET) $(mysqlCFLAGS) $(CFLAGS) \ + @DEFS@ @AP_DEFS@ $(mysqlLDADD) $(mysqlSOURCES) + +$(pgsqlTARGET): $(pgsqlSOURCES) $(HEADERS) + @@APXS_BIN@ -c -o $(pgsqlTARGET) $(pgsqlCFLAGS) $(CFLAGS) \ + @DEFS@ @AP_DEFS@ $(pgsqlLDADD) $(pgsqlSOURCES) + +$(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) + @@APXS_BIN@ -n $(coreNAME) -i $(coreTARGET); \ + if test @WANT_MYSQL_MOD@ -eq 1; then \ + @APXS_BIN@ -n $(mysqlNAME) -i $(mysqlTARGET); \ + fi; \ + if test @WANT_PGSQL_MOD@ -eq 1; then \ + @APXS_BIN@ -n $(pgsqlNAME) -i $(pgsqlTARGET); \ + 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); \ + fi; \ + if test @WANT_LOGIO_MOD@ -eq 1; then \ + @APXS_BIN@ -n $(logioNAME) -i $(logioTARGET); \ + fi; + +activate: + @@APXS_BIN@ -n $(coreNAME) -i -a $(coreTARGET); \ + if test @WANT_SSL_MOD@ -eq 1; then \ + @APXS_BIN@ -n $(sslNAME) -i -a $(sslTARGET); \ + fi + +clean: + $(RM) $(OBJ) $(SLO) $(LO) $(TARGETS) + $(RM) -r .libs + +local-dist: $(DISTFILES) + mkdir -p $(DESTDIR) + cp -dp --parents $(DISTFILES) $(DESTDIR) diff --git a/src/functions.h b/src/functions.h new file mode 100644 index 0000000..07711d2 --- /dev/null +++ b/src/functions.h @@ -0,0 +1,261 @@ +/* $Id$ */ + +/* Begin the individual functions that, given a request r, + * extract the needed information from it and return the + * value to the calling entity. + */ + +static const char *extract_remote_host(request_rec *r, char *a) +{ + return (char *) ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME, NULL); +} + +static const char *extract_remote_address(request_rec *r, char *a) __attribute__((unused)); + +static const char *extract_remote_address(request_rec *r, char *a) +{ + return r->connection->remote_ip; +} + +static const char *extract_local_address(request_rec *r, char *a) __attribute__((unused)); + +static const char *extract_local_address(request_rec *r, char *a) +{ + return r->connection->local_ip; +} + +static const char *extract_remote_logname(request_rec *r, char *a) +{ + return (char *) ap_get_remote_logname(r); +} + +static const char *extract_remote_user(request_rec *r, char *a) +{ + #ifdef WITH_APACHE13 + char *rvalue = r->connection->user; + #else + char *rvalue = r->user; + #endif + if (rvalue == NULL) { + rvalue = "-"; + } else if (strlen(rvalue) == 0) { + rvalue = "\"\""; + } + return rvalue; +} + +static const char *extract_request_line(request_rec *r, char *a) +{ + /* Upddated to mod_log_config logic */ + /* NOTE: If the original request contained a password, we + * re-write the request line here to contain XXXXXX instead: + * (note the truncation before the protocol string for HTTP/0.9 requests) + * (note also that r->the_request contains the unmodified request) + */ + return (r->parsed_uri.password) + ? apr_pstrcat(r->pool, r->method, " ", + apr_uri_unparse(r->pool, + &r->parsed_uri, 0), + r->assbackwards ? NULL : " ", + r->protocol, NULL) + : r->the_request; +} + +static const char *extract_request_file(request_rec *r, char *a) +{ + return r->filename; +} + +static const char *extract_request_uri(request_rec *r, char *a) +{ + return r->uri; +} + +static const char *extract_request_method(request_rec *r, char *a) +{ + return r->method; +} + +static const char *extract_request_protocol(request_rec *r, char *a) +{ + return r->protocol; +} + +static const char *extract_request_query(request_rec *r, char *a) +{ + return (r->args) ? apr_pstrcat(r->pool, "?", + r->args, NULL) + : ""; +} + +static const char *extract_status(request_rec *r, char *a) +{ + if (r->status <= 0) { + return "-"; + } else { + return apr_psprintf(r->pool, "%d", r->status); + } +} + +static const char *extract_virtual_host(request_rec *r, char *a) +{ + return r->server->server_hostname; +} + +static const char *extract_server_name(request_rec *r, char *a) +{ + return ap_get_server_name(r); +} + +static const char *extract_machine_id(request_rec *r, char *a) +{ + if (!global_config.machid) + return "-"; + else + return global_config.machid; +} + +static const char *extract_server_port(request_rec *r, char *a) +{ + return apr_psprintf(r->pool, "%u", + r->server->port ? r->server->port : ap_default_port(r)); +} + +/* This respects the setting of UseCanonicalName so that + * the dynamic mass virtual hosting trick works better. + */ +static const char *log_server_name(request_rec *r, char *a) __attribute__((unused)); +static const char *log_server_name(request_rec *r, char *a) +{ + return ap_get_server_name(r); +} + +static const char *extract_child_pid(request_rec *r, char *a) +{ + if (*a == '\0' || !strcmp(a, "pid")) { + return apr_psprintf(r->pool, "%" APR_PID_T_FMT, getpid()); + } + else if (!strcmp(a, "tid")) { +#if APR_HAS_THREADS + apr_os_thread_t tid = apr_os_thread_current(); +#else + int tid = 0; /* APR will format "0" anyway but an arg is needed */ +#endif + return apr_psprintf(r->pool, "%pT", &tid); + } + /* bogus format */ + return a; +} + +static const char *extract_referer(request_rec *r, char *a) +{ + const char *tempref; + + tempref = apr_table_get(r->headers_in, "Referer"); + if (!tempref) + { + return "-"; + } else { + return tempref; + } +} + +static const char *extract_agent(request_rec *r, char *a) +{ + const char *tempag; + + tempag = apr_table_get(r->headers_in, "User-Agent"); + if (!tempag) + { + return "-"; + } else { + return tempag; + } +} + +static const char *extract_specific_cookie(request_rec *r, char *a) +{ + const char *cookiestr; + char *cookieend; + char *isvalid; + char *cookiebuf; + + if (a != NULL) { + log_error(APLOG_MARK,APLOG_DEBUG, 0, r->server, + "watching for cookie '%s'", a); + + /* Fetch out the cookie header */ + cookiestr = (char *)apr_table_get(r->headers_in, "cookie2"); + if (cookiestr != NULL) { + log_error(APLOG_MARK,APLOG_DEBUG, 0, r->server, + "Cookie2: [%s]", cookiestr); + /* Does the cookie string contain one with our name? */ + isvalid = ap_strstr_c(cookiestr, a); + if (isvalid != NULL) { + /* Move past the cookie name and equal sign */ + isvalid += strlen(a) + 1; + /* Duplicate it into the pool */ + cookiebuf = apr_pstrdup(r->pool, isvalid); + /* Segregate just this cookie out of the string + * with a terminating nul at the first semicolon */ + cookieend = ap_strchr(cookiebuf, ';'); + if (cookieend != NULL) + *cookieend = '\0'; + return cookiebuf; + } + } + + cookiestr = (char *)apr_table_get(r->headers_in, "cookie"); + if (cookiestr != NULL) { + log_error(APLOG_MARK,APLOG_DEBUG, 0, r->server, + "Cookie: [%s]", cookiestr); + isvalid = ap_strstr_c(cookiestr, a); + if (isvalid != NULL) { + isvalid += strlen(a) + 1; + cookiebuf = apr_pstrdup(r->pool, isvalid); + cookieend = ap_strchr(cookiebuf, ';'); + if (cookieend != NULL) + *cookieend = '\0'; + return cookiebuf; + } + } + + cookiestr = apr_table_get(r->headers_out, "set-cookie"); + if (cookiestr != NULL) { + log_error(APLOG_MARK,APLOG_DEBUG, 0, r->server, + "Set-Cookie: [%s]", cookiestr); + isvalid = ap_strstr_c(cookiestr, a); + if (isvalid != NULL) { + isvalid += strlen(a) + 1; + cookiebuf = apr_pstrdup(r->pool, isvalid); + cookieend = ap_strchr(cookiebuf, ';'); + if (cookieend != NULL) + *cookieend = '\0'; + return cookiebuf; + } + } + } + + return "-"; +} + +/*static const char *extract_cookie(request_rec *r, char *a) +{ + logsql_state *cls = ap_get_module_config(r->server->module_config, + &log_sql_module); + + return extract_specific_cookie(r, (char *)cls->cookie_name); +}*/ + +static const char *extract_unique_id(request_rec *r, char *a) +{ + const char *tempid; + + tempid = apr_table_get(r->subprocess_env, "UNIQUE_ID"); + if (!tempid) + return "-"; + else + return tempid; +} + +/* End declarations of various extract_ functions */ diff --git a/src/functions13.h b/src/functions13.h new file mode 100644 index 0000000..54e3138 --- /dev/null +++ b/src/functions13.h @@ -0,0 +1,58 @@ +/* $Id$ */ + +static const char *extract_bytes_sent(request_rec *r, char *a) +{ + if (!r->sent_bodyct) { + return "-"; + } + else { + long int bs; + ap_bgetopt(r->connection->client, BO_BYTECT, &bs); + return ap_psprintf(r->pool, "%ld", bs); + } +} + +static const char *extract_request_time(request_rec *r, char *a) +{ + int timz; + struct tm *t; + char tstr[MAX_STRING_LEN]; + + t = ap_get_gmtoff(&timz); + + if (a && *a) { /* Custom format */ + strftime(tstr, MAX_STRING_LEN, a, t); + } else { /* CLF format */ + char sign = (timz < 0 ? '-' : '+'); + + if (timz < 0) { + timz = -timz; + } + strftime(tstr, MAX_STRING_LEN, "[%d/%b/%Y:%H:%M:%S ", t); + ap_snprintf(tstr + strlen(tstr), sizeof(tstr) - strlen(tstr), "%c%.2d%.2d]", sign, timz / 60, timz % 60); + } + + return ap_pstrdup(r->pool, tstr); +} + +static const char *extract_request_duration(request_rec *r, char *a) +{ + return ap_psprintf(r->pool, "%ld", time(NULL) - r->request_time); +} + +static const char *extract_request_timestamp(request_rec *r, char *a) +{ + return ap_psprintf(r->pool, "%ld", (long) time(NULL)); +} +static const char *extract_connection_status(request_rec *r, char *a) __attribute__((unused)); +static const char *extract_connection_status(request_rec *r, char *a) +{ + if (r->connection->aborted) + return "X"; + + if ((r->connection->keepalive) && + ((r->server->keep_alive_max - r->connection->keepalives) > 0)) { + return "+"; + } + return "-"; +} diff --git a/src/functions20.h b/src/functions20.h new file mode 100644 index 0000000..5220b7c --- /dev/null +++ b/src/functions20.h @@ -0,0 +1,116 @@ +/* $Id$ */ + +static const char *extract_bytes_sent(request_rec *r, char *a) +{ + if (!r->sent_bodyct || !r->bytes_sent) { + return "-"; + } else { + return apr_psprintf(r->pool, "%" APR_OFF_T_FMT, r->bytes_sent); + } +} + +static const char *extract_request_time_custom(request_rec *r, char *a, + apr_time_exp_t *xt) +{ + apr_size_t retcode; + char tstr[MAX_STRING_LEN]; + apr_strftime(tstr, &retcode, sizeof(tstr), a, xt); + return apr_pstrdup(r->pool, tstr); +} + +#define DEFAULT_REQUEST_TIME_SIZE 32 +typedef struct { + unsigned t; + char timestr[DEFAULT_REQUEST_TIME_SIZE]; + unsigned t_validate; +} cached_request_time; + +#define TIME_CACHE_SIZE 4 +#define TIME_CACHE_MASK 3 +static cached_request_time request_time_cache[TIME_CACHE_SIZE]; + +static const char *extract_request_time(request_rec *r, char *a) +{ + apr_time_exp_t xt; + + /* Please read comments in mod_log_config.h for more info about + * the I_INSIST....COMPLIANCE define + */ + if (a && *a) { /* Custom format */ +#ifdef I_INSIST_ON_EXTRA_CYCLES_FOR_CLF_COMPLIANCE + ap_explode_recent_localtime(&xt, apr_time_now()); +#else + ap_explode_recent_localtime(&xt, r->request_time); +#endif + return extract_request_time_custom(r, a, &xt); + } else { /* CLF format */ + /* This code uses the same technique as ap_explode_recent_localtime(): + * optimistic caching with logic to detect and correct race conditions. + * See the comments in server/util_time.c for more information. + */ + cached_request_time* cached_time = apr_palloc(r->pool, + sizeof(*cached_time)); +#ifdef I_INSIST_ON_EXTRA_CYCLES_FOR_CLF_COMPLIANCE + apr_time_t request_time = apr_time_now(); +#else + apr_time_t request_time = r->request_time; +#endif + unsigned t_seconds = (unsigned)apr_time_sec(request_time); + unsigned i = t_seconds & TIME_CACHE_MASK; + memcpy(cached_time, &(request_time_cache[i]), sizeof(*cached_time)); + if ((t_seconds != cached_time->t) || + (t_seconds != cached_time->t_validate)) { + + /* Invalid or old snapshot, so compute the proper time string + * and store it in the cache + */ + char sign; + int timz; + + ap_explode_recent_localtime(&xt, r->request_time); + timz = xt.tm_gmtoff; + if (timz < 0) { + timz = -timz; + sign = '-'; + } + else { + sign = '+'; + } + cached_time->t = t_seconds; + apr_snprintf(cached_time->timestr, DEFAULT_REQUEST_TIME_SIZE, + "[%02d/%s/%d:%02d:%02d:%02d %c%.2d%.2d]", + xt.tm_mday, apr_month_snames[xt.tm_mon], + xt.tm_year+1900, xt.tm_hour, xt.tm_min, xt.tm_sec, + sign, timz / (60*60), timz % (60*60)); + cached_time->t_validate = t_seconds; + memcpy(&(request_time_cache[i]), cached_time, + sizeof(*cached_time)); + } + return cached_time->timestr; + } +} + +static const char *extract_request_duration(request_rec *r, char *a) +{ + apr_time_t duration = apr_time_now() - r->request_time; + return apr_psprintf(r->pool, "%" APR_TIME_T_FMT, apr_time_sec(duration)); +} + +static const char *extract_request_timestamp(request_rec *r, char *a) +{ + return apr_psprintf(r->pool, "%"APR_TIME_T_FMT, apr_time_sec(apr_time_now())); +} + +static const char *extract_connection_status(request_rec *r, char *a) __attribute__((unused)); +static const char *extract_connection_status(request_rec *r, char *a) +{ + if (r->connection->aborted) + return "X"; + + if (r->connection->keepalive == AP_CONN_KEEPALIVE && + (!r->server->keep_alive_max || + (r->server->keep_alive_max - r->connection->keepalives) > 0)) { + return "+"; + } + return "-"; +} diff --git a/src/mod_log_sql.c b/src/mod_log_sql.c new file mode 100644 index 0000000..d319e97 --- /dev/null +++ b/src/mod_log_sql.c @@ -0,0 +1,1578 @@ +/* $Id$ */ + +#if defined(WITH_APACHE20) +# include "apache20.h" +#elif defined(WITH_APACHE13) +# include "apache13.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 + +#if APR_HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif + +#include "mod_log_sql.h" + +/* Configuratino Defaults */ +#define DEFAULT_TRANSFER_LOG_FMT "AbHhmRSsTUuv" +#define DEFAULT_NOTES_TABLE_NAME "notes" +#define DEFAULT_HIN_TABLE_NAME "headers_in" +#define DEFAULT_HOUT_TABLE_NAME "headers_out" +#define DEFAULT_COOKIE_TABLE_NAME "cookies" +#define DEFAULT_PRESERVE_FILE "logs/mod_log_sql-preserve" + +/* -------------* + * DECLARATIONS * + * -------------*/ + +/* Declare ourselves so the configuration routines can find and know us. */ +module AP_MODULE_DECLARE_DATA log_sql_module; + +/* The contents of these are known 'Apache wide' and are not variable + * on a per-virtual-server basis. Every virtual server 'knows' the + * same versions of these variables. + */ + +typedef struct { + int massvirtual; + int createtables; + int forcepreserve; + int disablepreserve; + char *machid; + int announce; + logsql_dbconnection db; + logsql_dbdriver *driver; + /** Show config support */ + char *showconfig; + apr_file_t *showconfig_fp; +} global_config_t; + +static global_config_t global_config; + +/* structure to hold helper function info */ +typedef struct { + const char *alias; /* The function alias */ + logsql_item_func *func; /* The extraction function pointer */ + int want_orig_req; /* if it requires the original request prior to internal redirection */ +} logsql_function; + +/* list of logsql_functions's for log types */ +static apr_array_header_t *logsql_function_list; + +/* structure to hold sqlfield mappings */ +typedef struct { + const char *alias; /* long name for item */ + const char *funcalias; /* The function alias */ + logsql_function *func; /* its extraction function */ + char *param; /* Parameter for function */ + const char *sql_field_name; /* its column in SQL */ + char string_contents; /* Whether this is a string field or not */ + logsql_field_datatype datatype; /* the field data type */ + apr_size_t size; /* The size of the data type */ +} logsql_field; + +/* list of logsql_item's for log types */ +static apr_array_header_t *logsql_field_list; + +/* But the contents of this structure will vary by virtual server. + * This permits each virtual server to vary its configuration slightly + * for per-server customization. + * + * Each child process has its own segregated copy of this structure. + */ +typedef struct { + apr_array_header_t *transfer_ignore_list; + apr_array_header_t *transfer_accept_list; + apr_array_header_t *remhost_ignore_list; + apr_array_header_t *notes_list; + apr_array_header_t *hout_list; + apr_array_header_t *hin_list; + apr_array_header_t *cookie_list; + const char *notes_table_name; + const char *hout_table_name; + const char *hin_table_name; + const char *cookie_table_name; + const char *transfer_table_name; + apr_array_header_t *transfer_log_format; + apr_pool_t *parsed_pool; + logsql_field **parsed_log_format; + const char *preserve_file; + const char *cookie_name; +} logsql_state; + +/** Registration function for extract functions + * + * This functions registers an alias for a function + * + * @note This is exported from the module + */ +LOGSQL_DECLARE(void) log_sql_register_function(apr_pool_t *p, + const char *alias, logsql_item_func *func, + logsql_function_req want_orig_req) +{ + logsql_function *item; + if (!logsql_function_list) + logsql_function_list = apr_array_make(p,10, sizeof(logsql_function)); + + item = apr_array_push(logsql_function_list); + item->alias = alias; + item->func = func; + item->want_orig_req = want_orig_req; + if (global_config.showconfig_fp) { + apr_file_printf(global_config.showconfig_fp," Function : %s\n",alias); + } +} +/** Register a old style sql mapping to the new style + * + * @note This is exported from the module + */ +LOGSQL_DECLARE(void) log_sql_register_alias(server_rec *s, apr_pool_t *p, + char key, const char *alias) +{ + server_rec *ts; + for (ts = s; ts; ts = ts->next) { + logsql_state *cfg = ap_get_module_config(ts->module_config, + &log_sql_module); + int itr; + for (itr = 0; itr < cfg->transfer_log_format->nelts; itr++) { + const char *logformat = ((const char **)cfg->transfer_log_format->elts)[itr]; + //log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Testing Logformat %s against %c for %s",logformat,key,alias); + // Check if it is only one character AND it is our key + if (logformat[1]=='\0' && logformat[0]==key) { + ((const char **)cfg->transfer_log_format->elts)[itr] = alias; + } + } + } +} + + +/** Registration sqlfield aliases to functions + * + * And update parse cache for transfer_log_format + * + * @note This is exported from the module + */ +LOGSQL_DECLARE(void) log_sql_register_field(apr_pool_t *p, + const char *alias, + const char *funcalias, const char *param, + const char *sql_field_name, + logsql_field_datatype datatype, apr_size_t size) +{ + logsql_field *item; + + if (!logsql_field_list) + logsql_field_list = apr_array_make(p,10, sizeof(logsql_field)); + + item = apr_array_push(logsql_field_list); + item->func = NULL; + item->alias = apr_pstrdup(p, alias); + item->funcalias = apr_pstrdup(p, funcalias); + item->param = apr_pstrdup(p, param); + item->sql_field_name = apr_pstrdup(p,sql_field_name); + item->datatype = datatype; + item->string_contents = 0; + if (datatype == LOGSQL_DATATYPE_CHAR || datatype == LOGSQL_DATATYPE_VARCHAR) { + item->string_contents = 1; + } + item->size = size; +} + +/** + * Links sql field items with their functions + */ +LOGSQL_DECLARE(void) log_sql_register_finish(server_rec *s) +{ + server_rec *ts; + int itr, f; + logsql_field *item; + logsql_function *func; + for (itr = 0; itr < logsql_field_list->nelts; itr++) { + item = &((logsql_field *)logsql_field_list->elts)[itr]; + if (item->func) continue; + /* Find function alias in function list */ + for (f = 0; f < logsql_function_list->nelts; f++) { + func = &((logsql_function *)logsql_function_list->elts)[f]; + if (strcmp(func->alias,item->funcalias)==0) { + item->func = func; + if (global_config.showconfig_fp) { + apr_file_printf(global_config.showconfig_fp," Item : %s using function %s(%s)\n" + "\tStoring in field %s of type %s(%"APR_SIZE_T_FMT")\n", + item->alias, item->funcalias, item->param, + item->sql_field_name, item->string_contents ? "TEXT":"NUMERIC", item->size); + } + break; + } + } + if (!item->func) { + log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + "Could not find function %s for item %s",item->funcalias, item->alias); + } + } + /* some voodoo here to post parse logitems in all servers * + * so a "cached" list is used in the main logging loop for speed */ + for (ts = s; ts; ts = ts->next) { + logsql_state *cfg = ap_get_module_config(ts->module_config, + &log_sql_module); + + if (!cfg->parsed_log_format) { + cfg->parsed_log_format = apr_pcalloc(cfg->parsed_pool, + cfg->transfer_log_format->nelts * sizeof(logsql_field *)); + } + + for (itr = 0; itr < cfg->transfer_log_format->nelts; itr++) { + const char *logformat = ((char **)cfg->transfer_log_format->elts)[itr]; + for (f = 0; f < logsql_field_list->nelts; f++) { + item = &((logsql_field *)logsql_field_list->elts)[f]; + if (item->func && strcmp(logformat,item->alias)==0) { + cfg->parsed_log_format[itr] = item; + break; + } + } + } + } +} + +/* Registration function for database drivers */ +LOGSQL_DECLARE(void) log_sql_register_driver(apr_pool_t *p, + logsql_dbdriver *driver) +{ + global_config.driver = driver; +} + +/* Include all the core extract functions */ +#include "functions.h" +#if defined(WITH_APACHE13) +# include "functions13.h" +#elif defined(WITH_APACHE20) +# include "functions20.h" +#endif + +static logsql_opendb_ret log_sql_opendb_link(server_rec* s) +{ + logsql_opendb_ret result; + if (global_config.driver == NULL) { + return LOGSQL_OPENDB_FAIL; + } + if (global_config.forcepreserve) { + /*global_config.db.connected = 1;*/ + return LOGSQL_OPENDB_PRESERVE; + } + if (global_config.db.connected) { + return LOGSQL_OPENDB_ALREADY; + } + /* database + host + user + passwd + */ + if (global_config.db.parms) { + result = global_config.driver->connect(s, &global_config.db); + if (result==LOGSQL_OPENDB_FAIL) { + global_config.db.connected = 0; + } else { + global_config.db.connected = 1; + } + return result; + } else { + log_error(APLOG_MARK, APLOG_ERR, 0, s, + "mod_log_sql: insufficient configuration info to establish database link"); + return LOGSQL_OPENDB_FAIL; + } +} + +static void preserve_entry(request_rec *r, const char *query) +{ + logsql_state *cls = ap_get_module_config(r->server->module_config, + &log_sql_module); + apr_status_t result; + apr_file_t *fp; + + /* If preserve file is disabled bail out */ + if (global_config.disablepreserve) + return; + #if defined(WITH_APACHE20) + result = apr_file_open(&fp, cls->preserve_file,APR_APPEND | APR_WRITE | APR_CREATE, APR_OS_DEFAULT, r->pool); + #elif defined(WITH_APACHE13) + fp = ap_pfopen(r->pool, cls->preserve_file, "a"); + result = (fp)?0:errno; + #endif + if (result != APR_SUCCESS) { + log_error(APLOG_MARK, APLOG_ERR, result, r->server, + "attempted append of local preserve file '%s' but failed.",cls->preserve_file); + } else { + apr_file_printf(fp,"%s;\n", query); + #if defined(WITH_APACHE20) + apr_file_close(fp); + #elif defined(WITH_APACHE13) + ap_pfclose(r->pool, fp); + #endif + log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, + "mod_log_sql: entry preserved in %s", cls->preserve_file); + } +} + + +/* ------------------------------------------------* + * Command handlers that are called according * + * to the directives found at Apache runtime. * + * ------------------------------------------------*/ + + +static const char *set_global_flag_slot(cmd_parms *cmd, + void *struct_ptr, + int flag) +{ + void *ptr = &global_config; + int offset = (int)(long)cmd->info; + + *(int *)((char *)ptr + offset) = flag ? 1 : 0; + + return NULL; +} + +static const char *set_global_nmv_flag_slot(cmd_parms *cmd, + void *struct_ptr, + int flag) +{ + if (global_config.massvirtual) { + return apr_psprintf(cmd->pool, + "mod_log_sql: do not set %s when LogSQLMassVirtualHosting(%d) is On.%d:%d", + cmd->cmd->name, global_config.massvirtual, + (int)(long)&global_config, (int)(long)struct_ptr); + } else { + return set_global_flag_slot(cmd,struct_ptr,flag); + } +} + +static const char *set_global_string_slot(cmd_parms *cmd, + void *struct_ptr, + const char *arg) +{ + void *ptr = &global_config; + int offset = (int)(long)cmd->info; + + *(const char **)((char *)ptr + offset) = apr_pstrdup(cmd->pool,arg); + return NULL; +} + +static const char *set_server_string_slot(cmd_parms *cmd, + void *struct_ptr, + const char *arg) +{ + void *ptr = ap_get_module_config(cmd->server->module_config, + &log_sql_module); + int offset = (int)(long)cmd->info; + + *(const char **)((char *)ptr + offset) = arg; + + return NULL; +} + +static const char *set_server_file_slot(cmd_parms *cmd, + void *struct_ptr, + const char *arg) +{ + void *ptr = ap_get_module_config(cmd->server->module_config, + &log_sql_module); + int offset = (int)(long)cmd->info; + const char *path; + + path = ap_server_root_relative(cmd->pool, (char *)arg); + + if (!path) { + return apr_pstrcat(cmd->pool, "Invalid file path ", + arg, NULL); + } + + *(const char **)((char*)ptr + offset) = path; + + return NULL; +} + +static apr_array_header_t *create_logformat_default(apr_pool_t *p) +{ + apr_array_header_t *logformat; + char **addme; + + logformat = apr_array_make(p, 12, sizeof(char *)); + addme = apr_array_push(logformat); *addme = "useragent"; + addme = apr_array_push(logformat); *addme = "bytes_sent"; + addme = apr_array_push(logformat); *addme = "request_protocol"; + addme = apr_array_push(logformat); *addme = "remote_host"; + addme = apr_array_push(logformat); *addme = "request_method"; + addme = apr_array_push(logformat); *addme = "referer"; + addme = apr_array_push(logformat); *addme = "timestamp"; + addme = apr_array_push(logformat); *addme = "status"; + addme = apr_array_push(logformat); *addme = "request_duration"; + addme = apr_array_push(logformat); *addme = "request_uri"; + addme = apr_array_push(logformat); *addme = "remote_user"; + addme = apr_array_push(logformat); *addme = "virtual_host"; + return logformat; +} + +static const char *set_server_nmv_string_slot(cmd_parms *parms, + void *struct_ptr, + const char *arg) +{ + if (global_config.massvirtual) + return apr_psprintf(parms->pool, + "mod_log_sql: do not set %s when LogSQLMassVirtualHosting is On.", + parms->cmd->name); + else + return set_server_string_slot(parms,struct_ptr,arg); +} + +/* Set a DB connection parameter */ +static const char *set_dbparam(cmd_parms *cmd, + void *struct_ptr, + const char *key, + const char *val) +{ + if (!global_config.db.parms) { + global_config.db.parms = apr_table_make(cmd->pool,5); + } + apr_table_set(global_config.db.parms,key,val); + return NULL; +} + +static const char *set_dbparam_slot(cmd_parms *cmd, + void *struct_ptr, + const char *arg) +{ + const char *param = (char *)cmd->info; + set_dbparam(cmd,NULL,param,arg); + return NULL; +} + +/* Sets basic connection info */ +static const char *set_log_sql_info(cmd_parms *cmd, void *dummy, + const char *host, const char *user, const char *pwd) +{ + if (!user) { /* user is null, so only one arg passed */ + /* TODO: to more error checking/force all params to be set */ + apr_uri_t uri; + apr_uri_parse(cmd->pool, host, &uri); + if (uri.scheme) { + set_dbparam(cmd, NULL, "driver", uri.scheme); + } + if (uri.hostname) { + set_dbparam(cmd, NULL, "hostname", uri.hostname); + } + if (uri.user) { + set_dbparam(cmd, NULL, "username", uri.user); + } + if (uri.password) { + set_dbparam(cmd, NULL, "password", uri.password); + } + if (uri.port_str) { + set_dbparam(cmd, NULL, "port", uri.port_str); + } + if (uri.path) { + /* extract Database name */ + char *off = ap_strchr(++uri.path,'/'); + if (off) + *off='\0'; + set_dbparam(cmd, NULL, "database", uri.path); + + } + } else { + if (*host != '.') { + set_dbparam(cmd, NULL, "hostname", host); + } + if (*user != '.') { + set_dbparam(cmd, NULL, "username", user); + } + if (*pwd != '.') { + set_dbparam(cmd, NULL, "password", pwd); + } + } + return NULL; +} + +static const char *add_server_string_slot(cmd_parms *cmd, + void *struct_ptr, + const char *arg) +{ + char **addme; + void *ptr = ap_get_module_config(cmd->server->module_config, + &log_sql_module); + int offset = (int)(long)cmd->info; + apr_array_header_t *ary = *(apr_array_header_t **)((char *)ptr + offset); + addme = apr_array_push(ary); + *addme = apr_pstrdup(ary->pool, arg); + + return NULL; +} + +static const char *set_logformat_slot(cmd_parms *cmd, + void *struct_ptr, + const char *arg) +{ + const char *t; + char t2[2] = {'\0','\0'}; + for (t = arg; *t != '\0'; t++) { + t2[0] = *t; + add_server_string_slot(cmd, NULL, t2); + } + return NULL; +} + +static const char *set_register_field(cmd_parms *cmd, + void *struct_ptr, + const char *arg) +{ + char *alias, *funcalias, *param, *field, *datatype_s, *size_s; + logsql_field_datatype datatype; + apr_size_t size; + + alias = ap_getword_white(cmd->pool, &arg); + funcalias = ap_getword_white(cmd->pool, &arg); + param = ap_getword_conf(cmd->pool, &arg); + field = ap_getword_white(cmd->pool, &arg); + datatype_s = ap_getword_white(cmd->pool, &arg); + size_s = ap_getword_white(cmd->pool, &arg); + + if (strcasecmp("VARCHAR",datatype_s)==0) { + datatype = LOGSQL_DATATYPE_VARCHAR; + } else if (strcasecmp("INT",datatype_s)==0) { + datatype = LOGSQL_DATATYPE_INT; + } else if (strcasecmp("CHAR",datatype_s)==0) { + datatype = LOGSQL_DATATYPE_CHAR; + } else if (strcasecmp("SMALLINT",datatype_s)==0) { + datatype = LOGSQL_DATATYPE_SMALLINT; + } else if (strcasecmp("BIGINT",datatype_s)==0) { + datatype = LOGSQL_DATATYPE_BIGINT; + } else { + return apr_psprintf(cmd->pool, "Unknown data type %s",datatype_s); + } + + size = atoi(size_s); + + log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server, + "%s, %s, %s, %s, %s(%d), %s(%"APR_SIZE_T_FMT")", + alias, funcalias, param, field, datatype_s, datatype, size_s, size); + + log_sql_register_field(cmd->pool, alias, funcalias, param, + field, datatype, size); + + return NULL; +} + +/*------------------------------------------------------------* + * Apache-specific hooks into the module code * + * that are defined in the array 'mysql_lgog_module' (at EOF) * + *------------------------------------------------------------*/ +/* Closing mysql link: child_exit(1.3), pool registration(2.0) */ +#if defined(WITH_APACHE20) +static apr_status_t log_sql_close_link(void *data) +{ + if (global_config.driver) + global_config.driver->disconnect(&global_config.db); + return APR_SUCCESS; +} +#elif defined(WITH_APACHE13) +static void log_sql_child_exit(server_rec *s, apr_pool_t *p) +{ + if (global_config.driver) + global_config.driver->disconnect(&global_config.db); +} +#endif + +/* Child Init */ +#if defined(WITH_APACHE20) +static void log_sql_child_init(apr_pool_t *p, server_rec *s) +#elif defined(WITH_APACHE13) +static void log_sql_child_init(server_rec *s, apr_pool_t *p) +#endif +{ + logsql_opendb_ret retval; +# if defined(WITH_APACHE20) + /* Register cleanup hook to close DDB connection (apache 2 doesn't have child_exit) */ + apr_pool_cleanup_register(p, NULL, log_sql_close_link, log_sql_close_link); +# endif + /* Open a link to the database */ + retval = log_sql_opendb_link(s); + switch (retval) { + case LOGSQL_OPENDB_FAIL: + if (global_config.driver==NULL) { + log_error(APLOG_MARK, APLOG_ERR, 0, s, + "mod_log_sql: Driver module not loaded"); + } else { + log_error(APLOG_MARK, APLOG_ERR, 0, s, + "mod_log_sql: child spawned but unable to open database link"); + } + break; + case LOGSQL_OPENDB_SUCCESS: + case LOGSQL_OPENDB_ALREADY: + log_error(APLOG_MARK,APLOG_DEBUG,0, s, + "mod_log_sql: open_logdb_link successful"); + break; + case LOGSQL_OPENDB_PRESERVE: + log_error(APLOG_MARK,APLOG_DEBUG, 0, s, + "mod_log_sql: open_logdb_link said that preservation is forced"); + break; + } +} + +static apr_array_header_t *do_merge_array(apr_array_header_t *parent, apr_array_header_t *child, apr_pool_t *p); + +/* post_config / module_init */ +#if defined(WITH_APACHE20) +static int log_sql_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) +#elif defined(WITH_APACHE13) +static void log_sql_module_init(server_rec *s, apr_pool_t *p) +#endif +{ + server_rec *cur_s; + const char *default_p = ap_server_root_relative(p, DEFAULT_PRESERVE_FILE); + apr_array_header_t *parent = NULL; + + if (global_config.showconfig != NULL) { + const char *tempfile = ap_server_root_relative(p, global_config.showconfig); + apr_status_t result; + #if defined(WITH_APACHE20) + result = apr_file_open(&global_config.showconfig_fp, tempfile,APR_TRUNCATE | APR_WRITE | APR_CREATE, APR_OS_DEFAULT, p); + #elif defined(WITH_APACHE13) + global_config.showconfig_fp = ap_pfopen(p, tempfile, "w"); + result = (fp)?0:errno; + #endif + if (result != APR_SUCCESS) { + log_error(APLOG_MARK, APLOG_ERR, result, s, + "attempted open of showconfig file '%s' failed.",tempfile); + global_config.showconfig_fp = NULL; + } else { + #if defined(WITH_APACHE20) + char temp_time[APR_RFC822_DATE_LEN]; + apr_rfc822_date(temp_time,apr_time_now()); + #elif defined(WITH_APACHE13) + char *temp_time = ap_get_time()); + #endif + apr_file_printf(global_config.showconfig_fp,"Mod_log_sql Config dump created on %s\n", temp_time); + } + } + + for (cur_s = s; cur_s != NULL; cur_s= cur_s->next) { + logsql_state *cls = ap_get_module_config(cur_s->module_config, + &log_sql_module); + /* ap_server_root_relative any default preserve file locations */ + if (cls->preserve_file == DEFAULT_PRESERVE_FILE) + cls->preserve_file = default_p; + + /* Post-process logformats */ + if (!cur_s->is_virtual) { + parent = create_logformat_default(p); + cls->transfer_log_format = do_merge_array(parent, cls->transfer_log_format, p); + parent = cls->transfer_log_format; + } else { + cls->transfer_log_format = do_merge_array(parent, cls->transfer_log_format, p); + } + } + + /* TODO: Add local_address, remote_address, connection_status */ + /** Register functions */ + /** register_function(p, funcname, func_ptr, which request_rec); */ + log_sql_register_function(p, "useragent", extract_agent, LOGSQL_FUNCTION_REQ_ORIG); + log_sql_register_function(p, "request_args", extract_request_query, LOGSQL_FUNCTION_REQ_ORIG); + log_sql_register_function(p, "bytes_sent", extract_bytes_sent, LOGSQL_FUNCTION_REQ_FINAL); + log_sql_register_function(p, "cookie", extract_specific_cookie,LOGSQL_FUNCTION_REQ_FINAL); + log_sql_register_function(p, "request_file", extract_request_file, LOGSQL_FUNCTION_REQ_FINAL); + log_sql_register_function(p, "request_protocol",extract_request_protocol,LOGSQL_FUNCTION_REQ_FINAL); + log_sql_register_function(p, "remote_host", extract_remote_host, LOGSQL_FUNCTION_REQ_FINAL); + log_sql_register_function(p, "unique_id", extract_unique_id, LOGSQL_FUNCTION_REQ_FINAL); + log_sql_register_function(p, "remote_logname", extract_remote_logname, LOGSQL_FUNCTION_REQ_FINAL); + log_sql_register_function(p, "request_method", extract_request_method, LOGSQL_FUNCTION_REQ_FINAL); + log_sql_register_function(p, "machine_id", extract_machine_id, LOGSQL_FUNCTION_REQ_FINAL); + log_sql_register_function(p, "child_pid", extract_child_pid, LOGSQL_FUNCTION_REQ_FINAL); + log_sql_register_function(p, "server_port", extract_server_port, LOGSQL_FUNCTION_REQ_FINAL); + log_sql_register_function(p, "referrer", extract_referer, LOGSQL_FUNCTION_REQ_ORIG); + log_sql_register_function(p, "request_line", extract_request_line, LOGSQL_FUNCTION_REQ_ORIG); + log_sql_register_function(p, "timestamp", extract_request_timestamp,LOGSQL_FUNCTION_REQ_FINAL); + log_sql_register_function(p, "status", extract_status, LOGSQL_FUNCTION_REQ_ORIG); + log_sql_register_function(p, "request_duration",extract_request_duration,LOGSQL_FUNCTION_REQ_ORIG); + log_sql_register_function(p, "request_time", extract_request_time, LOGSQL_FUNCTION_REQ_FINAL); + log_sql_register_function(p, "remote_user", extract_remote_user, LOGSQL_FUNCTION_REQ_FINAL); + log_sql_register_function(p, "request_uri", extract_request_uri, LOGSQL_FUNCTION_REQ_ORIG); + log_sql_register_function(p, "virtual_host", extract_virtual_host, LOGSQL_FUNCTION_REQ_FINAL); + log_sql_register_function(p, "server_name", extract_server_name, LOGSQL_FUNCTION_REQ_FINAL); + + /** Old style aliases */ + /** register_alias(s, shortname, longname) */ + log_sql_register_alias(s,p,'A',"useragent"); + log_sql_register_alias(s,p,'a',"request_args"); + log_sql_register_alias(s,p,'b',"bytes_sent"); + log_sql_register_alias(s,p,'c',"cookie"); + log_sql_register_alias(s,p,'f',"request_file"); + log_sql_register_alias(s,p,'H',"request_protocol"); + log_sql_register_alias(s,p,'h',"remote_host"); + log_sql_register_alias(s,p,'I',"unique_id"); + log_sql_register_alias(s,p,'l',"remote_logname"); + log_sql_register_alias(s,p,'m',"request_method"); + log_sql_register_alias(s,p,'M',"machine_id"); + log_sql_register_alias(s,p,'P',"child_pid"); + log_sql_register_alias(s,p,'p',"server_port"); + log_sql_register_alias(s,p,'R',"referrer"); + log_sql_register_alias(s,p,'r',"request_line"); + log_sql_register_alias(s,p,'S',"timestamp"); + log_sql_register_alias(s,p,'s',"status"); + log_sql_register_alias(s,p,'T',"request_duration"); + log_sql_register_alias(s,p,'t',"request_time"); + log_sql_register_alias(s,p,'u',"remote_user"); + log_sql_register_alias(s,p,'U',"request_uri"); + log_sql_register_alias(s,p,'v',"virtual_host"); + log_sql_register_alias(s,p,'V',"server_name"); + + /* Register handlers */ + /** register_field(s,p, longname, funcalias, arg, + * sqlfieldname, DATATYPE, DATA LENGTH); */ + log_sql_register_field(p,"useragent", "useragent",NULL, + "agent", LOGSQL_DATATYPE_VARCHAR, 0); + log_sql_register_field(p,"request_args", "request_args",NULL, + "request_args",LOGSQL_DATATYPE_VARCHAR,0); + log_sql_register_field(p,"bytes_sent", "bytes_sent",NULL, + "bytes_sent",LOGSQL_DATATYPE_INT,0); + log_sql_register_field(p,"cookie", "cookie","Apache", + "cookie",LOGSQL_DATATYPE_VARCHAR,0); + log_sql_register_field(p,"request_file", "request_file",NULL, + "request_file",LOGSQL_DATATYPE_VARCHAR,0); + log_sql_register_field(p,"request_protocol", "request_protocol",NULL, + "request_protocol",LOGSQL_DATATYPE_VARCHAR,0); + log_sql_register_field(p,"remote_host", "remote_host",NULL, + "remote_host",LOGSQL_DATATYPE_VARCHAR,0); + log_sql_register_field(p,"unique_id", "unique_id",NULL, + "id",LOGSQL_DATATYPE_VARCHAR,0); + log_sql_register_field(p,"remote_logname", "remote_logname",NULL, + "remote_logname",LOGSQL_DATATYPE_VARCHAR,0); + log_sql_register_field(p,"request_method", "request_method",NULL, + "request_method",LOGSQL_DATATYPE_VARCHAR,0); + log_sql_register_field(p,"machine_id", "machine_id",NULL, + "machine_id",LOGSQL_DATATYPE_VARCHAR,0); + log_sql_register_field(p,"child_pid", "child_pid",NULL, + "child_pid",LOGSQL_DATATYPE_INT,0); + log_sql_register_field(p,"server_port", "server_port",NULL, + "server_port",LOGSQL_DATATYPE_INT,0); + log_sql_register_field(p,"referer", "referrer",NULL, + "referer",LOGSQL_DATATYPE_VARCHAR,0); + log_sql_register_field(p,"referrer", "referrer",NULL, + "referer",LOGSQL_DATATYPE_VARCHAR,0); + log_sql_register_field(p,"request_line", "request_line",NULL, + "request_line",LOGSQL_DATATYPE_VARCHAR,0); + log_sql_register_field(p,"timestamp", "timestamp",NULL, + "time_stamp",LOGSQL_DATATYPE_INT,0); + log_sql_register_field(p,"status", "status",NULL, + "status",LOGSQL_DATATYPE_INT,0); + log_sql_register_field(p,"request_duration", "request_duration",NULL, + "request_duration",LOGSQL_DATATYPE_INT,0); + log_sql_register_field(p,"request_time", "request_time",NULL, + "request_time",LOGSQL_DATATYPE_VARCHAR,0); + log_sql_register_field(p,"remote_user", "remote_user",NULL, + "remote_user",LOGSQL_DATATYPE_VARCHAR,0); + log_sql_register_field(p,"request_uri", "request_uri",NULL, + "request_uri",LOGSQL_DATATYPE_VARCHAR,0); + log_sql_register_field(p,"virtual_host", "virtual_host",NULL, + "virtual_host",LOGSQL_DATATYPE_VARCHAR,0); + log_sql_register_field(p,"server_name", "server_name",NULL, + "virtual_host",LOGSQL_DATATYPE_VARCHAR,0); + + log_sql_register_finish(s); + + if (global_config.announce) { + ap_add_version_component(p, PACKAGE_NAME"/"PACKAGE_VERSION); + } + global_config.db.p = p; + +#if defined(WITH_APACHE20) + return OK; +#endif +} + +/* This function handles calling the DB module, handling errors + * of missing tables and lost DB connections, and falling back to + * preserving the DB query. + * + * Parms: request record, table type, table name, and the full SQL command + */ + +static logsql_query_ret safe_sql_insert(request_rec *r, logsql_tabletype table_type, + const char *table_name, const char *query) { + + logsql_query_ret result; + logsql_state *cls = ap_get_module_config(r->server->module_config, + &log_sql_module); + + if (!global_config.db.connected || global_config.driver == NULL) { + /* preserve query */ + return LOGSQL_QUERY_NOLINK; + } + + result = global_config.driver->insert(r,&global_config.db,query); + + /* If we ran the query and it returned an error, try to be robust. + * (After all, the module thought it had a valid mysql_log connection but the query + * could have failed for a number of reasons, so we have to be extra-safe and check.) */ + switch (result) { + case LOGSQL_QUERY_SUCCESS: + return LOGSQL_QUERY_SUCCESS; + case LOGSQL_QUERY_NOLINK: + return LOGSQL_QUERY_FAIL; + /* TODO: What do we do here */ + case LOGSQL_QUERY_FAIL: + global_config.driver->disconnect(&global_config.db); + global_config.db.connected = 0; + /* re-open the connection and try again */ + if (log_sql_opendb_link(r->server) != LOGSQL_OPENDB_FAIL) { + log_error(APLOG_MARK,APLOG_NOTICE,0, r->server,"db reconnect successful"); +# if defined(WITH_APACHE20) + apr_sleep(apr_time_from_sec(0.25)); /* pause for a quarter second */ +# elif defined(WITH_APACHE13) +# if defined(WIN32) + Sleep((DWORD)0.25); +# else + { + struct timespec delay, remainder; + int nanoret; + delay.tv_sec = 0; + delay.tv_nsec = 250000000; /* pause for a quarter second */ + nanoret = nanosleep(&delay, &remainder); + if (nanoret && errno != EINTR) { + log_error(APLOG_MARK,APLOG_ERR, errno, r->server,"nanosleep unsuccessful"); + } + } +# endif /* win32 */ +# endif + result = global_config.driver->insert(r,&global_config.db,query); + if (result == LOGSQL_QUERY_SUCCESS) { + return LOGSQL_QUERY_SUCCESS; + } else { + log_error(APLOG_MARK,APLOG_ERR,0,r->server,"second attempt failed"); + preserve_entry(r, query); + return LOGSQL_QUERY_PRESERVED; + } + } else { + log_error(APLOG_MARK,APLOG_ERR,0,r->server, + "reconnect failed, unable to reach database. SQL logging stopped until child regains a db connection."); + log_error(APLOG_MARK,APLOG_ERR,0,r->server, + "log entries are being preserved in %s",cls->preserve_file); + preserve_entry(r, query); + return LOGSQL_QUERY_PRESERVED; + } + break; + case LOGSQL_QUERY_NOTABLE: + if (global_config.createtables) { + log_error(APLOG_MARK,APLOG_ERR,0,r->server, + "table doesn't exist...creating now"); + if ((result = global_config.driver->create_table(r, &global_config.db, table_type, + table_name))!=LOGSQL_TABLE_SUCCESS) { + log_error(APLOG_MARK,APLOG_ERR,result,r->server, + "child attempted but failed to create one or more tables for %s, preserving query", ap_get_server_name(r)); + preserve_entry(r, query); + return LOGSQL_QUERY_PRESERVED; + } else { + log_error(APLOG_MARK,APLOG_ERR,result, r->server, + "tables successfully created - retrying query"); + if ((result = global_config.driver->insert(r,&global_config.db,query))!=LOGSQL_QUERY_SUCCESS) { + log_error(APLOG_MARK,APLOG_ERR,result, r->server, + "giving up, preserving query"); + preserve_entry(r, query); + return LOGSQL_QUERY_PRESERVED; + } else { + log_error(APLOG_MARK,APLOG_NOTICE,0, r->server, + "query successful after table creation"); + return LOGSQL_QUERY_SUCCESS; + } + } + } else { + log_error(APLOG_MARK,APLOG_ERR,0,r->server, + "table doesn't exist, creation denied by configuration, preserving query"); + preserve_entry(r, query); + return LOGSQL_QUERY_PRESERVED; + } + break; + default: + log_error(APLOG_MARK,APLOG_ERR,0, r->server, + "Invalid return code from mog_log_query"); + return LOGSQL_QUERY_FAIL; + break; + } + return LOGSQL_QUERY_FAIL; +} + +/* This function gets called to create a per-server configuration + * record. It will always be called for the main server and + * for each virtual server that is established. Each server maintains + * its own state that is separate from the others' states. + * + * The return value is a pointer to the created module-specific + * structure. + */ +static void *log_sql_make_state(apr_pool_t *p, server_rec *s) +{ + logsql_state *cls = (logsql_state *) apr_pcalloc(p, sizeof(logsql_state)); + + /* These defaults are overridable in the httpd.conf file. */ + cls->transfer_log_format = apr_array_make(p, 1, sizeof(char *)); + cls->parsed_pool = p; + + cls->notes_table_name = DEFAULT_NOTES_TABLE_NAME; + cls->hin_table_name = DEFAULT_HIN_TABLE_NAME; + cls->hout_table_name = DEFAULT_HOUT_TABLE_NAME; + cls->cookie_table_name = DEFAULT_COOKIE_TABLE_NAME; + cls->preserve_file = DEFAULT_PRESERVE_FILE; + + cls->transfer_ignore_list = apr_array_make(p, 1, sizeof(char *)); + cls->transfer_accept_list = apr_array_make(p, 1, sizeof(char *)); + cls->remhost_ignore_list = apr_array_make(p, 1, sizeof(char *)); + cls->notes_list = apr_array_make(p, 1, sizeof(char *)); + cls->hin_list = apr_array_make(p, 1, sizeof(char *)); + cls->hout_list = apr_array_make(p, 1, sizeof(char *)); + cls->cookie_list = apr_array_make(p, 1, sizeof(char *)); + return (void *) cls; +} + + +/* Iterates through an array of char* and searches for a matching element + * Returns 0 if not found, 1 if found */ +static int in_array(apr_array_header_t *ary, const char *elem) +{ + int itr; + for (itr = 0; itr < ary->nelts; itr++) { + if (!strcmp(elem,((char **)ary->elts)[itr])) { + return 1; + } + } + return 0; +} + + +/* Parse through lists and merge based on +/- prefixes */ +static apr_array_header_t *do_merge_array(apr_array_header_t *parent, apr_array_header_t *child, apr_pool_t *p) +{ + apr_array_header_t *ret; + ret = apr_array_make(p, 1, sizeof(char *)); + if (apr_is_empty_array(child)) { + apr_array_cat(ret, parent); + } else { + apr_array_header_t *addlist, *dellist; + apr_pool_t *subp; + char **elem, **ptr = (char **)(child->elts); + int itr, overwrite = 0; + + apr_pool_create(&subp,p); + + addlist = apr_array_make(subp,5,sizeof(char *)); + dellist = apr_array_make(subp,5,sizeof(char *)); + + for (itr=0; itrnelts; itr++) { + if (*ptr[itr] == '+') { + elem = (char **)apr_array_push(addlist); + *elem = (ptr[itr]+1); + } else if (*ptr[itr] == '-') { + elem = (char **)apr_array_push(dellist); + *elem = (ptr[itr]+1); + } else { + overwrite = 1; + elem = (char **)apr_array_push(addlist); + *elem = ptr[itr]; + } + } + child = apr_array_make(p,1,sizeof(char *)); + ptr = (char **)(parent->elts); + if (overwrite==0) { + /* if we are not overwriting the existing then prepare for merge */ + for (itr=0; itrnelts; itr++) { + if (!in_array(addlist, ptr[itr]) && !in_array(dellist,ptr[itr])) { + elem = apr_array_push(ret); + *elem = apr_pstrdup(p, ptr[itr]); + } + } + } + apr_array_cat(ret, addlist); + apr_pool_destroy(subp); + } + return ret; +} + +static void *log_sql_merge_state(apr_pool_t *p, void *basev, void *addv) +{ + /* Fetch the two states to merge */ + logsql_state *parent = (logsql_state *) basev; + logsql_state *child = (logsql_state *) addv; + + /* Child can override these, otherwise they default to parent's choice. + * If the parent didn't set them, create reasonable defaults for the + * ones that should have such default settings. Leave the others null. */ + + /* No default for transfer_table_name because we want its absence + * to disable logging. */ + if (!child->transfer_table_name) { + child->transfer_table_name = parent->transfer_table_name; + } + + if (child->preserve_file == DEFAULT_PRESERVE_FILE) + child->preserve_file = parent->preserve_file; + /* server_root_relative the preserve file location */ + if (child->preserve_file == DEFAULT_PRESERVE_FILE) + child->preserve_file = ap_server_root_relative(p, DEFAULT_PRESERVE_FILE); + + if (child->notes_table_name == DEFAULT_NOTES_TABLE_NAME) + child->notes_table_name = parent->notes_table_name; + + if (child->hin_table_name == DEFAULT_HIN_TABLE_NAME) + child->hin_table_name = parent->hin_table_name; + + if (child->hout_table_name == DEFAULT_HOUT_TABLE_NAME) + child->hout_table_name = parent->hout_table_name; + + if (child->cookie_table_name == DEFAULT_COOKIE_TABLE_NAME) + child->cookie_table_name = parent->cookie_table_name; + + child->transfer_ignore_list = do_merge_array(parent->transfer_ignore_list, child->transfer_ignore_list, p); + child->transfer_accept_list = do_merge_array(parent->transfer_accept_list, child->transfer_accept_list, p); + child->remhost_ignore_list = do_merge_array(parent->remhost_ignore_list, child->remhost_ignore_list, p); + child->notes_list = do_merge_array(parent->notes_list, child->notes_list, p); + child->hin_list = do_merge_array(parent->hin_list, child->hin_list, p); + child->hout_list = do_merge_array(parent->hout_list, child->hout_list, p); + child->cookie_list = do_merge_array(parent->cookie_list,child->cookie_list, p); + + if (!child->cookie_name) + child->cookie_name = parent->cookie_name; + + + return (void*) child; +} + +/* Routine to perform the actual construction and execution of the relevant + * INSERT statements. + */ +static int log_sql_transaction(request_rec *orig) +{ + char **ptrptr, **ptrptr2; + logsql_state *cls = ap_get_module_config(orig->server->module_config, &log_sql_module); + const char *access_query; + request_rec *r; + const char *transfer_tablename = cls->transfer_table_name; + const char *notes_tablename = cls->notes_table_name; + const char *hout_tablename = cls->hout_table_name; + const char *hin_tablename = cls->hin_table_name; + const char *cookie_tablename = cls->cookie_table_name; + if (global_config.driver == NULL) { + return OK; + } + /* We handle mass virtual hosting differently. Dynamically determine the name + * of the table from the virtual server's name, and flag it for creation. + */ + if (global_config.massvirtual) { + /* TODO: Make these configurable? */ + char *access_base = "access_"; + char *notes_base = "notes_"; + char *hout_base = "headout_"; + char *hin_base = "headin_"; + char *cookie_base = "cookies_"; + + + /* Determine the hostname and convert it to all lower-case; */ + char *servername = apr_pstrdup(orig->pool,(char *)ap_get_server_name(orig)); + + char *p=servername; + while (*p) { + *p = apr_tolower(*p); + if (*p == '.') *p = '_'; + if (*p == '-') *p = '_'; + ++p; + } + + /* Find memory long enough to hold the table name + \0. */ + transfer_tablename = apr_pstrcat(orig->pool, access_base, servername, NULL); + notes_tablename = apr_pstrcat(orig->pool, notes_base, servername, NULL); + hin_tablename = apr_pstrcat(orig->pool, hin_base, servername, NULL); + hout_tablename = apr_pstrcat(orig->pool, hout_base, servername, NULL); + cookie_tablename = apr_pstrcat(orig->pool, cookie_base, servername, NULL); + + /* Tell this virtual server its transfer table name, and + * turn on create_tables, which is implied by massvirtual. + */ + + global_config.createtables = 1; + } + + /* Do we have enough info to log? */ + if (!transfer_tablename) { + return DECLINED; + } else { + const char *thehost; + const char *theitem; + char *fields = "", *values = ""; + char *itemsets = ""; + char *note_query = NULL; + char *hin_query = NULL; + char *hout_query = NULL; + char *cookie_query = NULL; + const char *unique_id; + const char *formatted_item; + int i, showcomma; + int proceed; + + for (r = orig; r->next; r = r->next) { + continue; + } + + /* The following is a stolen upsetting mess of pointers, I'm sorry. + * Anyone with the motiviation and/or the time should feel free + * to make this cleaner. :) */ + ptrptr2 = (char **) (cls->transfer_accept_list->elts + (cls->transfer_accept_list->nelts * cls->transfer_accept_list->elt_size)); + + /* Go through each element of the accept list and compare it to the + * request_uri. If we don't get a match, return without logging */ + if ((r->uri) && (cls->transfer_accept_list->nelts)) { + proceed = 0; + for (ptrptr = (char **) cls->transfer_accept_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->transfer_accept_list->elt_size)) + if (ap_strstr(r->uri, *ptrptr)) { + proceed = 1; + break; + } + if (!proceed) + return OK; + } + + /* Go through each element of the ignore list and compare it to the + * request_uri. If we get a match, return without logging */ + ptrptr2 = (char **) (cls->transfer_ignore_list->elts + (cls->transfer_ignore_list->nelts * cls->transfer_ignore_list->elt_size)); + if (r->uri) { + for (ptrptr = (char **) cls->transfer_ignore_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->transfer_ignore_list->elt_size)) + if (ap_strstr(r->uri, *ptrptr)) { + return OK; + } + } + + /* Go through each element of the ignore list and compare it to the + * remote host. If we get a match, return without logging */ + ptrptr2 = (char **) (cls->remhost_ignore_list->elts + (cls->remhost_ignore_list->nelts * cls->remhost_ignore_list->elt_size)); + thehost = ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME, NULL); + if (thehost) { + for (ptrptr = (char **) cls->remhost_ignore_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->remhost_ignore_list->elt_size)) + if (ap_strstr_c(thehost, *ptrptr)) { + return OK; + } + } + + + /* Iterate through the format characters and set up the INSERT string according to + * what the user has configured. */ + showcomma = 0; + for (i = 0; itransfer_log_format->nelts; i++) { + logsql_field *item = cls->parsed_log_format[i]; + if (item==NULL || item->func==NULL) { + log_error(APLOG_MARK, APLOG_ERR, 0, orig->server, + "Log Format '%s' unknown or incomplete",((char **)cls->transfer_log_format->elts)[i]); + continue; + } + + /* Yes, this key is one of the configured keys. + * Call the key's function and put the returned value into 'formatted_item' */ + formatted_item = item->func->func(item->func->want_orig_req ? orig : r, + item->param ? item->param : ""); + + /* Massage 'formatted_item' for proper SQL eligibility... */ + if (!formatted_item) { + formatted_item = ""; + } else if (formatted_item[0] == '-' && formatted_item[1] == '\0' && !item->string_contents) { + /* If apache tried to log a '-' character for a numeric field, convert that to a zero + * because the database expects a numeral and will reject the '-' character. */ + formatted_item = "0"; + } + + /* Append the fieldname and value-to-insert to the appropriate strings, quoting stringvals with ' as appropriate */ + fields = apr_pstrcat(r->pool, fields, (showcomma ? "," : ""), + item->sql_field_name, NULL); + values = apr_pstrcat(r->pool, values, (showcomma ? "," : ""), + global_config.driver->escape(r, formatted_item, r->pool,&global_config.db), NULL); + showcomma = 1; + } + + /* Work through the list of notes defined by LogSQLWhichNotes */ + i = 0; + unique_id = extract_unique_id(r, ""); + + ptrptr2 = (char **) (cls->notes_list->elts + (cls->notes_list->nelts * cls->notes_list->elt_size)); + for (ptrptr = (char **) cls->notes_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->notes_list->elt_size)) { + /* If the specified note (*ptrptr) exists for the current request... */ + if ((theitem = apr_table_get(r->notes, *ptrptr))) { + itemsets = apr_pstrcat(r->pool, itemsets, + (i > 0 ? "," : ""), + "(", + global_config.driver->escape(r, unique_id, r->pool, &global_config.db), + ",", + global_config.driver->escape(r, *ptrptr, r->pool,&global_config.db), + ",", + global_config.driver->escape(r, theitem, r->pool,&global_config.db), + ")", + NULL); + i++; + } + } + if ( *itemsets != '\0' ) { + note_query = apr_psprintf(r->pool, "insert %s into %s (id, item, val) values %s", + /*global_config.insertdelayed?"delayed":*/"", notes_tablename, itemsets); + + log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: note string: %s", note_query); + } + + /* Work through the list of headers-out defined by LogSQLWhichHeadersOut*/ + i = 0; + itemsets = ""; + + ptrptr2 = (char **) (cls->hout_list->elts + (cls->hout_list->nelts * cls->hout_list->elt_size)); + for (ptrptr = (char **) cls->hout_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->hout_list->elt_size)) { + /* If the specified header (*ptrptr) exists for the current request... */ + if ((theitem = apr_table_get(r->headers_out, *ptrptr))) { + itemsets = apr_pstrcat(r->pool, itemsets, + (i > 0 ? "," : ""), + "(", + global_config.driver->escape(r,unique_id, r->pool, &global_config.db), + ",", + global_config.driver->escape(r,*ptrptr, r->pool,&global_config.db), + ",", + global_config.driver->escape(r,theitem, r->pool,&global_config.db), + ")", + NULL); + i++; + } + } + if ( *itemsets != '\0' ) { + hout_query = apr_psprintf(r->pool, "insert %s into %s (id, item, val) values %s", + /*global_config.insertdelayed?"delayed":*/"", hout_tablename, itemsets); + + log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: header_out string: %s", hout_query); + } + + + /* Work through the list of headers-in defined by LogSQLWhichHeadersIn */ + i = 0; + itemsets = ""; + + ptrptr2 = (char **) (cls->hin_list->elts + (cls->hin_list->nelts * cls->hin_list->elt_size)); + for (ptrptr = (char **) cls->hin_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->hin_list->elt_size)) { + /* If the specified header (*ptrptr) exists for the current request... */ + if ((theitem = apr_table_get(r->headers_in, *ptrptr))) { + itemsets = apr_pstrcat(r->pool, itemsets, + (i > 0 ? "," : ""), + "(", + global_config.driver->escape(r,unique_id, r->pool, &global_config.db), + ",", + global_config.driver->escape(r,*ptrptr, r->pool,&global_config.db), + ",", + global_config.driver->escape(r,theitem, r->pool,&global_config.db), + ")", + NULL); + i++; + } + } + if ( *itemsets != '\0' ) { + hin_query = apr_psprintf(r->pool, "insert %s into %s (id, item, val) values %s", + /*global_config.insertdelayed?"delayed":*/"", hin_tablename, itemsets); + + log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: header_in string: %s", hin_query); + } + + + /* Work through the list of cookies defined by LogSQLWhichCookies */ + i = 0; + itemsets = ""; + + ptrptr2 = (char **) (cls->cookie_list->elts + (cls->cookie_list->nelts * cls->cookie_list->elt_size)); + for (ptrptr = (char **) cls->cookie_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->cookie_list->elt_size)) { + /* If the specified cookie (*ptrptr) exists for the current request... */ + if ( strncmp((theitem = extract_specific_cookie(r, *ptrptr)), "-", 1) ) { + itemsets = apr_pstrcat(r->pool, itemsets, + (i > 0 ? "," : ""), + "(", + global_config.driver->escape(r,unique_id, r->pool, &global_config.db), + ",", + global_config.driver->escape(r,*ptrptr, r->pool,&global_config.db), + ",", + global_config.driver->escape(r,theitem, r->pool,&global_config.db), + ")", + NULL); + i++; + } + + } + if ( *itemsets != '\0' ) { + cookie_query = apr_psprintf(r->pool, "insert %s into %s (id, item, val) values %s", + /*global_config.insertdelayed?"delayed":*/"", cookie_tablename, itemsets); + + log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: cookie string: %s", cookie_query); + } + + + /* Set up the actual INSERT statement */ + access_query = apr_psprintf(r->pool, "insert %s into %s (%s) values (%s)", + /*global_config.insertdelayed?"delayed":*/"", transfer_tablename, fields, values); + + log_error(APLOG_MARK,APLOG_DEBUG,0, r->server,"mod_log_sql: access string: %s", access_query); + + /* If the person activated force-preserve, go ahead and push all the entries + * into the preserve file, then return. + */ + if (global_config.forcepreserve) { + log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: preservation forced"); + preserve_entry(orig, access_query); + if ( note_query != NULL ) + preserve_entry(orig, note_query); + if ( hin_query != NULL ) + preserve_entry(orig, hin_query); + if ( hout_query != NULL ) + preserve_entry(orig, hout_query); + if ( cookie_query != NULL ) + preserve_entry(orig, cookie_query); + return OK; + } + + /* How's our mysql link integrity? */ + if (!global_config.db.connected) { + if (!global_config.forcepreserve) { + /* Make a try to establish the link */ + log_sql_opendb_link(r->server); + } + if (!global_config.db.connected) { + /* Unable to re-establish a DB link, so assume that it's really + * gone and send the entry to the preserve file instead. + * This short-circuits safe_sql_query() during a db outage and therefore + * we don't keep logging the db error over and over. + */ + preserve_entry(orig, access_query); + if ( note_query != NULL ) + preserve_entry(orig, note_query); + if ( hin_query != NULL ) + preserve_entry(orig, hin_query); + if ( hout_query != NULL ) + preserve_entry(orig, hout_query); + if ( cookie_query != NULL ) + preserve_entry(orig, cookie_query); + + return OK; + } else { + /* Whew, we got the DB link back */ + log_error(APLOG_MARK,APLOG_NOTICE,0, orig->server,"mod_log_sql: child established database connection"); + } + } + + + /* ---> So as of here we have a non-null value of mysql_log. <--- */ + /* ---> i.e. we have a good MySQL connection. <--- */ + + /* Make the access-table insert */ + safe_sql_insert(orig,LOGSQL_TABLE_ACCESS,transfer_tablename,access_query); + + /* Log the optional notes, headers, etc. */ + if (note_query) + safe_sql_insert(orig, LOGSQL_TABLE_NOTES,notes_tablename,note_query); + + if (hout_query) + safe_sql_insert(orig, LOGSQL_TABLE_HEADERSOUT,hout_tablename,hout_query); + + if (hin_query) + safe_sql_insert(orig, LOGSQL_TABLE_HEADERSIN,hin_tablename,hin_query); + + if (cookie_query) + safe_sql_insert(orig, LOGSQL_TABLE_COOKIES,cookie_tablename,cookie_query); + + return OK; + } +} + + +/* Setup of the available httpd.conf configuration commands. + * Structure: command, function called, NULL, where available, how many arguments, verbose description + */ +static const command_rec log_sql_cmds[] = { + AP_INIT_FLAG("LogSQLAnnounce", set_global_flag_slot, + (void *)APR_OFFSETOF(global_config_t, announce), RSRC_CONF, + "Whether to announce that mod_log_sql is loaded in the server header") + , + /* DB connection parameters */ + AP_INIT_TAKE13("LogSQLLoginInfo", set_log_sql_info, NULL, RSRC_CONF, + "The database connection URI in the form "driver://user:password@hostname:port/database"") + , + AP_INIT_TAKE2("LogSQLDBParam", set_dbparam, NULL, RSRC_CONF, + "First argument is the DB parameter, second is the value to assign") + , + AP_INIT_FLAG("LogSQLForcePreserve", set_global_flag_slot, + (void *)APR_OFFSETOF(global_config_t, forcepreserve), RSRC_CONF, + "Forces logging to preserve file and bypasses database") + , + AP_INIT_FLAG("LogSQLDisablePreserve", set_global_flag_slot, + (void *)APR_OFFSETOF(global_config_t, disablepreserve), RSRC_CONF, + "Completely disables use of the preserve file") + , + AP_INIT_TAKE1("LogSQLPreserveFile", set_server_file_slot, + (void *)APR_OFFSETOF(logsql_state,preserve_file), RSRC_CONF, + "Name of the file to use for data preservation during database downtime") + , + AP_INIT_FLAG("LogSQLCreateTables", set_global_nmv_flag_slot, + (void *)APR_OFFSETOF(global_config_t, createtables), RSRC_CONF, + "Turn on module's capability to create its SQL tables on the fly") + , + /* Table names */ + AP_INIT_FLAG("LogSQLMassVirtualHosting", set_global_flag_slot, + (void *)APR_OFFSETOF(global_config_t, massvirtual), RSRC_CONF, + "Activates option(s) useful for ISPs performing mass virutal hosting") + , + AP_INIT_TAKE1("LogSQLTransferLogTable", set_server_nmv_string_slot, + (void *)APR_OFFSETOF(logsql_state, transfer_table_name), RSRC_CONF, + "The database table that holds the transfer log") + , + AP_INIT_TAKE1("LogSQLNotesLogTable", set_server_nmv_string_slot, + (void *)APR_OFFSETOF(logsql_state, notes_table_name), RSRC_CONF, + "The database table that holds the notes") + , + AP_INIT_TAKE1("LogSQLHeadersOutLogTable", set_server_nmv_string_slot, + (void *)APR_OFFSETOF(logsql_state, hout_table_name), RSRC_CONF, + "The database table that holds the outbound headers") + , + AP_INIT_TAKE1("LogSQLHeadersInLogTable", set_server_nmv_string_slot, + (void *)APR_OFFSETOF(logsql_state, hin_table_name), RSRC_CONF, + "The database table that holds the inbound headers") + , + AP_INIT_TAKE1("LogSQLCookieLogTable", set_server_nmv_string_slot, + (void *)APR_OFFSETOF(logsql_state, cookie_table_name), RSRC_CONF, + "The database table that holds the cookie info") + , + /* New Log Format */ + AP_INIT_ITERATE("LogSQLTransferLogItems", add_server_string_slot, + (void *)APR_OFFSETOF(logsql_state, transfer_log_format), RSRC_CONF, + "What fields to log to the database transfer log") + , + AP_INIT_RAW_ARGS("LogSQLRegisterItem", set_register_field, + NULL, RSRC_CONF, + "Register a new Item for logging, Arguments: ItemName function argument sqlfield datatype datalen
" + "datatypes are INT, SMALLINT, VARCHAR, CHAR
") + , + AP_INIT_TAKE1("LogSQLShowConfig", set_global_string_slot, + (void *)APR_OFFSETOF(global_config_t, showconfig), RSRC_CONF, + "Add this to export the entire running function and dfield configuration to the named file") + , + /* Machine ID */ + AP_INIT_TAKE1("LogSQLMachineID", set_global_string_slot, + (void *)APR_OFFSETOF(global_config_t, machid), RSRC_CONF, + "Machine ID that the module will log, useful in web clusters to differentiate machines") + , + /* Limits on logging */ + AP_INIT_ITERATE("LogSQLRequestAccept", add_server_string_slot, + (void *)APR_OFFSETOF(logsql_state, transfer_accept_list), RSRC_CONF, + "List of URIs to accept for logging. Accesses that don't match will not be logged") + , + AP_INIT_ITERATE("LogSQLRequestIgnore", add_server_string_slot, + (void *)APR_OFFSETOF(logsql_state, transfer_ignore_list), RSRC_CONF, + "List of URIs to ignore. Accesses that match will not be logged to database") + , + AP_INIT_ITERATE("LogSQLRemhostIgnore", add_server_string_slot, + (void *)APR_OFFSETOF(logsql_state, remhost_ignore_list), RSRC_CONF, + "List of remote hosts to ignore. Accesses that match will not be logged to database") + , + /* Special logging table configuration */ + AP_INIT_TAKE1("LogSQLWhichCookie", set_server_string_slot, + (void *)APR_OFFSETOF(logsql_state, cookie_name), RSRC_CONF, + "The single cookie that you want logged in the access_log when using the 'c' config directive") + , + AP_INIT_ITERATE("LogSQLWhichNotes", add_server_string_slot, + (void *)APR_OFFSETOF(logsql_state, notes_list), RSRC_CONF, + "Notes that you would like to log in a separate table") + , + AP_INIT_ITERATE("LogSQLWhichHeadersOut", add_server_string_slot, + (void *)APR_OFFSETOF(logsql_state, hout_list), RSRC_CONF, + "Outbound headers that you would like to log in a separate table") + , + AP_INIT_ITERATE("LogSQLWhichHeadersIn", add_server_string_slot, + (void *)APR_OFFSETOF(logsql_state, hin_list), RSRC_CONF, + "Inbound headers that you would like to log in a separate table") + , + AP_INIT_ITERATE("LogSQLWhichCookies", add_server_string_slot, + (void *)APR_OFFSETOF(logsql_state, cookie_list), RSRC_CONF, + "The cookie(s) that you would like to log in a separate table") + , + AP_INIT_RAW_ARGS("LogSQLDeprecated", ap_set_deprecated, NULL, RSRC_CONF, + "
Deprecated
The following Commands are deprecated and should not be used..
Read the documentation for more information
Deprecated") + , + /* Deprecated commands */ + AP_INIT_TAKE1("LogSQLTransferLogFormat", set_logformat_slot, + (void *)APR_OFFSETOF(logsql_state, transfer_log_format), RSRC_CONF, + "(Deprecated) Use LogSQLTransferLogItem to specify symbolic log items instead") + , + AP_INIT_TAKE1("LogSQLDatabase", set_dbparam_slot, + (void *)"database", RSRC_CONF, + "(Deprecated) Use LogSQLDBParam database dbname. The name of the database database for logging") + , + AP_INIT_TAKE1("LogSQLTableType", set_dbparam_slot, + (void *)"tabletype", RSRC_CONF, + "(Deprecated) Use LogSQLDBParam tabletype type. What kind of table to create (MyISAM, InnoDB,...) when creating tables") + , + AP_INIT_TAKE1("LogSQLSocketFile", set_dbparam_slot, + (void *)"socketfile", RSRC_CONF, + "(Deprecated) Use LogSQLDBParam socketfile socket. Name of the file to employ for socket connections to database") + , + AP_INIT_TAKE1("LogSQLTCPPort", set_dbparam_slot, + (void *)"port", RSRC_CONF, + "(Deprecated) Use LogSQLDBParam port port. Port number to use for TCP connections to database, defaults to 3306 if not set") + , + {NULL} +}; +/* The configuration array that sets up the hooks into the module. */ +#if defined(WITH_APACHE20) +static void register_hooks(apr_pool_t *p) { + ap_hook_post_config(log_sql_post_config, NULL, NULL, APR_HOOK_REALLY_FIRST); + ap_hook_child_init(log_sql_child_init, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_log_transaction(log_sql_transaction, NULL, NULL, APR_HOOK_MIDDLE); +} + +module AP_MODULE_DECLARE_DATA log_sql_module = { + STANDARD20_MODULE_STUFF, + NULL, /* create per-directory config structures */ + NULL, /* merge per-directory config structures */ + log_sql_make_state, /* create per-server config structures */ + log_sql_merge_state, /* merge per-server config structures */ + log_sql_cmds, /* command handlers */ + register_hooks /* register hooks */ +}; +#elif defined(WITH_APACHE13) +module MODULE_VAR_EXPORT log_sql_module = { + STANDARD_MODULE_STUFF, + log_sql_module_init, /* module initializer */ + NULL, /* create per-dir config */ + NULL, /* merge per-dir config */ + log_sql_make_state, /* create server config */ + log_sql_merge_state, /* merge server config */ + log_sql_cmds, /* config directive table */ + NULL, /* [9] content handlers */ + NULL, /* [2] URI-to-filename translation */ + NULL, /* [5] check/validate user_id */ + NULL, /* [6] check authorization */ + NULL, /* [4] check access by host */ + NULL, /* [7] MIME type checker/setter */ + NULL, /* [8] fixups */ + log_sql_transaction, /* [10] logger */ + NULL /* [3] header parser */ +#if MODULE_MAGIC_NUMBER >= 19970728 /* 1.3-dev or later support these additionals... */ + ,log_sql_child_init, /* child process initializer */ + log_sql_child_exit, /* process exit/cleanup */ + NULL /* [1] post read-request */ +#endif + +}; +#endif diff --git a/src/mod_log_sql_dbd.c b/src/mod_log_sql_dbd.c new file mode 100644 index 0000000..c78a128 --- /dev/null +++ b/src/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/src/mod_log_sql_dbi.c b/src/mod_log_sql_dbi.c new file mode 100644 index 0000000..40a972b --- /dev/null +++ b/src/mod_log_sql_dbi.c @@ -0,0 +1,263 @@ +/* $Id: mod_log_sql_dbi.c 120 2004-04-17 15:14:12Z urkle@drip.ws $ */ + +#if defined(WITH_APACHE20) +# include "apache20.h" +#elif defined(WITH_APACHE13) +# include "apache13.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 "dbi/dbi.h" + +typedef struct { + dbi_conn conn; +} dbi_conn_rec; + +/* Connect to the MYSQL database */ +static logsql_opendb_ret log_sql_dbi_connect(server_rec *s, logsql_dbconnection *db) +{ + const char *driver = apr_table_get(db->parms,"driver"); + const char *host = apr_table_get(db->parms,"hostname"); + const char *user = apr_table_get(db->parms,"username"); + const char *passwd = apr_table_get(db->parms,"password"); + const char *database = apr_table_get(db->parms,"database"); + const char *s_tcpport = apr_table_get(db->parms,"port"); + unsigned int tcpport = (s_tcpport)?atoi(s_tcpport):0; + const char *socketfile = apr_table_get(db->parms,"socketfile"); + //dbi_result result; + dbi_conn_rec *dblink = db->handle; + if (!dblink) { + dblink = apr_pcalloc(db->p, sizeof(*dblink)); + db->handle = (void *)dblink; + } + + dblink->conn = dbi_conn_new(driver); + + dbi_conn_set_option(dblink->conn, "host", host); + dbi_conn_set_option(dblink->conn, "username", user); + dbi_conn_set_option(dblink->conn, "password", passwd); + dbi_conn_set_option(dblink->conn, "dbname", database); + if (tcpport) { + dbi_conn_set_option_numeric(dblink->conn, "port", tcpport); + } + + if (socketfile && !strcmp(driver,"mysql")) { + dbi_conn_set_option(dblink->conn, "mysql_unix_socket", socketfile); + } + + if (!dbi_conn_connect(dblink->conn)) { + log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + "HOST: '%s' PORT: '%d' DB: '%s' USER: '%s' SOCKET: '%s'", + host, tcpport, database, user, socketfile); + return LOGSQL_OPENDB_SUCCESS; + } else { + const char *error; + dbi_conn_error(dblink->conn, &error); + log_error(APLOG_MARK, APLOG_ERR, 0, s, + "DBI Error: %s", error); + log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + "HOST: '%s' PORT: '%d' DB: '%s' USER: '%s' SOCKET: '%s'", + host, tcpport, database, user, socketfile); + return LOGSQL_OPENDB_FAIL; + } +} + +/* Close the DB link */ +static void log_sql_dbi_close(logsql_dbconnection *db) +{ + dbi_conn_rec *dblink = db->handle; + dbi_conn_close(dblink->conn); + dblink->conn = NULL; +} + +/* Routine to escape the 'dangerous' characters that would otherwise + * corrupt the INSERT string: ', \, and " + */ +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; + + if (!from_str) + return NULL; + else { + char *to_str = strdup(from_str); + char *retval; + dbi_driver_quote_string(dbi_conn_get_driver(dblink->conn), &to_str); + retval = apr_pstrdup(p, to_str); + free(to_str); + return retval; + } +} + +/* Run a mysql insert query and return a categorized error or success */ +static logsql_query_ret log_sql_dbi_query(request_rec *r,logsql_dbconnection *db, + const char *query) +{ + const char *error; + dbi_result result; + dbi_conn_rec *dblink = db->handle; + + if (!dblink->conn) { + return LOGSQL_QUERY_NOLINK; + } + + /* Run the query */ + if ((result = dbi_conn_query(dblink->conn, query))) { + return LOGSQL_QUERY_SUCCESS; + } + /* Check to see if the error is "nonexistent table" */ + dbi_conn_error(dblink->conn, &error); + log_error(APLOG_MARK, APLOG_ERR, 0, r->server, + "DBI Error: %s", error); +/* if (real_error == ER_NO_SUCH_TABLE) { + log_error(APLOG_MARK,APLOG_ERR,0, r->server,"table does not exist, preserving query"); + return LOGSQL_QUERY_NOTABLE; + }*/ + return LOGSQL_QUERY_FAIL; +} + +/* Create table table_name of type table_type. */ +static logsql_table_ret log_sql_dbi_create(request_rec *r, logsql_dbconnection *db, + logsql_tabletype table_type, const char *table_name) +{ + dbi_result result; + const char *driver = apr_table_get(db->parms,"driver"); + const char *tabletype = apr_table_get(db->parms,"tabletype"); + char *type_suffix = NULL; + + char *create_prefix = "create table if not exists `"; + char *create_suffix = NULL; + char *create_sql; + + dbi_conn_rec *dblink = db->handle; + +/* if (!global_config.createtables) { + return APR_SUCCESS; + }*/ + + switch (table_type) { + case LOGSQL_TABLE_ACCESS: + create_suffix = + "` (id char(19),\ + agent varchar(255),\ + bytes_sent int unsigned,\ + child_pid smallint unsigned,\ + cookie varchar(255),\ + machine_id varchar(25),\ + request_file varchar(255),\ + referer varchar(255),\ + remote_host varchar(50),\ + remote_logname varchar(50),\ + remote_user varchar(50),\ + request_duration smallint unsigned,\ + request_line varchar(255),\ + request_method varchar(10),\ + request_protocol varchar(10),\ + request_time char(28),\ + request_uri varchar(255),\ + request_args varchar(255),\ + server_port smallint unsigned,\ + ssl_cipher varchar(25),\ + ssl_keysize smallint unsigned,\ + ssl_maxkeysize smallint unsigned,\ + status smallint unsigned,\ + time_stamp int unsigned,\ + virtual_host varchar(255))"; + break; + case LOGSQL_TABLE_COOKIES: + case LOGSQL_TABLE_HEADERSIN: + case LOGSQL_TABLE_HEADERSOUT: + case LOGSQL_TABLE_NOTES: + create_suffix = + "` (id char(19),\ + item varchar(80),\ + val varchar(80))"; + break; + } + + if (tabletype && !strcmp(driver,"mysql")) { + type_suffix = apr_pstrcat(r->pool, " TYPE=", + tabletype, NULL); + } + /* Find memory long enough to hold the whole CREATE string + \0 */ + create_sql = apr_pstrcat(r->pool, create_prefix, table_name, create_suffix, + type_suffix, NULL); + + log_error(APLOG_MARK,APLOG_DEBUG,0, r->server,"create string: %s", create_sql); + + if (!dblink) { + return LOGSQL_QUERY_NOLINK; + } + + /* Run the create query */ + if (!(result = dbi_conn_query(dblink, create_sql))) { + const char *error; + dbi_conn_error(dblink->conn, &error); + log_error(APLOG_MARK, APLOG_ERR, 0, r->server, + "DBI Error: %s", error); + return LOGSQL_TABLE_FAIL; + } + + return LOGSQL_TABLE_SUCCESS; +} + +static logsql_dbdriver log_sql_dbi_driver = { + "dbi", + NULL, + log_sql_dbi_connect, /* open DB connection */ + log_sql_dbi_close, /* close DB connection */ + log_sql_dbi_escape, /* escape query */ + log_sql_dbi_query, /* insert query */ + log_sql_dbi_create /* create table */ +}; + +static apr_status_t log_sql_dbi_cleanup(void *data) +{ + dbi_shutdown(); +#if defined(WITH_APACHE20) + return APR_SUCCESS; +#endif +} + +LOGSQL_REGISTER(dbi) { + dbi_driver driver; + const char **driver_list; + int count = 1; + + dbi_initialize(NULL); + + for (driver = dbi_driver_list(NULL); + driver; + driver = dbi_driver_list(driver)) { + count++; + } + driver_list = apr_pcalloc(p, sizeof(char *) * (count)); + count = 0; + for (driver = dbi_driver_list(NULL); + driver; + driver = dbi_driver_list(driver)) { + driver_list[count++] = dbi_driver_get_name(driver); + } + log_sql_dbi_driver.provided_drivers = driver_list; + log_sql_register_driver(p,&log_sql_dbi_driver); + apr_pool_cleanup_register(p, NULL, log_sql_dbi_cleanup, NULL); + LOGSQL_REGISTER_RETURN; +} diff --git a/src/mod_log_sql_logio.c b/src/mod_log_sql_logio.c new file mode 100644 index 0000000..ed69acf --- /dev/null +++ b/src/mod_log_sql_logio.c @@ -0,0 +1,146 @@ +/* $Id: mod_log_sql_ssl.c 140 2004-05-14 03:50:47Z 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 "http_connection.h" + +module AP_MODULE_DECLARE_DATA log_sql_logio_module; + +// From apachge 2.2's mod_logio.c to provide logging ACTUAL incoming and outgoing bytes +static const char logio_filter_name[] = "LOG_SQL_INPUT_OUTPUT"; + +typedef struct { + apr_off_t bytes_in; + apr_off_t bytes_out; +} logio_config_t; + +static void ap_logio_add_bytes_out(conn_rec *c, apr_off_t bytes){ + logio_config_t *cf = ap_get_module_config(c->conn_config, &log_sql_logio_module); + + cf->bytes_out += bytes; +} + +static const char *log_bytes_in(request_rec *r, char *a) +{ + logio_config_t *cf = ap_get_module_config(r->connection->conn_config, + &log_sql_logio_module); + + return apr_off_t_toa(r->pool, cf->bytes_in); +} + +static const char *log_bytes_out(request_rec *r, char *a) +{ + logio_config_t *cf = ap_get_module_config(r->connection->conn_config, + &log_sql_logio_module); + + return apr_off_t_toa(r->pool, cf->bytes_out); +} + +static int logio_transaction(request_rec *r) +{ + logio_config_t *cf = ap_get_module_config(r->connection->conn_config, + &log_sql_logio_module); + + cf->bytes_in = cf->bytes_out = 0; + + return OK; +} + +static apr_status_t logio_in_filter(ap_filter_t *f, + apr_bucket_brigade *bb, + ap_input_mode_t mode, + apr_read_type_e block, + apr_off_t readbytes) { + apr_off_t length; + apr_status_t status; + logio_config_t *cf = ap_get_module_config(f->c->conn_config, &log_sql_logio_module); + + status = ap_get_brigade(f->next, bb, mode, block, readbytes); + + apr_brigade_length (bb, 0, &length); + + if (length > 0) + cf->bytes_in += length; + + return status; +} + +static apr_status_t logio_out_filter(ap_filter_t *f, + apr_bucket_brigade *bb) { + apr_bucket *b = APR_BRIGADE_LAST(bb); + + /* End of data, make sure we flush */ + if (APR_BUCKET_IS_EOS(b)) { + APR_BUCKET_INSERT_BEFORE(b, + apr_bucket_flush_create(f->c->bucket_alloc)); + } + + return ap_pass_brigade(f->next, bb); +} + +static int logio_pre_conn(conn_rec *c, void *csd) { + logio_config_t *cf = apr_pcalloc(c->pool, sizeof(logio_config_t)); + + ap_set_module_config(c->conn_config, &log_sql_logio_module, cf); + + ap_add_input_filter(logio_filter_name, NULL, NULL, c); + ap_add_output_filter(logio_filter_name, NULL, NULL, c); + + return OK; +} + +static int post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) +{ + log_sql_register_function(p, "bytes_in", log_bytes_in, LOGSQL_FUNCTION_REQ_FINAL); + log_sql_register_function(p, "bytes_out", log_bytes_out, LOGSQL_FUNCTION_REQ_FINAL); + + log_sql_register_alias(s,p,'i', "bytes_in"); + log_sql_register_alias(s,p,'o', "bytes_out"); + + log_sql_register_field(p, "bytes_in", "bytes_in", NULL, + "bytes_in", LOGSQL_DATATYPE_INT, 0); + log_sql_register_field(p, "bytes_out", "bytes_out", NULL, + "bytes_out", LOGSQL_DATATYPE_INT, 0); + + log_sql_register_finish(s); + return OK; +} + +static void register_hooks(apr_pool_t *p) { + static const char *pre[] = { "mod_log_sql.c", NULL }; + + ap_hook_pre_connection(logio_pre_conn, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_log_transaction(logio_transaction, pre, NULL, APR_HOOK_MIDDLE); + ap_hook_post_config(post_config, NULL, NULL, APR_HOOK_REALLY_FIRST); + + ap_register_input_filter(logio_filter_name, logio_in_filter, NULL, + AP_FTYPE_NETWORK - 1); + ap_register_output_filter(logio_filter_name, logio_out_filter, NULL, + AP_FTYPE_NETWORK - 1); + + APR_REGISTER_OPTIONAL_FN(ap_logio_add_bytes_out); +} + +module AP_MODULE_DECLARE_DATA log_sql_logio_module = { + STANDARD20_MODULE_STUFF, + NULL, NULL, NULL, NULL, NULL, register_hooks +}; diff --git a/src/mod_log_sql_mysql.c b/src/mod_log_sql_mysql.c new file mode 100644 index 0000000..942c03a --- /dev/null +++ b/src/mod_log_sql_mysql.c @@ -0,0 +1,269 @@ +/* $Id$ */ + +#if defined(WITH_APACHE20) +# include "apache20.h" +#elif defined(WITH_APACHE13) +# include "apache13.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 "mysql.h" +#include "mysqld_error.h" + +/* The enduser won't modify these */ +#define MYSQL_ERROR(mysql) ((mysql)?(mysql_error(mysql)):"MySQL server has gone away") + +/* Connect to the MYSQL database */ +static logsql_opendb_ret log_sql_mysql_connect(server_rec *s, logsql_dbconnection *db) +{ + const char *host = apr_table_get(db->parms,"hostname"); + const char *user = apr_table_get(db->parms,"username"); + const char *passwd = apr_table_get(db->parms,"password"); + const char *database = apr_table_get(db->parms,"database"); + const char *s_tcpport = apr_table_get(db->parms,"port"); + unsigned int tcpport = (s_tcpport)?atoi(s_tcpport):3306; + const char *socketfile = apr_table_get(db->parms,"socketfile"); + MYSQL *dblink = db->handle; + + dblink = mysql_init(dblink); + db->handle = (void *)dblink; + + + if (!socketfile) { + socketfile = "/var/lib/mysql/mysql.sock"; + } + + if (mysql_real_connect(dblink, host, user, passwd, database, tcpport, + socketfile, 0)) { + log_error(APLOG_MARK,APLOG_DEBUG,0, s,"HOST: '%s' PORT: '%d' DB: '%s' USER: '%s' SOCKET: '%s'", + host, tcpport, database, user, socketfile); + return LOGSQL_OPENDB_SUCCESS; + } else { + log_error(APLOG_MARK,APLOG_ERR,0, s,"mod_log_sql_mysql: database connection error: mysql error: %s", + MYSQL_ERROR(dblink)); + log_error(APLOG_MARK,APLOG_DEBUG, 0, s,"HOST: '%s' PORT: '%d' DB: '%s' USER: '%s' SOCKET: '%s'", + host, tcpport, database, user, socketfile); + return LOGSQL_OPENDB_FAIL; + } +} + +/* Close the DB link */ +static void log_sql_mysql_close(logsql_dbconnection *db) +{ + mysql_close((MYSQL *)db->handle); + /* mysql_close frees this data so NULL it out incase we reconnect later */ + db->handle=NULL; +} + +/* Routine to escape the 'dangerous' characters that would otherwise + * corrupt the INSERT string: ', \, and " + */ +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 */ + if (!from_str || strlen(from_str) == 0) + return "NULL"; + else { + char *to_str; + unsigned long length = strlen(from_str); + unsigned long retval; + + /* Pre-allocate a new string that could hold twice the original, which would only + * happen if the whole original string was 'dangerous' characters. + */ + to_str = (char *) apr_palloc(p, length * 2 + 3); + if (!to_str) { + return from_str; + } + strcpy(to_str, "'"); + if (!db->connected) { + /* Well, I would have liked to use the current database charset. mysql is + * unavailable, however, so I fall back to the slightly less respectful + * mysql_escape_string() function that uses the default charset. + */ + retval = mysql_escape_string(to_str+1, from_str, length); + } else { + /* MySQL is available, so I'll go ahead and respect the current charset when + * I perform the escape. + */ + retval = mysql_real_escape_string((MYSQL *)db->handle, to_str+1, from_str, length); + } + strcat(to_str,"'"); + + if (retval) + return to_str; + else + return from_str; + } +} + +#if defined(WIN32) +#define SIGNAL_GRAB +#define SIGNAL_RELEASE +#define SIGNAL_VAR +#else +#define SIGNAL_VAR void (*handler) (int); +#define SIGNAL_GRAB handler = signal(SIGPIPE, SIG_IGN); +#define SIGNAL_RELEASE signal(SIGPIPE, handler); +#endif +/* Run a mysql insert query and return a categorized error or success */ +static logsql_query_ret log_sql_mysql_query(request_rec *r,logsql_dbconnection *db, + const char *query) +{ + int retval; + SIGNAL_VAR + + unsigned int real_error = 0; + /*const char *real_error_str = NULL;*/ + + MYSQL *dblink = (MYSQL *)db->handle; + + if (!dblink) { + return LOGSQL_QUERY_NOLINK; + } + + /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */ + SIGNAL_GRAB + + /* Run the query */ + if (!(retval = mysql_query(dblink, query))) { + SIGNAL_RELEASE + return LOGSQL_QUERY_SUCCESS; + } + real_error = mysql_errno(dblink); + log_error(APLOG_MARK, APLOG_ERR, 0, r->server, + "mysql_query returned (%d) \"%s\"", real_error, MYSQL_ERROR(dblink)); + /* Check to see if the error is "nonexistent table" */ + + if (real_error == ER_NO_SUCH_TABLE) { + log_error(APLOG_MARK,APLOG_ERR,0, r->server,"table does not exist, preserving query"); + /* Restore SIGPIPE to its original handler function */ + SIGNAL_RELEASE + return LOGSQL_QUERY_NOTABLE; + } + + /* Restore SIGPIPE to its original handler function */ + SIGNAL_RELEASE + return LOGSQL_QUERY_FAIL; +} + +/* Create table table_name of type table_type. */ +static logsql_table_ret log_sql_mysql_create(request_rec *r, logsql_dbconnection *db, + logsql_tabletype table_type, const char *table_name) +{ + int retval; + const char *tabletype = apr_table_get(db->parms,"tabletype"); + SIGNAL_VAR + char *type_suffix = NULL; + + char *create_prefix = "create table if not exists `"; + char *create_suffix = NULL; + char *create_sql; + + MYSQL *dblink = (MYSQL *)db->handle; + +/* if (!global_config.createtables) { + return APR_SUCCESS; + }*/ + + switch (table_type) { + case LOGSQL_TABLE_ACCESS: + create_suffix = + "` (id char(19),\ + agent varchar(255),\ + bytes_sent int unsigned,\ + child_pid smallint unsigned,\ + cookie varchar(255),\ + machine_id varchar(25),\ + request_file varchar(255),\ + referer varchar(255),\ + remote_host varchar(50),\ + remote_logname varchar(50),\ + remote_user varchar(50),\ + request_duration smallint unsigned,\ + request_line varchar(255),\ + request_method varchar(10),\ + request_protocol varchar(10),\ + request_time char(28),\ + request_uri varchar(255),\ + request_args varchar(255),\ + server_port smallint unsigned,\ + ssl_cipher varchar(25),\ + ssl_keysize smallint unsigned,\ + ssl_maxkeysize smallint unsigned,\ + status smallint unsigned,\ + time_stamp int unsigned,\ + virtual_host varchar(255),\ + bytes_in int unsigned,\ + bytes_out int unsigned)"; + break; + case LOGSQL_TABLE_COOKIES: + case LOGSQL_TABLE_HEADERSIN: + case LOGSQL_TABLE_HEADERSOUT: + case LOGSQL_TABLE_NOTES: + create_suffix = + "` (id char(19),\ + item varchar(80),\ + val varchar(80))"; + break; + } + + if (tabletype) { + type_suffix = apr_pstrcat(r->pool, " TYPE=", + tabletype, NULL); + } + /* Find memory long enough to hold the whole CREATE string + \0 */ + create_sql = apr_pstrcat(r->pool, create_prefix, table_name, create_suffix, + type_suffix, NULL); + + log_error(APLOG_MARK,APLOG_DEBUG,0, r->server,"create string: %s", create_sql); + + if (!dblink) { + return LOGSQL_QUERY_NOLINK; + } + /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */ + SIGNAL_GRAB + + /* Run the create query */ + if ((retval = mysql_query(dblink, create_sql))) { + log_error(APLOG_MARK,APLOG_ERR,0, r->server,"failed to create table: %s", + table_name); + SIGNAL_RELEASE + return LOGSQL_TABLE_FAIL; + } + SIGNAL_RELEASE + return LOGSQL_TABLE_SUCCESS; +} + +static const char *supported_drivers[] = {"mysql",NULL}; +static logsql_dbdriver mysql_driver = { + "mysql", + supported_drivers, + log_sql_mysql_connect, /* open DB connection */ + log_sql_mysql_close, /* close DB connection */ + log_sql_mysql_escape, /* escape query */ + log_sql_mysql_query, /* insert query */ + log_sql_mysql_create /* create table */ +}; + +LOGSQL_REGISTER(mysql) { + log_sql_register_driver(p,&mysql_driver); + LOGSQL_REGISTER_RETURN; +} diff --git a/src/mod_log_sql_pgsql.c b/src/mod_log_sql_pgsql.c new file mode 100644 index 0000000..4e12920 --- /dev/null +++ b/src/mod_log_sql_pgsql.c @@ -0,0 +1,247 @@ +/* $Id$ */ + +#if defined(WITH_APACHE20) +# include "apache20.h" +#elif defined(WITH_APACHE13) +# include "apache13.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 "libpq-fe.h" + +/* Connect to the PGSQL database */ +static logsql_opendb_ret log_sql_pgsql_connect(server_rec *s, logsql_dbconnection *db) +{ + const char *host = apr_table_get(db->parms,"hostname"); + const char *user = apr_table_get(db->parms,"username"); + const char *passwd = apr_table_get(db->parms,"password"); + const char *database = apr_table_get(db->parms,"database"); + const char *s_tcpport = apr_table_get(db->parms,"port"); + + db->handle = PQsetdbLogin(host, s_tcpport, NULL, NULL, database, user, passwd); + + if (PQstatus(db->handle) == CONNECTION_OK) { + log_error(APLOG_MARK,APLOG_DEBUG,0, s,"HOST: '%s' PORT: '%s' DB: '%s' USER: '%s'", + host, s_tcpport, database, user); + return LOGSQL_OPENDB_SUCCESS; + } else { + log_error(APLOG_MARK,APLOG_DEBUG,0, s,"mod_log_sql: database connection error: %s", + PQerrorMessage(db->handle)); + log_error(APLOG_MARK,APLOG_DEBUG, 0, s,"HOST: '%s' PORT: '%s' DB: '%s' USER: '%s'", + host, s_tcpport, database, user); + return LOGSQL_OPENDB_FAIL; + } +} + +/* Close the DB link */ +static void log_sql_pgsql_close(logsql_dbconnection *db) +{ + PQfinish((PGconn*)(db->handle)); +} + +/* Routine to escape the 'dangerous' characters that would otherwise + * corrupt the INSERT string: ', \, and " + * Also PQescapeString does not place the ' around the string. So we have + * to do this manually + */ +static const char *log_sql_pgsql_escape(const char *from_str, apr_pool_t *p, + logsql_dbconnection *db) +{ + char *temp; + if (!from_str) + return NULL; + else { + char *to_str; + unsigned long length = strlen(from_str); + unsigned long retval; + + /* Pre-allocate a new string that could hold twice the original, which would only + * happen if the whole original string was 'dangerous' characters. + * And forsee the space for the 2 ' + */ + temp = to_str = (char *) apr_palloc(p, length * 2 + 3); + if (!to_str) { + return from_str; + } + + *temp = '\''; + temp++; + + retval = PQescapeString(temp, from_str, length); + + /* avoid the string to be tolong for the sql database*/ + if (retval > 250) retval = 250; + + *(temp+retval) = '\''; + *(temp+retval+1) = '\0'; + + /* We must always return the to_str, because we always need the ' added */ +// if (retval) + return to_str; +// else +// return from_str; + } +} + +/* Run a sql insert query and return a categorized error or success */ +static logsql_query_ret log_sql_pgsql_query(request_rec *r,logsql_dbconnection *db, + const char *query) +{ + PGresult *result; + void (*handler) (int); + unsigned int real_error = 0; + /*const char *real_error_str = NULL;*/ + + PGconn *conn = db->handle; + + if (PQstatus(conn) != CONNECTION_OK) { + return LOGSQL_QUERY_NOLINK; + } + /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */ + /* Does postgresql do this also ??? */ + handler = signal(SIGPIPE, SIG_IGN); + + result = PQexec(conn, query); + /* Run the query */ + if (PQresultStatus(result) == PGRES_COMMAND_OK) { + signal(SIGPIPE, handler); + PQclear(result); + return LOGSQL_QUERY_SUCCESS; + } + /* Check to see if the error is "nonexistent table" */ + /* removed ... don't know how ! (sorry) + real_error = mysql_errno(dblink); + + if (real_error == ER_NO_SUCH_TABLE) { + log_error(APLOG_MARK,APLOG_ERR,0, r->server,"table does not exist, preserving query"); + signal(SIGPIPE, handler); + PQclear(result); + return LOGSQL_QUERY_NOTABLE; + }*/ + + /* Restore SIGPIPE to its original handler function */ + signal(SIGPIPE, handler); + PQclear(result); + return LOGSQL_QUERY_FAIL; +} + +/* Create table table_name of type table_type. */ +static logsql_table_ret log_sql_pgsql_create(request_rec *r, logsql_dbconnection *db, + logsql_tabletype table_type, const char *table_name) +{ + PGresult *result; + const char *tabletype = apr_table_get(db->parms,"tabletype"); + void (*handler) (int); + char *type_suffix = NULL; + + char *create_prefix = "create table if not exists `"; + char *create_suffix = NULL; + char *create_sql; + + PGconn *conn = db->handle; + +/* if (!global_config.createtables) { + return APR_SUCCESS; + }*/ + + switch (table_type) { + case LOGSQL_TABLE_ACCESS: + create_suffix = + "` (id char(19),\ + agent varchar(255),\ + bytes_sent int unsigned,\ + child_pid smallint unsigned,\ + cookie varchar(255),\ + machine_id varchar(25),\ + request_file varchar(255),\ + referer varchar(255),\ + remote_host varchar(50),\ + remote_logname varchar(50),\ + remote_user varchar(50),\ + request_duration smallint unsigned,\ + request_line varchar(255),\ + request_method varchar(10),\ + request_protocol varchar(10),\ + request_time char(28),\ + request_uri varchar(255),\ + request_args varchar(255),\ + server_port smallint unsigned,\ + ssl_cipher varchar(25),\ + ssl_keysize smallint unsigned,\ + ssl_maxkeysize smallint unsigned,\ + status smallint unsigned,\ + time_stamp int unsigned,\ + virtual_host varchar(255))"; + break; + case LOGSQL_TABLE_COOKIES: + case LOGSQL_TABLE_HEADERSIN: + case LOGSQL_TABLE_HEADERSOUT: + case LOGSQL_TABLE_NOTES: + create_suffix = + "` (id char(19),\ + item varchar(80),\ + val varchar(80))"; + break; + } + + if (tabletype) { + type_suffix = apr_pstrcat(r->pool, " TYPE=", + tabletype, NULL); + } + /* Find memory long enough to hold the whole CREATE string + \0 */ + create_sql = apr_pstrcat(r->pool, create_prefix, table_name, create_suffix, + type_suffix, NULL); + + log_error(APLOG_MARK,APLOG_DEBUG,0, r->server,"create string: %s", create_sql); + + if (PQstatus(conn) != CONNECTION_OK) { + return LOGSQL_QUERY_NOLINK; + } + /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */ + handler = signal(SIGPIPE, SIG_IGN); + + /* Run the create query */ + result = PQexec(conn, create_sql); + if (PQresultStatus(result) != PGRES_COMMAND_OK) { + log_error(APLOG_MARK,APLOG_ERR,0, r->server,"failed to create table: %s", + table_name); + signal(SIGPIPE, handler); + PQclear(result); + return LOGSQL_TABLE_FAIL; + } + signal(SIGPIPE, handler); + PQclear(result); + return LOGSQL_TABLE_SUCCESS; +} + +static char *supported_drivers[] = {"pgsql",NULL}; +static logsql_dbdriver pgsql_driver = { + supported_drivers, + log_sql_pgsql_connect, /* open DB connection */ + log_sql_pgsql_close, /* close DB connection */ + log_sql_pgsql_escape, /* escape query */ + log_sql_pgsql_query, /* insert query */ + log_sql_pgsql_create /* create table */ +}; + +LOGSQL_REGISTER(pgsql) { + log_sql_register_driver(p,&pgsql_driver); + LOGSQL_REGISTER_RETURN; +} diff --git a/src/mod_log_sql_ssl.c b/src/mod_log_sql_ssl.c new file mode 100644 index 0000000..47bba8b --- /dev/null +++ b/src/mod_log_sql_ssl.c @@ -0,0 +1,106 @@ +/* $Id$ */ + +#if defined(WITH_APACHE20) +# include "apache20.h" +#elif defined(WITH_APACHE13) +# include "apache13.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 "mod_ssl.h" + +#if defined(WITH_APACHE20) +static APR_OPTIONAL_FN_TYPE(ssl_var_lookup) *header_ssl_lookup = NULL; +# define TEST_SSL(r) header_ssl_lookup +#elif defined(WITH_APACHE13) +# define TEST_SSL(r) ap_ctx_get(r->connection->client->ctx, "ssl") +# define header_ssl_lookup ssl_var_lookup +#endif + +static const char *extract_ssl_keysize(request_rec *r, char *a) +{ + char *result = NULL; + if (TEST_SSL(r) != NULL) + { + result = header_ssl_lookup(r->pool, r->server, r->connection, r, "SSL_CIPHER_USEKEYSIZE"); + log_error(APLOG_MARK,APLOG_DEBUG,0, r->server,"SSL_KEYSIZE: %s", result); + if (result && result[0]) + return result; + else + return "0"; + } else { + return "0"; + } +} + +static const char *extract_ssl_maxkeysize(request_rec *r, char *a) +{ + char *result = NULL; + if (TEST_SSL(r) != NULL) + { + result = header_ssl_lookup(r->pool, r->server, r->connection, r, "SSL_CIPHER_ALGKEYSIZE"); + log_error(APLOG_MARK,APLOG_DEBUG,0, r->server,"SSL_ALGKEYSIZE: %s", result); + if (result && result[0]) + return result; + else + return "0"; + } else { + return "0"; + } +} + +static const char *extract_ssl_cipher(request_rec *r, char *a) +{ + char *result = NULL; + if (TEST_SSL(r) != NULL) + { + result = header_ssl_lookup(r->pool, r->server, r->connection, r, "SSL_CIPHER"); + log_error(APLOG_MARK,APLOG_DEBUG,0, r->server,"SSL_CIPHER: %s", result); + if (result && result[0]) + return result; + else + return "0"; + } else { + return "-"; + } +} + + +LOGSQL_REGISTER(ssl) +{ + log_sql_register_function(p, "ssl_keysize", extract_ssl_keysize, LOGSQL_FUNCTION_REQ_FINAL); + log_sql_register_function(p, "ssl_maxkeysize", extract_ssl_maxkeysize, LOGSQL_FUNCTION_REQ_FINAL); + log_sql_register_function(p, "ssl_cipher", extract_ssl_cipher, LOGSQL_FUNCTION_REQ_FINAL); + + log_sql_register_alias(s,p,'q', "ssl_keysize"); + log_sql_register_alias(s,p,'Q', "ssl_maxkeysize"); + log_sql_register_alias(s,p,'z', "ssl_cipher"); + + log_sql_register_field(p, "ssl_keysize", "ssl_keysize", NULL, + "ssl_keysize", LOGSQL_DATATYPE_VARCHAR, 0); + log_sql_register_field(p, "ssl_maxkeysize", "ssl_maxkeysize", NULL, + "ssl_maxkeysize", LOGSQL_DATATYPE_VARCHAR, 0); + log_sql_register_field(p, "ssl_cipher", "ssl_cipher", NULL, + "ssl_cipher", LOGSQL_DATATYPE_VARCHAR, 0); + +#if defined(WITH_APACHE20) + header_ssl_lookup = APR_RETRIEVE_OPTIONAL_FN(ssl_var_lookup); +#endif + LOGSQL_REGISTER_RETURN; +} diff --git a/winconfig.h b/winconfig.h deleted file mode 100644 index 702c35f..0000000 --- a/winconfig.h +++ /dev/null @@ -1,78 +0,0 @@ -/* config.h. Generated by configure. */ -/* config.h.in. Generated from configure.ac by autoheader. */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_INTTYPES_H */ - -/* Define to 1 if you have the `m' library (-lm). */ -/* #undef HAVE_LIBM */ - -/* Define to 1 if you have the `mysqlclient' library (-lmysqlclient). */ -#define HAVE_LIBMYSQLCLIENT 1 - -/* Define to 1 if you have the `z' library (-lz). */ -/* #undef HAVE_LIBZ */ - -/* Define to 1 if you have the header file. */ -#define HAVE_LIMITS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MOD_SSL_H */ - -/* Define to 1 if you have the `mysql_real_escape_string' function. */ -#define HAVE_MYSQL_REAL_ESCAPE_STRING 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STDINT_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STDLIB_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STRINGS_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STRING_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_STAT_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_TYPES_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_UNISTD_H */ - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "mod_log_sql" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "mod_log_sql 1.100" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "mod-log-sql" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "1.100" - -/* Define to 1 if you have the ANSI C header files. */ -/* #undef STDC_HEADERS */ - -/* Define if we want to compile in SSL support. */ -/* #undef WANT_SSL_LOGGING */ - -/* Define to 1 if we are compiling with Apache 1.3.x */ -/* #undef WITH_APACHE13 */ - -/* Define to 1 if we are compiling with Apache 2.0.x */ -/* #undef WITH_APACHE20 */ - -/* Define to 1 if we are compiling with mysql */ -#define WITH_MYSQL 1 - -- cgit