From ab1ac8ba7570005c169e7aa772762b55d354e07d Mon Sep 17 00:00:00 2001 From: Edward Rudd Date: Tue, 23 Dec 2003 19:49:56 +0000 Subject: update autoconf scripts to check MySQL.. moved autoconf DEFUN macros to m4 subdirectory autogen.sh calls aclocal to include m4 directory. merged in changes from 1.19b1 fixed log_sql_merge_config bug in 1.19b1 release 1.91 --- CHANGELOG | 44 ++++- Documentation/documentation.lyx | 353 +++++++++++++++++++++++++++++----------- Makefile.in | 4 +- aclocal.m4 | 128 --------------- autogen.sh | 6 +- configure.ac | 7 +- create_tables.sql | 2 +- m4/apache.m4 | 128 +++++++++++++++ m4/mysql.m4 | 64 ++++++++ mod_log_sql.c | 220 ++++++++++++++++--------- 10 files changed, 648 insertions(+), 308 deletions(-) delete mode 100644 aclocal.m4 create mode 100644 m4/apache.m4 create mode 100644 m4/mysql.m4 diff --git a/CHANGELOG b/CHANGELOG index de34ba1..9769044 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,23 +1,59 @@ -$Id: CHANGELOG,v 1.2 2003/12/22 04:45:38 urkle Exp $ +$Id: CHANGELOG,v 1.3 2003/12/23 19:49:55 urkle Exp $ TODO: -* Rethink documentation flow and rewrite? * Port connection portion to other DBMS? Genericize the module? Start with PostgreSQL. (provider mechanism, and libDBI) -* merge server config into vh config * does determining table name in massvirtual mode upon every request cause performance degradation? If so fix. * LogSQLRotateLogs directive with daily/monthly/weekly/etc. * new format char: IP as bigint? ( not w/ ipV6 ) * socket-based middleman daemon with configurable conns, or connect/disconnect. * ignore by cookie +* tools to import logs into SQL +* Directive to yes/no create ancillary tables (or just access table) +* break module into separate code files + separate DB implimentation into sub-modules via provider mechanism +* add document building to Makefile.in +* backport patch for apache 1.3 CHANGES: -1.90: ? +1.91: 2003-12-23 +* Added checks for MySQL to autoconf +* fixed merge code to work correctly. +* Merged in 1.19b1 changes +* Hostnames are now converted to lowercase in the mass-virtual naming section. + The loop that converts dots to underscores has been optimized as well. +* New directive LogSQLTableType allows one to specify the kind of table that + the module makes during table creation (e.g. InnoDB, MyISAM). Thanks to Jim + Turner for the suggestion and patch. If your MySQL server does not support + the specified type, it will create a MyISAM table instead. +* Directives can now be placed in the 'main' server config and will be + inherited by the virtual hosts. This means a LOT less repetition: you only + specify the item once to have it inherited, but it can still be overridden + on a virtualhost level. These can be specified in this manner: + + LogSQLTransferLogTable + LogSQLTransferLogFormat + LogSQLPreserveFile + LogSQLNotesLogTable + LogSQLHeadersInLogTable + LogSQLHeadersOutLogTable + LogSQLCookieLogTable + LogSQLRemhostIgnore + LogSQLRequestIgnore + LogSQLRequestAccept + LogSQLWhichNotes + LogSQLWhichHeadersOut + LogSQLWhichHeadersIn + LogSQLWhichCookies + LogSQLWhichCookie + +1.90: 2003-12-22 * updated code to compile under apache 2.0 * rewrote and consolidate configuration handler routines * made all functions static. * made delayed insert configurable, instead of compile time +* moved to my autoconfigure support 1.18: * Delayed inserts (a MySQL extension) are now available at compile-time. diff --git a/Documentation/documentation.lyx b/Documentation/documentation.lyx index a678315..eeb6af5 100644 --- a/Documentation/documentation.lyx +++ b/Documentation/documentation.lyx @@ -1,5 +1,5 @@ -#LyX 1.2 created this file. For more info see http://www.lyx.org/ -\lyxformat 220 +#LyX 1.3 created this file. For more info see http://www.lyx.org/ +\lyxformat 221 \textclass article \language english \inputencoding default @@ -162,7 +162,7 @@ Note which directives go in the 'main server config' and which directives This is made clear in the directive documentation. \layout Itemize -The 'time_stamp' field is stored in an UNSIGNED INTEGER column, in the standard +The 'time_stamp' field is stored in an UNSIGNED INTEGER format, in the standard unix \begin_inset Quotes eld \end_inset @@ -173,9 +173,9 @@ seconds since the epoch format. This is superior to storing the access time as a string due to size requirement -s: an UNSIGNED INT requires 4 bytes, whereas an Apache date string -- e.g. - "18/Nov/2001:13:59:52 -0800" -- requires 26 bytes: those extra 22 bytes - become significant when multiplied by thousands of accesses on a busy server. +s: an UNSIGNED INT requires 4 bytes, whereas an Apache date string (e.g. + "18/Nov/2001:13:59:52 -0800") requires 26 bytes: those extra 22 bytes become + significant when multiplied by thousands of accesses on a busy server. Besides, an INT type is far more flexible for comparisons, etc. \begin_deeper \layout Standard @@ -301,6 +301,11 @@ These installation documents assume a relatively modern GNU/Linux scenario. compiling the module for those platforms. \layout Subsubsection + +\begin_inset LatexCommand \label{sub:Solaris} + +\end_inset + Solaris \layout Standard @@ -387,6 +392,143 @@ contact \end_inset and help fill in this section. +\layout Subsubsection + +OS X +\layout Standard + +mod_log_sql should compile and work out-of-the-box on this platform. + Here are some notes from a user successfully running the module on OS X: +\layout Quote + + +\emph on +The only changes I had to make were to where I had the various libraries + installed. +\layout Quote + + +\emph on +Here are the changes I made to the head of the Makefile: +\layout LyX-Code + +APACHESOURCE = /usr/local/src/apache_1.3.27 +\layout Quote + + +\emph on +(Wasn't sure if this was really needed or not, so I downloaded the Apache + source just in case) +\layout LyX-Code + +APACHEINSTALLED = /usr/sbin +\layout LyX-Code + +APACHEHEADERS = /usr/include/httpd +\layout LyX-Code + +APXS = $(APACHEINSTALLED)/apxs +\layout LyX-Code + +MYSQLLIBRARIES = /usr/local/mysql/lib +\layout LyX-Code + +MYSQLHEADERS = /usr/local/mysql/include +\layout Quote + + +\emph on +I'm using a binary installation of MySQL and the default apache installation + on OS X Client 10.2.3, the locations of these files may vary depending on + how you've installed MySQL and will almost certainly be different if you're + using OS X Server. +\layout Standard + +My thanks to Tom Wiebe for being the first (to my knowlege) mod_log_sql + user on OS X and for providing these notes. +\layout Subsubsection + +Digital Unix +\layout Standard + +Digital Unix, like Solaris, needs to be linked against librt; see section + +\begin_inset LatexCommand \ref{sub:Solaris} + +\end_inset + +. + Here are further notes from a user successfully running the module on Digital + Unix: +\layout Quote + + +\emph on +Instead of trying to get the module to remember where the MySQL libraries + were, I instead compiled apache with the information: +\layout Quote + + +\emph on +LDFLAGS='-rpath /isp/mysql/lib/mysql' ./configure ... +\layout Quote + + +\emph on +Everything worked as expected after that. + (The error I got without this was "/sbin/loader: Fatal Error: cannot map + libmysqlclient.so" ) +\layout Quote + + +\emph on +Digital Unix (v4.0f, at least ) appears to follow the same requirements needed + by Solaris, so simply adding librt to the module made it compile without + errors. +\layout Quote + + +\emph on +As for the warnings, here's the text: +\layout LyX-Code + + +\emph on +mod_log_sql.c: In function `extract_request_duration': +\layout LyX-Code + + +\emph on +mod_log_sql.c:292: warning: long int format, different type arg (arg 4) +\layout LyX-Code + + +\emph on +mod_log_sql.c: In function `extract_request_timestamp': +\layout LyX-Code + + +\emph on +mod_log_sql.c:497: warning: long int format, different type arg (arg 4) +\layout Quote + + +\emph on +Poking around in the code, it looks like the compiler was complaining that + what time() is returning doesn't play nicely with %ld by default. + I just typecast them as (long)'s and the warnings went away ( not that + the module wasn't working correctly without them ). +\layout Quote + + +\emph on +The module works very well so far in testing... + hasn't dropped a single log entry yet. + +\layout Standard + +My thanks to Jim Turner for permitting me to quote him here, and for being + the first known user of mod_log_sql on Digital Unix. \layout Subsection Do I want a DSO or a static module? @@ -919,10 +1061,24 @@ mysql> create database apachelogs; \end_inset If you want to hand-create the tables, run the enclosed 'create-tables' - SQL script as follows: + SQL script as follows ( +\begin_inset Quotes eld +\end_inset + +create_tables.sql +\begin_inset Quotes erd +\end_inset + + needs to be in your current working directory). \begin_deeper \layout LyX-Code +mysql> use apachelogs +\layout LyX-Code + +Database changed +\layout LyX-Code + mysql> source create_tables.sql \end_deeper \layout Enumerate @@ -939,9 +1095,7 @@ Create a specific MySQL userid that httpd will use to authenticate and enter \layout LyX-Code mysql> grant insert,create on apachelogs.* to loguser@my.apachemachine.com -\layout LyX-Code - -identified by 'l0gger'; + identified by 'l0gger'; \end_deeper \layout Enumerate @@ -4817,24 +4971,29 @@ Context: virtual host In HTTP, cookies have names to distinguish them from each other. Using mod_usertrack, for example, you can give your user-tracking cookies a name with the CookieName directive. + \layout Standard -You must include a 'c' character in -\noun on -LogSQLTransferLogFormat -\noun default - for this directive to take effect; once you specify 'c', +mod_log_sql allows you to log cookie information. + \noun on -LogSQLWhichCookie + LogSQLWhichCookie \noun default tells mod_log_sql which cookie to log. This is necessary because you will usually be setting and receiving more - than one cookie from a client; this cookie designates which one to log. + than one cookie from a client. +\layout Standard + +You must include a 'c' character in +\noun on +LogSQLTransferLogFormat +\noun default + for this directive to take effect. \layout Standard -Note: although this was intended for people who are using mod_usertrack - to set user-tracking cookies, you aren't restricted in any way. - You can choose which cookie you wish to log to the database --any cookie +Note: although this was origintally intended for people using mod_usertrack + to create user-tracking cookies, you aren't restricted in any way. + You can choose which cookie you wish to log to the database -- any cookie at all -- and it doesn't necessarily have to have anything to do with mod_usert rack. \layout Subsubsection @@ -5742,7 +5901,7 @@ Please contact Problems \layout Subsubsection -Apache segfaults when using PHP and mod_log_sql +Apache segfaults or has other problems when using PHP and mod_log_sql \layout Standard This occurs if you compiled PHP with MySQL database support. @@ -5759,8 +5918,9 @@ real \layout Standard -The solution is to configure PHP to link against the real MySQL libraries - and recompile mod_php. +PHP and mod_log_sql can be configured to happily coexist. + The solution is to configure PHP to link against the real MySQL libraries: + recompile PHP using --with-mysql=/your/path. Apache will run properly once the modules are all using the same version of the MySQL libraries. \layout Subsubsection @@ -5983,6 +6143,83 @@ Reference: \end_inset +\layout Subsubsection + +Sometimes a single VirtualHost gets logged to two different tables (e.g. + access_foo_com, access_www_foo_com). + Or, accesses to an unqualified hostname (e.g. + +\begin_inset Quotes eld +\end_inset + +http://intranet/index.html +\begin_inset Quotes erd +\end_inset + +) get logged in separate tables. +\layout Standard + +Proper usage of the Apache runtime +\noun on +ServerName +\noun default + directive and the directive +\noun on +UseCanonicalName On +\noun default +(or +\noun on +DNS +\noun default +) are necessary to prevent this problem. + +\begin_inset Quotes eld +\end_inset + +On +\begin_inset Quotes erd +\end_inset + + is the default for +\noun on +UseCanonicalName +\noun default +, and specifies that self-referential URLs are generated from the +\noun on +ServerName +\noun default +part of your VirtualHost: +\layout Quote + +With UseCanonicalName on (and in all versions prior to 1.3) Apache will use + the ServerName and Port directives to construct the canonical name for + the server. + With UseCanonicalName off Apache will form self-referential URLs using + the hostname and port supplied by the client if any are supplied (otherwise + it will use the canonical name, as defined above). + [From +\begin_inset LatexCommand \url[the Apache documentation]{http://httpd.apache.org/docs/mod/core.html#usecanonicalname} + +\end_inset + +] +\layout Standard + +The module inherits Apache's +\begin_inset Quotes eld +\end_inset + +knowledge +\begin_inset Quotes erd +\end_inset + + about the server name being accessed. + As long as those two directives are properly configured, mod_log_sql will + log to only one table per virtual host while using +\noun on +LogSQLMassVirtualHosting +\noun default +. \layout Subsection Performance and Tuning @@ -6236,7 +6473,7 @@ not correct \series default to assume that 20 Apache children with a VSZ of 7MB each equals -\begin_inset Formula $(20\times 7MB)$ +\begin_inset Formula $(20\times7MB)$ \end_inset of memory consumption -- the real answer is much, much lower. @@ -6359,74 +6596,6 @@ How do I...? -- accomplishing certain tasks \layout Subsubsection -I am using LogSQLMassVirtualHosting, and sometimes a single VirtualHost - gets logged to two different tables. - How do I prevent that? -\layout Standard - -Proper usage of the Apache runtime -\noun on -ServerName -\noun default - directive and the directive -\noun on -UseCanonicalName On -\noun default -(or -\noun on -DNS -\noun default -) are necessary to prevent this problem. - -\begin_inset Quotes eld -\end_inset - -On -\begin_inset Quotes erd -\end_inset - - is the default for -\noun on -UseCanonicalName -\noun default -, and specifies that self-referential URLs are generated from the -\noun on -ServerName -\noun default -part of your VirtualHost: -\layout Quote - -With UseCanonicalName on (and in all versions prior to 1.3) Apache will use - the ServerName and Port directives to construct the canonical name for - the server. - With UseCanonicalName off Apache will form self-referential URLs using - the hostname and port supplied by the client if any are supplied (otherwise - it will use the canonical name, as defined above). - [From -\begin_inset LatexCommand \url[the Apache documentation]{http://httpd.apache.org/docs/mod/core.html#usecanonicalname} - -\end_inset - -] -\layout Standard - -The module inherits Apache's -\begin_inset Quotes eld -\end_inset - -knowledge -\begin_inset Quotes erd -\end_inset - - about the server name being accessed. - As long as those two directives are properly configured, mod_log_sql will - log to only one table per virtual host while using -\noun on -LogSQLMassVirtualHosting -\noun default -. -\layout Subsubsection - How do I extract the data in a format that my analysis tool can understand? \layout Standard diff --git a/Makefile.in b/Makefile.in index b143029..97f961c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -9,9 +9,9 @@ HEADERS = CFLAGS = -Wc,-Wall -Wc,-Werror -Wc,-fno-strict-aliasing -INCLUDES = -I/usr/include/mysql +INCLUDES = @MYSQL_CFLAGS@ -LDADD = -L/usr/lib/mysql -lmysqlclient +LDADD = @MYSQL_LDFLAGS@ @MYSQL_LIBS@ EXTRA_DIST = INSTALL LICENSE CHANGELOG make_combined_log.pl diff --git a/aclocal.m4 b/aclocal.m4 deleted file mode 100644 index b74f335..0000000 --- a/aclocal.m4 +++ /dev/null @@ -1,128 +0,0 @@ -dnl CHECK_PATH_APACHE([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) -dnl Test for Apache apxs -dnl -AC_DEFUN(CHECK_PATH_APACHE, -[dnl -AC_ARG_WITH( - apache, - [ --with-apache[=DIR] Apache install root], - apache_prefix="$withval", - apache_prefix="/usr" - ) -AC_ARG_ENABLE(apachetest, [ --disable-apachetest Do not try to compile and run apache version test program], - , enable_apachetest=yes) - - - AC_REQUIRE([AC_CANONICAL_TARGET]) - PATH="$apache_prefix:$apache_prefix/bin:$apache_prefix/sbin:$PATH" - AC_PATH_PROG(APXS_BIN, apxs, no, [$PATH]) - min_apache_version=ifelse([$1], ,1.3.1,$1) - AC_MSG_CHECKING(for Apache - version >= $min_apache_version) - no_apxs="" - if test "$APXS_BIN" == "no"; then - no_apxs=yes - else - APACHE_INCDIR=`$APXS_BIN -q INCLUDEDIR` - APACHE_CFLAGS=-I$APACHE_INCDIR - APACHE_MODDIR=`$APXS_BIN -q LIBEXECDIR` - - if test "x$enable_apachetest" = "xyes" ; then - ac_save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $APACHE_CFLAGS" - AC_TRY_RUN([ -#include -#include -#include -#include "httpd.h" - -#ifndef AP_SERVER_BASEREVISION - #define AP_SERVER_BASEREVISION SERVER_BASEREVISION -#endif - -char* my_strdup (char *str) -{ - char *new_str; - - if (str) { - new_str = (char *)malloc ((strlen (str) + 1) * sizeof(char)); - strcpy (new_str, str); - } else - new_str = NULL; - - return new_str; -} - -int main (int argc, char *argv[]) -{ - int major1, minor1, micro1; - int major2, minor2, micro2; - char *tmp_version; - - { FILE *fp = fopen("conf.apachetest", "a"); if ( fp ) fclose(fp); } - - tmp_version = my_strdup("$min_apache_version"); - if (sscanf(tmp_version, "%d.%d.%d", &major1, &minor1, µ1) != 3) { - printf("%s, bad version string\n", "$min_apache_version"); - exit(1); - } - tmp_version = my_strdup(AP_SERVER_BASEREVISION); - if (sscanf(tmp_version, "%d.%d.%d", &major2, &minor2, µ2) != 3) { - printf("%s, bad version string\n", AP_SERVER_BASEREVISION); - exit(1); - } - if ((major2 > major1) || - ((major2 == major1) && (minor2 > minor1)) || - ((major2 == major1) && (minor2 == minor1) && (micro2 >= micro1))) - { - return 0; - } else { - printf("\n*** This module requires apache version %d.%d.%d or greater\n", - major1, minor1, micro1); - printf("*** I found version %d.%d.%d. Please verify the installation directory\n", - major2, minor2, micro2); - printf("*** of apache with the --with-apache configure option.\n"); - return 1; - } -} - -],, no_apxs=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) - CFLAGS="$ac_save_CFLAGS" - fi - fi - if test "x$no_apxs" = x ; then - AC_MSG_RESULT(yes) - ifelse([$2], , :, [$2]) - else - AC_MSG_RESULT(no) - if test "APXS_BIN" = "no" ; then - echo "*** The apxs binary installed by apache could not be found" - echo "*** If apache is installed in PREFIX, make sure PREFIX/bin is in" - echo "*** your path, or use the --with-apache configure option" - else - if test -f conf.apachetest ; then - : - else - echo "*** Could not run Apache test program, checking why..." - CFLAGS="$CFLAGS APACHE_CFLAGS" - AC_TRY_LINK([ -#include -#include "httpd.h" - -int main(int argc, char *argv[]) -{ return 0; } -#undef main -#define main K_and_R_C_main -], [ return 0; ], - [ echo "*** The test program compiled, but failed to run. Check config.log" ], - [ echo "*** The test program failed to compile or link. Check config.log" ]) - CFLAGS="$ac_save_CFLAGS" - fi - fi - APACHE_CFLAGS="" - ifelse([$3], , :, [$3]) - fi - AC_SUBST(APACHE_CFLAGS) - AC_SUBST(APACHE_INCDIR) - AC_SUBST(APACHE_MODDIR) - rm -f conf.apachetest -]) diff --git a/autogen.sh b/autogen.sh index eda8b43..9ae9c6b 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,12 +1,16 @@ #!/bin/sh -rm -rf autom4te-2.53.cache +if [ -z $ACLOCAL ]; then + ACLOCAL=aclocal-1.5 +fi if [ -z $AUTOCONF ]; then AUTOCONF=autoconf-2.53 fi if [ -z $AUTOHEADER ]; then AUTOHEADER=autoheader-2.53 fi +rm -rf autom4te-2.53.cache +$ACLOCAL -I m4 $AUTOHEADER $AUTOCONF touch stamp-h.in diff --git a/configure.ac b/configure.ac index 4fa277a..56f648c 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ dnl Required initializer -AC_INIT(mod_log_sql, 1.90) +AC_INIT(mod_log_sql, 1.91) AC_PREREQ(2.53) AC_CONFIG_HEADERS(config.h) @@ -14,6 +14,11 @@ CHECK_PATH_APACHE($APACHE_VERSION, AC_MSG_ERROR([*** Apache version $APACHE_VERSION not found!]) ) +CHECK_PATH_MYSQL(:, + AC_MSG_ERROR([*** Mysql client libraries not found!]) + ) + + AC_CONFIG_FILES([stamp-h], [echo timestamp > stamp-h]) dnl Write config.status and the Makefile diff --git a/create_tables.sql b/create_tables.sql index 0266b52..0fe0f4b 100644 --- a/create_tables.sql +++ b/create_tables.sql @@ -23,7 +23,7 @@ create table access_log ( ssl_maxkeysize smallint unsigned, status smallint unsigned , time_stamp int unsigned , - virtual_host varchar(50) + virtual_host varchar(255) ); create table notes ( diff --git a/m4/apache.m4 b/m4/apache.m4 new file mode 100644 index 0000000..b74f335 --- /dev/null +++ b/m4/apache.m4 @@ -0,0 +1,128 @@ +dnl CHECK_PATH_APACHE([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for Apache apxs +dnl +AC_DEFUN(CHECK_PATH_APACHE, +[dnl +AC_ARG_WITH( + apache, + [ --with-apache[=DIR] Apache install root], + apache_prefix="$withval", + apache_prefix="/usr" + ) +AC_ARG_ENABLE(apachetest, [ --disable-apachetest Do not try to compile and run apache version test program], + , enable_apachetest=yes) + + + AC_REQUIRE([AC_CANONICAL_TARGET]) + PATH="$apache_prefix:$apache_prefix/bin:$apache_prefix/sbin:$PATH" + AC_PATH_PROG(APXS_BIN, apxs, no, [$PATH]) + min_apache_version=ifelse([$1], ,1.3.1,$1) + AC_MSG_CHECKING(for Apache - version >= $min_apache_version) + no_apxs="" + if test "$APXS_BIN" == "no"; then + no_apxs=yes + else + APACHE_INCDIR=`$APXS_BIN -q INCLUDEDIR` + APACHE_CFLAGS=-I$APACHE_INCDIR + APACHE_MODDIR=`$APXS_BIN -q LIBEXECDIR` + + if test "x$enable_apachetest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $APACHE_CFLAGS" + AC_TRY_RUN([ +#include +#include +#include +#include "httpd.h" + +#ifndef AP_SERVER_BASEREVISION + #define AP_SERVER_BASEREVISION SERVER_BASEREVISION +#endif + +char* my_strdup (char *str) +{ + char *new_str; + + if (str) { + new_str = (char *)malloc ((strlen (str) + 1) * sizeof(char)); + strcpy (new_str, str); + } else + new_str = NULL; + + return new_str; +} + +int main (int argc, char *argv[]) +{ + int major1, minor1, micro1; + int major2, minor2, micro2; + char *tmp_version; + + { FILE *fp = fopen("conf.apachetest", "a"); if ( fp ) fclose(fp); } + + tmp_version = my_strdup("$min_apache_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major1, &minor1, µ1) != 3) { + printf("%s, bad version string\n", "$min_apache_version"); + exit(1); + } + tmp_version = my_strdup(AP_SERVER_BASEREVISION); + if (sscanf(tmp_version, "%d.%d.%d", &major2, &minor2, µ2) != 3) { + printf("%s, bad version string\n", AP_SERVER_BASEREVISION); + exit(1); + } + if ((major2 > major1) || + ((major2 == major1) && (minor2 > minor1)) || + ((major2 == major1) && (minor2 == minor1) && (micro2 >= micro1))) + { + return 0; + } else { + printf("\n*** This module requires apache version %d.%d.%d or greater\n", + major1, minor1, micro1); + printf("*** I found version %d.%d.%d. Please verify the installation directory\n", + major2, minor2, micro2); + printf("*** of apache with the --with-apache configure option.\n"); + return 1; + } +} + +],, no_apxs=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + fi + fi + if test "x$no_apxs" = x ; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "APXS_BIN" = "no" ; then + echo "*** The apxs binary installed by apache could not be found" + echo "*** If apache is installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or use the --with-apache configure option" + else + if test -f conf.apachetest ; then + : + else + echo "*** Could not run Apache test program, checking why..." + CFLAGS="$CFLAGS APACHE_CFLAGS" + AC_TRY_LINK([ +#include +#include "httpd.h" + +int main(int argc, char *argv[]) +{ return 0; } +#undef main +#define main K_and_R_C_main +], [ return 0; ], + [ echo "*** The test program compiled, but failed to run. Check config.log" ], + [ echo "*** The test program failed to compile or link. Check config.log" ]) + CFLAGS="$ac_save_CFLAGS" + fi + fi + APACHE_CFLAGS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(APACHE_CFLAGS) + AC_SUBST(APACHE_INCDIR) + AC_SUBST(APACHE_MODDIR) + rm -f conf.apachetest +]) diff --git a/m4/mysql.m4 b/m4/mysql.m4 new file mode 100644 index 0000000..c4c4a3b --- /dev/null +++ b/m4/mysql.m4 @@ -0,0 +1,64 @@ +dnl CHECK_PATH_MYSQL([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUNT]]) +dnl Check for MySQL Libs +dnl +AC_DEFUN(CHECK_PATH_MYSQL, +[dnl +AC_ARG_WITH( + mysql, + [AC_HELP_STRING([--with-mysql],[Path to MySQL client library])], + mysql_prefix="$withval", + + ) +AC_ARG_ENABLE( + mysqltest, + [AC_HELP_STRING([--disble-mysqltest],[Do not try to compile and run mysql test program])], + , + enable_apachetest=yes) + + AC_REQUIRE([AC_CANONICAL_TARGET]) + ac_save_CFLAGS=$CFLAGS + ac_save_LDFLAGS=$LDFLAGS + if test "x$mysql_prefix" != "x" && test "x$mysql_prefix" != "xyes"; then + MYSQL_LDFLAGS="-L${mysql_prefix}/lib -L${mysql_prefix}/lib/mysql -L${mysql_prefix}/mysql/lib" + MYSQL_CFLAGS="-I${mysql_prefix}/include -I${mysql_prefix}/include/mysql -I${mysql_prefix}/mysql/include" + else + MYSQL_LDFLAGS="-L/usr/local/mysql/lib -L/usr/lib/mysql -L/usr/mysql/lib -L/usr/local/lib/mysql -L/usr/local/mysql/lib/mysql -L/usr/mysql/lib/mysql" + MYSQL_CFLAGS="-I/usr/local/mysql/include -I/usr/include/mysql -I/usr/mysql/include -I/usr/local/include/mysql -I/usr/local/mysql/include/mysql -I/usr/mysql/include/mysql" + fi + CFLAGS="$CFLAGS $MYSQL_CFLAGS" + LDFLAGS="$LDFLAGS $MYSQL_LDFLAGS" + AC_CHECK_LIB(m, floor) + AC_CHECK_LIB(z, gzclose) + with_mysql="yes" + AC_DEFINE(WITH_MYSQL,,[with mysql]) + AC_CHECK_LIB(mysqlclient, mysql_init, , + [AC_MSG_ERROR(libmysqlclient is needed for MySQL support)]) + MYSQL_LIBS=$LIBS + AC_CHECK_FUNCS(mysql_real_escape_string) + AC_MSG_CHECKING(whether mysql clients can run) + AC_TRY_RUN([ + #include + #include + int main(void) + { + MYSQL *a = mysql_init(NULL); + return 0; + } + ], , no_mysql=yes,[echo $ac_n "cross compiling; assumed OK.... $ac_c"]) + CFLAGS=$ac_save_CFLAGS + LDFLAGS=$ac_save_LDFLAGS + if test "x$no_mysql" = x; then + AC_MSG_RESULT(yes) + ifelse([$1], , :, [$1]) + else + AC_MSG_RESULT(no) + echo "*** MySQL could not be found ***" + MYSQL_CFLAGS="" + MYSQL_LDFLAGS="" + MYSQL_LIBS="" + ifelse([$2], , :, [$2]) + fi + AC_SUBST(MYSQL_LDFLAGS) + AC_SUBST(MYSQL_CFLAGS) + AC_SUBST(MYSQL_LIBS) +]) diff --git a/mod_log_sql.c b/mod_log_sql.c index 8a48b17..de6fe1a 100644 --- a/mod_log_sql.c +++ b/mod_log_sql.c @@ -1,4 +1,4 @@ -/* $Header: /home/cvs/mod_log_sql/mod_log_sql.c,v 1.3 2003/12/22 04:45:38 urkle Exp $ */ +/* $Header: /home/cvs/mod_log_sql/mod_log_sql.c,v 1.4 2003/12/23 19:49:56 urkle Exp $ */ /* --------* * DEFINES * * --------*/ @@ -58,6 +58,15 @@ #include "mod_ssl.h" #endif + +/* 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 "/tmp/sql-preserve" + /* -------------* * DECLARATIONS * * -------------*/ @@ -74,6 +83,7 @@ typedef struct { int massvirtual; int createtables; int forcepreserve; + char *tabletype; char *dbname; char *dbhost; char *dbuser; @@ -366,13 +376,6 @@ static const char *extract_request_duration(request_rec *r, char *a) return apr_psprintf(r->pool, "%" APR_TIME_T_FMT, apr_time_sec(duration)); } -static const char *extract_request_duration_microseconds(request_rec *r, char *a) __attribute__ ((unused)); -static const char *extract_request_duration_microseconds(request_rec *r, char *a) -{ - return apr_psprintf(r->pool, "%" APR_TIME_T_FMT, - (apr_time_now() - r->request_time)); -} - static const char *extract_virtual_host(request_rec *r, char *a) { return apr_pstrdup(r->pool, r->server->server_hostname); @@ -589,7 +592,7 @@ static const char *extract_specific_cookie(request_rec *r, char *a) static const char *extract_request_timestamp(request_rec *r, char *a) { - return apr_psprintf(r->pool, "%ld", time(NULL)); + return apr_psprintf(r->pool, "%"APR_TIME_T_FMT, apr_time_sec(apr_time_now())); } /* @@ -910,6 +913,8 @@ static int safe_create_tables(logsql_state *cls, request_rec *r) char *create_hin = NULL; char *create_cookies = NULL; + char *type_suffix = NULL; + char *createprefix = "create table if not exists `"; char *access_suffix = "` (id char(19),\ @@ -952,13 +957,15 @@ static int safe_create_tables(logsql_state *cls, request_rec *r) "` (id char(19),\ item varchar(80),\ val varchar(80))"; - + if (global_config.tabletype) { + type_suffix = apr_pstrcat(r->pool, " TYPE=", global_config.tabletype, NULL); + } /* Find memory long enough to hold the whole CREATE string + \0 */ - create_access = apr_pstrcat(r->pool, createprefix, cls->transfer_table_name, access_suffix, NULL); - create_notes = apr_pstrcat(r->pool, createprefix, cls->notes_table_name, notes_suffix, NULL); - create_hout = apr_pstrcat(r->pool, createprefix, cls->hout_table_name, headers_suffix, NULL); - create_hin = apr_pstrcat(r->pool, createprefix, cls->hin_table_name, headers_suffix, NULL); - create_cookies= apr_pstrcat(r->pool, createprefix, cls->cookie_table_name, cookies_suffix, NULL); + create_access = apr_pstrcat(r->pool, createprefix, cls->transfer_table_name, access_suffix, type_suffix, NULL); + create_notes = apr_pstrcat(r->pool, createprefix, cls->notes_table_name, notes_suffix, type_suffix, NULL); + create_hout = apr_pstrcat(r->pool, createprefix, cls->hout_table_name, headers_suffix, type_suffix, NULL); + create_hin = apr_pstrcat(r->pool, createprefix, cls->hin_table_name, headers_suffix, type_suffix, NULL); + create_cookies= apr_pstrcat(r->pool, createprefix, cls->cookie_table_name, cookies_suffix, type_suffix, NULL); #ifdef DEBUG ap_log_error(APLOG_MARK,APLOG_DEBUG,0,r->server,"mod_log_sql: create string: %s", create_access); @@ -982,12 +989,12 @@ static int safe_create_tables(logsql_state *cls, request_rec *r) } if ((create_results = safe_sql_query(r, create_hin))) { - ap_log_error(APLOG_MARK,APLOG_ERR,0,r->server,"mod_log_sql: failed to create header_out table"); + ap_log_error(APLOG_MARK,APLOG_ERR,0,r->server,"mod_log_sql: failed to create header_in table"); retval = create_results; } if ((create_results = safe_sql_query(r, create_hout))) { - ap_log_error(APLOG_MARK,APLOG_ERR,0,r->server,"mod_log_sql: failed to create header_in table"); + ap_log_error(APLOG_MARK,APLOG_ERR,0,r->server,"mod_log_sql: failed to create header_out table"); retval = create_results; } @@ -1009,33 +1016,36 @@ static const char *set_global_flag_slot(cmd_parms *cmd, void *struct_ptr, int flag) { - int offset = (int)(long)&global_config; + void *ptr = &global_config; + int offset = (int)(long)cmd->info; - *(int *)((char *)struct_ptr + offset) = flag ? 1 : 0; + *(int *)((char *)ptr + offset) = flag ? 1 : 0; return NULL; } -static const char *set_global_nmv_flag_slot(cmd_parms *parms, +static const char *set_global_nmv_flag_slot(cmd_parms *cmd, void *struct_ptr, int flag) { - 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_global_flag_slot(parms,struct_ptr,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) { - int offset = (int)(long)&global_config; + void *ptr = &global_config; + int offset = (int)(long)cmd->info; - *(const char **)((char *)struct_ptr + offset) = apr_pstrdup(cmd->pool,arg); - + *(const char **)((char *)ptr + offset) = apr_pstrdup(cmd->pool,arg); return NULL; } @@ -1043,10 +1053,11 @@ static const char *set_server_string_slot(cmd_parms *cmd, void *struct_ptr, const char *arg) { - int offset = (int)(long)ap_get_module_config(cmd->server->module_config, + void *ptr = ap_get_module_config(cmd->server->module_config, &log_sql_module); + int offset = (int)(long)cmd->info; - *(const char **)((char *)struct_ptr + offset) = arg; + *(const char **)((char *)ptr + offset) = arg; return NULL; } @@ -1058,7 +1069,7 @@ static const char *set_server_nmv_string_slot(cmd_parms *parms, { if (global_config.massvirtual) return apr_psprintf(parms->pool, - "mod_log_sql: do not set %s when LogSQLMassVirtualHosting is On.", + "mod_log_sql: do not set %s when LogSQLMassVirtualHosting is On.", parms->cmd->name); else return set_server_string_slot(parms,struct_ptr,arg); @@ -1083,9 +1094,10 @@ static const char *add_server_string_slot(cmd_parms *cmd, const char *arg) { char **addme; - int offset = (int)(long)ap_get_module_config(cmd->server->module_config, + void *ptr = ap_get_module_config(cmd->server->module_config, &log_sql_module); - apr_array_header_t *ary = *(apr_array_header_t **)((apr_array_header_t *)struct_ptr + offset); + int offset = (int)(long)cmd->info; + apr_array_header_t *ary = *(apr_array_header_t **)((apr_array_header_t *)ptr + offset); addme = apr_array_push(ary); *addme = apr_pstrdup(ary->pool, arg); @@ -1131,7 +1143,6 @@ static apr_status_t log_sql_close_link(void *data) static void log_sql_child_init(apr_pool_t *p, server_rec *s) { apr_pool_cleanup_register(p, NULL, log_sql_close_link, log_sql_close_link); - } static int log_sql_open(apr_pool_t *pc, apr_pool_t *p, apr_pool_t *pt, server_rec *s) @@ -1178,7 +1189,7 @@ void *log_sql_initializer(server_rec *main_server, apr_pool_t *p) static int log_sql_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp) { /* Initialize Global configuration */ - memset(&global_config,0,sizeof(global_config)); + memset(&global_config,0,sizeof(global_config_t)); global_config.socketfile = "/tmp/mysql.sock"; global_config.tcpport = 3306; return OK; @@ -1186,16 +1197,15 @@ static int log_sql_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp static void *log_sql_make_state(apr_pool_t *p, server_rec *s) { - logsql_state *cls = (logsql_state *) apr_palloc(p, sizeof(logsql_state)); + logsql_state *cls = (logsql_state *) apr_pcalloc(p, sizeof(logsql_state)); /* These defaults are overridable in the httpd.conf file. */ - cls->transfer_table_name = NULL; /* No default b/c we want its absence to disable logging */ - cls->transfer_log_format = "AbHhmRSsTUuv"; - cls->notes_table_name = "notes"; - cls->hin_table_name = "headers_in"; - cls->hout_table_name = "headers_out"; - cls->cookie_table_name = "cookies"; - cls->preserve_file = "/tmp/sql-preserve"; + cls->transfer_log_format = DEFAULT_TRANSFER_LOG_FMT; + 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 *)); @@ -1204,11 +1214,70 @@ static void *log_sql_make_state(apr_pool_t *p, server_rec *s) 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 *)); - cls->cookie_name = NULL; return (void *) cls; } +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. */ + + child->transfer_table_name = child->transfer_table_name ? + child->transfer_table_name : parent->transfer_table_name; + /* No default for transfer_table_name because we want its absence + * to disable logging. */ + + if (child->transfer_log_format == DEFAULT_TRANSFER_LOG_FMT) + child->transfer_log_format = parent->transfer_log_format; + + if (child->preserve_file == DEFAULT_PRESERVE_FILE) + child->preserve_file = parent->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; + + if (apr_is_empty_array(child->transfer_ignore_list)) + apr_array_cat(child->transfer_ignore_list, parent->transfer_ignore_list); + + if (apr_is_empty_array(child->transfer_accept_list)) + apr_array_cat(child->transfer_accept_list, parent->transfer_accept_list); + + if (apr_is_empty_array(child->remhost_ignore_list)) + apr_array_cat(child->remhost_ignore_list, parent->remhost_ignore_list); + + if (apr_is_empty_array(child->notes_list)) + apr_array_cat(child->notes_list, parent->notes_list); + + if (apr_is_empty_array(child->hin_list)) + apr_array_cat(child->hin_list, parent->hin_list); + + if (apr_is_empty_array(child->hout_list)) + apr_array_cat(child->hout_list, parent->hout_list); + + if (apr_is_empty_array(child->cookie_list)) + apr_array_cat(child->cookie_list, parent->cookie_list); + + 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. */ @@ -1233,36 +1302,22 @@ static int log_sql_transaction(request_rec *orig) char *i_tablename; char *o_tablename; char *c_tablename; - unsigned int i; - /* Find memory long enough to hold the table name + \0. */ - a_tablename = apr_pstrcat(orig->pool, access_base, ap_get_server_name(orig), NULL); - n_tablename = apr_pstrcat(orig->pool, notes_base, ap_get_server_name(orig), NULL); - i_tablename = apr_pstrcat(orig->pool, hin_base, ap_get_server_name(orig), NULL); - o_tablename = apr_pstrcat(orig->pool, hout_base, ap_get_server_name(orig), NULL); - c_tablename = apr_pstrcat(orig->pool, cookie_base, ap_get_server_name(orig), NULL); - - /* Transform any dots to underscores */ - for (i = 0; i < strlen(a_tablename); i++) { - if (a_tablename[i] == '.') - a_tablename[i] = '_'; - } - for (i = 0; i < strlen(n_tablename); i++) { - if (n_tablename[i] == '.') - n_tablename[i] = '_'; - } - for (i = 0; i < strlen(i_tablename); i++) { - if (i_tablename[i] == '.') - i_tablename[i] = '_'; - } - for (i = 0; i < strlen(o_tablename); i++) { - if (o_tablename[i] == '.') - o_tablename[i] = '_'; - } - for (i = 0; i < strlen(c_tablename); i++) { - if (c_tablename[i] == '.') - c_tablename[i] = '_'; + /* Determint 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 = '_'; + ++p; } + + /* Find memory long enough to hold the table name + \0. */ + a_tablename = apr_pstrcat(orig->pool, access_base, servername, NULL); + n_tablename = apr_pstrcat(orig->pool, notes_base, servername, NULL); + i_tablename = apr_pstrcat(orig->pool, hin_base, servername, NULL); + o_tablename = apr_pstrcat(orig->pool, hout_base, servername, NULL); + c_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. @@ -1396,7 +1451,8 @@ static int log_sql_transaction(request_rec *orig) } if ( itemsets != "" ) { note_query = apr_psprintf(r->pool, "insert %s into `%s` (id, item, val) values %s", - global_config.insertdelayed?"delayed":NULL, cls->notes_table_name, itemsets); + global_config.insertdelayed?"delayed":"", cls->notes_table_name, itemsets); + #ifdef DEBUG ap_log_error(APLOG_MARK,APLOG_DEBUG,0,orig->server,"mod_log_sql: note string: %s", note_query); #endif @@ -1425,7 +1481,8 @@ static int log_sql_transaction(request_rec *orig) } if ( itemsets != "" ) { hout_query = apr_psprintf(r->pool, "insert %s into `%s` (id, item, val) values %s", - global_config.insertdelayed?"delayed":NULL, cls->hout_table_name, itemsets); + global_config.insertdelayed?"delayed":"", cls->hout_table_name, itemsets); + #ifdef DEBUG ap_log_error(APLOG_MARK,APLOG_DEBUG,0,orig->server,"mod_log_sql: header_out string: %s", hout_query); #endif @@ -1455,7 +1512,7 @@ static int log_sql_transaction(request_rec *orig) } if ( itemsets != "" ) { hin_query = apr_psprintf(r->pool, "insert %s into `%s` (id, item, val) values %s", - global_config.insertdelayed?"delayed":NULL, cls->hin_table_name, itemsets); + global_config.insertdelayed?"delayed":"", cls->hin_table_name, itemsets); #ifdef DEBUG ap_log_error(APLOG_MARK,APLOG_DEBUG,0,orig->server,"mod_log_sql: header_in string: %s", hin_query); @@ -1487,7 +1544,8 @@ static int log_sql_transaction(request_rec *orig) } if ( itemsets != "" ) { cookie_query = apr_psprintf(r->pool, "insert %s into `%s` (id, item, val) values %s", - global_config.insertdelayed?"delayed":NULL, cls->cookie_table_name, itemsets); + global_config.insertdelayed?"delayed":"", cls->cookie_table_name, itemsets); + #ifdef DEBUG ap_log_error(APLOG_MARK,APLOG_DEBUG,0,orig->server,"mod_log_sql: cookie string: %s", cookie_query); #endif @@ -1496,7 +1554,7 @@ static int log_sql_transaction(request_rec *orig) /* Set up the actual INSERT statement */ access_query = apr_psprintf(r->pool, "insert %s into `%s` (%s) values (%s)", - global_config.insertdelayed?"delayed":NULL, cls->transfer_table_name, fields, values); + global_config.insertdelayed?"delayed":"", cls->transfer_table_name, fields, values); #ifdef DEBUG ap_log_error(APLOG_MARK,APLOG_DEBUG,0,r->server,"mod_log_sql: access string: %s", access_query); @@ -1656,6 +1714,10 @@ static const command_rec log_sql_cmds[] = { (void *)APR_OFFSETOF(global_config_t, socketfile), RSRC_CONF, "Name of the file to employ for socket connections to database") , + AP_INIT_TAKE1("LogSQLTableType", set_global_string_slot, + (void *)APR_OFFSETOF(global_config_t, tabletype), RSRC_CONF, + "What kind of table to create (MyISAM, InnoDB,...) when creating tables") + , AP_INIT_TAKE1("LogSQLTCPPort", set_log_sql_tcp_port, NULL, RSRC_CONF, "Port number to use for TCP connections to database, defaults to 3306 if not set") , @@ -1690,7 +1752,7 @@ module AP_MODULE_DECLARE_DATA log_sql_module = { NULL, /* create per-directory config structures */ NULL, /* merge per-directory config structures */ log_sql_make_state, /* create per-server config structures */ - NULL, /* merge per-server config structures */ + log_sql_merge_state, /* merge per-server config structures */ log_sql_cmds, /* command handlers */ register_hooks /* register hooks */ }; -- cgit