summaryrefslogtreecommitdiffstatsabout
path: root/mod_log_sql.c
diff options
context:
space:
mode:
Diffstat (limited to 'mod_log_sql.c')
-rw-r--r--mod_log_sql.c1282
1 files changed, 0 insertions, 1282 deletions
diff --git a/mod_log_sql.c b/mod_log_sql.c
deleted file mode 100644
index 1892eec..0000000
--- a/mod_log_sql.c
+++ /dev/null
@@ -1,1282 +0,0 @@
1/* $Id$ */
2
3#if defined(WITH_APACHE20)
4# include "apache20.h"
5#elif defined(WITH_APACHE13)
6# include "apache13.h"
7#else
8# error Unsupported Apache version
9#endif
10
11#ifdef HAVE_CONFIG_H
12/* Undefine these to prevent conflicts between Apache ap_config_auto.h and
13 * my config.h. Only really needed for Apache < 2.0.48, but it can't hurt.
14 */
15#undef PACKAGE_BUGREPORT
16#undef PACKAGE_NAME
17#undef PACKAGE_STRING
18#undef PACKAGE_TARNAME
19#undef PACKAGE_VERSION
20
21#include "config.h"
22#endif
23
24#if APR_HAVE_UNISTD_H
25#include <unistd.h>
26#endif
27#ifdef HAVE_LIMITS_H
28#include <limits.h>
29#endif
30
31#include "mod_log_sql.h"
32
33/* Configuratino Defaults */
34#define DEFAULT_TRANSFER_LOG_FMT "AbHhmRSsTUuv"
35#define DEFAULT_NOTES_TABLE_NAME "notes"
36#define DEFAULT_HIN_TABLE_NAME "headers_in"
37#define DEFAULT_HOUT_TABLE_NAME "headers_out"
38#define DEFAULT_COOKIE_TABLE_NAME "cookies"
39#define DEFAULT_PRESERVE_FILE "logs/mod_log_sql-preserve"
40
41/* -------------*
42 * DECLARATIONS *
43 * -------------*/
44
45/* Declare ourselves so the configuration routines can find and know us. */
46module AP_MODULE_DECLARE_DATA log_sql_module;
47
48/* The contents of these are known 'Apache wide' and are not variable
49 * on a per-virtual-server basis. Every virtual server 'knows' the
50 * same versions of these variables.
51 */
52
53typedef struct {
54 int massvirtual;
55 int createtables;
56 int forcepreserve;
57 int disablepreserve;
58 char *machid;
59 int announce;
60 logsql_dbconnection db;
61 logsql_dbdriver *driver;
62} global_config_t;
63
64static global_config_t global_config;
65
66/* structure to hold helper function info */
67typedef struct {
68 char key; /* item letter character */
69 logsql_item_func *func; /* its extraction function */
70 const char *sql_field_name; /* its column in SQL */
71 int want_orig_default; /* if it requires the original request prior to internal redirection */
72 int string_contents; /* if it returns a string */
73} logsql_item;
74
75/* But the contents of this structure will vary by virtual server.
76 * This permits each virtual server to vary its configuration slightly
77 * for per-server customization.
78 *
79 * Each child process has its own segregated copy of this structure.
80 */
81typedef struct {
82 apr_array_header_t *transfer_ignore_list;
83 apr_array_header_t *transfer_accept_list;
84 apr_array_header_t *remhost_ignore_list;
85 apr_array_header_t *notes_list;
86 apr_array_header_t *hout_list;
87 apr_array_header_t *hin_list;
88 apr_array_header_t *cookie_list;
89 const char *notes_table_name;
90 const char *hout_table_name;
91 const char *hin_table_name;
92 const char *cookie_table_name;
93 const char *transfer_table_name;
94 const char *transfer_log_format;
95 apr_pool_t *parsed_pool;
96 logsql_item **parsed_log_format;
97 const char *preserve_file;
98 const char *cookie_name;
99} logsql_state;
100
101
102/* list of "handlers" for log types */
103static apr_array_header_t *logsql_item_list;
104
105/* Registration function for extract functions *
106 * and update parse cache for transfer_log_format *
107 * this is exported from the module */
108LOGSQL_DECLARE(void) log_sql_register_item(server_rec *s, apr_pool_t *p,
109 char key, logsql_item_func *func, const char *sql_field_name,
110 int want_orig_default, int string_contents)
111{
112 server_rec *ts;
113 logsql_item *item;
114 if (!logsql_item_list)
115 logsql_item_list = apr_array_make(p,10, sizeof(logsql_item));
116
117 item= apr_array_push(logsql_item_list);
118 item->key = key;
119 item->func = func;
120 item->sql_field_name = sql_field_name;
121 item->want_orig_default = want_orig_default;
122 item->string_contents = string_contents;
123 /* some voodoo here to post parse logitems in all servers *
124 * so a "cached" list is used in the main logging loop for speed */
125 for (ts = s; ts; ts = ts->next) {
126 logsql_state *cfg = ap_get_module_config(ts->module_config,
127 &log_sql_module);
128 char *pos;
129
130 if (cfg->transfer_log_format) {
131 if ( (pos = ap_strchr_c(cfg->transfer_log_format,key))!=NULL) {
132 cfg->parsed_log_format[pos - cfg->transfer_log_format] = item;
133 }
134 }
135 }
136}
137
138/* Registration function for database drivers */
139LOGSQL_DECLARE(void) log_sql_register_driver(apr_pool_t *p,
140 logsql_dbdriver *driver)
141{
142 global_config.driver = driver;
143}
144
145/* Include all the core extract functions */
146#include "functions.h"
147#if defined(WITH_APACHE13)
148# include "functions13.h"
149#elif defined(WITH_APACHE20)
150# include "functions20.h"
151#endif
152
153static logsql_opendb_ret log_sql_opendb_link(server_rec* s)
154{
155 logsql_opendb_ret result;
156 if (global_config.driver == NULL) {
157 return LOGSQL_OPENDB_FAIL;
158 }
159 if (global_config.forcepreserve) {
160 //global_config.db.connected = 1;
161 return LOGSQL_OPENDB_PRESERVE;
162 }
163 if (global_config.db.connected) {
164 return LOGSQL_OPENDB_ALREADY;
165 }
166 /* database
167 host
168 user
169 passwd
170 */
171 if (global_config.db.parms) {
172 result = global_config.driver->connect(s, &global_config.db);
173 if (result==LOGSQL_OPENDB_FAIL) {
174 global_config.db.connected = 0;
175 } else {
176 global_config.db.connected = 1;
177 }
178 return result;
179 } else {
180 log_error(APLOG_MARK, APLOG_ERR, 0, s,
181 "mod_log_sql: insufficient configuration info to establish database link");
182 return LOGSQL_OPENDB_FAIL;
183 }
184}
185
186static void preserve_entry(request_rec *r, const char *query)
187{
188 logsql_state *cls = ap_get_module_config(r->server->module_config,
189 &log_sql_module);
190 #if defined(WITH_APACHE20)
191 apr_file_t *fp;
192 apr_status_t result;
193 #elif defined(WITH_APACHE13)
194 FILE *fp;
195 int result;
196 #endif
197 /* If preserve file is disabled bail out */
198 if (global_config.disablepreserve)
199 return;
200 #if defined(WITH_APACHE20)
201 result = apr_file_open(&fp, cls->preserve_file,APR_APPEND | APR_WRITE | APR_CREATE, APR_OS_DEFAULT, r->pool);
202 #elif defined(WITH_APACHE13)
203 fp = ap_pfopen(r->pool, cls->preserve_file, "a");
204 result = (fp)?0:errno;
205 #endif
206 if (result != APR_SUCCESS) {
207 log_error(APLOG_MARK, APLOG_ERR, result, r->server,
208 "attempted append of local preserve file '%s' but failed.",cls->preserve_file);
209 } else {
210 #if defined(WITH_APACHE20)
211 apr_file_printf(fp,"%s;\n", query);
212 apr_file_close(fp);
213 #elif defined(WITH_APACHE13)
214 fprintf(fp,"%s;\n", query);
215 ap_pfclose(r->pool, fp);
216 #endif
217 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
218 "mod_log_sql: entry preserved in %s", cls->preserve_file);
219 }
220}
221
222
223/* ------------------------------------------------*
224 * Command handlers that are called according *
225 * to the directives found at Apache runtime. *
226 * ------------------------------------------------*/
227
228
229static const char *set_global_flag_slot(cmd_parms *cmd,
230 void *struct_ptr,
231 int flag)
232{
233 void *ptr = &global_config;
234 int offset = (int)(long)cmd->info;
235
236 *(int *)((char *)ptr + offset) = flag ? 1 : 0;
237
238 return NULL;
239}
240
241static const char *set_global_nmv_flag_slot(cmd_parms *cmd,
242 void *struct_ptr,
243 int flag)
244{
245 if (global_config.massvirtual) {
246 return apr_psprintf(cmd->pool,
247 "mod_log_sql: do not set %s when LogSQLMassVirtualHosting(%d) is On.%d:%d",
248 cmd->cmd->name, global_config.massvirtual,
249 (int)(long)&global_config, (int)(long)struct_ptr);
250 } else {
251 return set_global_flag_slot(cmd,struct_ptr,flag);
252 }
253}
254
255static const char *set_global_string_slot(cmd_parms *cmd,
256 void *struct_ptr,
257 const char *arg)
258{
259 void *ptr = &global_config;
260 int offset = (int)(long)cmd->info;
261
262 *(const char **)((char *)ptr + offset) = apr_pstrdup(cmd->pool,arg);
263 return NULL;
264}
265static const char *set_server_string_slot(cmd_parms *cmd,
266 void *struct_ptr,
267 const char *arg)
268{
269 void *ptr = ap_get_module_config(cmd->server->module_config,
270 &log_sql_module);
271 int offset = (int)(long)cmd->info;
272
273 *(const char **)((char *)ptr + offset) = arg;
274
275 return NULL;
276}
277
278static const char *set_server_file_slot(cmd_parms *cmd,
279 void *struct_ptr,
280 const char *arg)
281{
282 void *ptr = ap_get_module_config(cmd->server->module_config,
283 &log_sql_module);
284 int offset = (int)(long)cmd->info;
285 const char *path;
286
287 path = ap_server_root_relative(cmd->pool, (char *)arg);
288
289 if (!path) {
290 return apr_pstrcat(cmd->pool, "Invalid file path ",
291 arg, NULL);
292 }
293
294 *(const char **)((char*)ptr + offset) = path;
295
296 return NULL;
297}
298
299static const char *set_logformat_slot(cmd_parms *cmd,
300 void *struct_ptr,
301 const char *arg)
302{
303 logsql_state *cfg = ap_get_module_config(cmd->server->module_config,
304 &log_sql_module);
305
306 cfg->transfer_log_format = arg;
307/* apr_pool_clear(cfg->parsed_pool);*/
308 cfg->parsed_log_format = apr_pcalloc(cfg->parsed_pool,
309 strlen(arg) * sizeof(logsql_item *));
310 return NULL;
311}
312
313static const char *set_server_nmv_string_slot(cmd_parms *parms,
314 void *struct_ptr,
315 const char *arg)
316{
317 if (global_config.massvirtual)
318 return apr_psprintf(parms->pool,
319 "mod_log_sql: do not set %s when LogSQLMassVirtualHosting is On.",
320 parms->cmd->name);
321 else
322 return set_server_string_slot(parms,struct_ptr,arg);
323}
324
325/* Set a DB connection parameter */
326static const char *set_dbparam(cmd_parms *cmd,
327 void *struct_ptr,
328 const char *key,
329 const char *val)
330{
331 if (!global_config.db.parms) {
332 global_config.db.parms = apr_table_make(cmd->pool,5);
333 }
334 apr_table_set(global_config.db.parms,key,val);
335 return NULL;
336}
337
338static const char *set_dbparam_slot(cmd_parms *cmd,
339 void *struct_ptr,
340 const char *arg)
341{
342 const char *param = (char *)cmd->info;
343 set_dbparam(cmd,NULL,param,arg);
344 return NULL;
345}
346
347/* Sets basic connection info */
348static const char *set_log_sql_info(cmd_parms *cmd, void *dummy,
349 const char *host, const char *user, const char *pwd)
350{
351 if (!user) { /* user is null, so only one arg passed */
352 /* TODO: to more error checking/force all params to be set */
353 apr_uri_t uri;
354 apr_uri_parse(cmd->pool, host, &uri);
355 if (uri.scheme) {
356 set_dbparam(cmd, NULL, "driver", uri.scheme);
357 }
358 if (uri.hostname) {
359 set_dbparam(cmd, NULL, "hostname", uri.hostname);
360 }
361 if (uri.user) {
362 set_dbparam(cmd, NULL, "username", uri.user);
363 }
364 if (uri.password) {
365 set_dbparam(cmd, NULL, "password", uri.password);
366 }
367 if (uri.port_str) {
368 set_dbparam(cmd, NULL, "port", uri.port_str);
369 }
370 if (uri.path) {
371 /* extract Database name */
372 char *off = ap_strchr(++uri.path,'/');
373 if (off)
374 *off='\0';
375 set_dbparam(cmd, NULL, "database", uri.path);
376
377 }
378 } else {
379 if (*host != '.') {
380 set_dbparam(cmd, NULL, "hostname", host);
381 }
382 if (*user != '.') {
383 set_dbparam(cmd, NULL, "username", user);
384 }
385 if (*pwd != '.') {
386 set_dbparam(cmd, NULL, "password", pwd);
387 }
388 }
389 return NULL;
390}
391
392static const char *add_server_string_slot(cmd_parms *cmd,
393 void *struct_ptr,
394 const char *arg)
395{
396 char **addme;
397 void *ptr = ap_get_module_config(cmd->server->module_config,
398 &log_sql_module);
399 int offset = (int)(long)cmd->info;
400 apr_array_header_t *ary = *(apr_array_header_t **)((char *)ptr + offset);
401 addme = apr_array_push(ary);
402 *addme = apr_pstrdup(ary->pool, arg);
403
404 return NULL;
405}
406
407/*------------------------------------------------------------*
408 * Apache-specific hooks into the module code *
409 * that are defined in the array 'mysql_lgog_module' (at EOF) *
410 *------------------------------------------------------------*/
411/* Closing mysql link: child_exit(1.3), pool registration(2.0) */
412#if defined(WITH_APACHE20)
413static apr_status_t log_sql_close_link(void *data)
414{
415 if (global_config.driver)
416 global_config.driver->disconnect(&global_config.db);
417 return APR_SUCCESS;
418}
419#elif defined(WITH_APACHE13)
420static void log_sql_child_exit(server_rec *s, apr_pool_t *p)
421{
422 if (global_config.driver)
423 global_config.driver->disconnect(&global_config.db);
424}
425#endif
426
427/* Child Init */
428#if defined(WITH_APACHE20)
429static void log_sql_child_init(apr_pool_t *p, server_rec *s)
430#elif defined(WITH_APACHE13)
431static void log_sql_child_init(server_rec *s, apr_pool_t *p)
432#endif
433{
434 logsql_opendb_ret retval;
435# if defined(WITH_APACHE20)
436 /* Register cleanup hook to close DDB connection (apache 2 doesn't have child_exit) */
437 apr_pool_cleanup_register(p, NULL, log_sql_close_link, log_sql_close_link);
438# endif
439 /* Open a link to the database */
440 retval = log_sql_opendb_link(s);
441 switch (retval) {
442 case LOGSQL_OPENDB_FAIL:
443 if (global_config.driver==NULL) {
444 log_error(APLOG_MARK, APLOG_ERR, 0, s,
445 "mod_log_sql: Driver module not loaded");
446 } else {
447 log_error(APLOG_MARK, APLOG_ERR, 0, s,
448 "mod_log_sql: child spawned but unable to open database link");
449 }
450 break;
451 case LOGSQL_OPENDB_SUCCESS:
452 case LOGSQL_OPENDB_ALREADY:
453 log_error(APLOG_MARK,APLOG_DEBUG,0, s,
454 "mod_log_sql: open_logdb_link successful");
455 break;
456 case LOGSQL_OPENDB_PRESERVE:
457 log_error(APLOG_MARK,APLOG_DEBUG, 0, s,
458 "mod_log_sql: open_logdb_link said that preservation is forced");
459 break;
460 }
461}
462
463/* post_config / module_init */
464#if defined(WITH_APACHE20)
465static int log_sql_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
466#elif defined(WITH_APACHE13)
467static void log_sql_module_init(server_rec *s, apr_pool_t *p)
468#endif
469{
470 /* TODO: Add local_address, remote_address, server_name, connection_status */
471 /* Register handlers */
472 log_sql_register_item(s,p,'A', extract_agent, "agent", 1, 1);
473 log_sql_register_item(s,p,'a', extract_request_query, "request_args", 1, 1);
474 log_sql_register_item(s,p,'b', extract_bytes_sent, "bytes_sent", 0, 0);
475 log_sql_register_item(s,p,'c', extract_cookie, "cookie", 0, 1);
476 /* TODO: Document */
477 log_sql_register_item(s,p,'f', extract_request_file, "request_file", 0, 1);
478 log_sql_register_item(s,p,'H', extract_request_protocol, "request_protocol", 0, 1);
479 log_sql_register_item(s,p,'h', extract_remote_host, "remote_host", 0, 1);
480 log_sql_register_item(s,p,'I', extract_unique_id, "id", 0, 1);
481 log_sql_register_item(s,p,'l', extract_remote_logname, "remote_logname", 0, 1);
482 log_sql_register_item(s,p,'m', extract_request_method, "request_method", 0, 1);
483 log_sql_register_item(s,p,'M', extract_machine_id, "machine_id", 0, 1);
484 log_sql_register_item(s,p,'P', extract_child_pid, "child_pid", 0, 0);
485 log_sql_register_item(s,p,'p', extract_server_port, "server_port", 0, 0);
486 log_sql_register_item(s,p,'R', extract_referer, "referer", 1, 1);
487 log_sql_register_item(s,p,'r', extract_request_line, "request_line", 1, 1);
488 log_sql_register_item(s,p,'S', extract_request_timestamp, "time_stamp", 0, 0);
489 log_sql_register_item(s,p,'s', extract_status, "status", 1, 0);
490 log_sql_register_item(s,p,'T', extract_request_duration, "request_duration", 1, 0);
491 log_sql_register_item(s,p,'t', extract_request_time, "request_time", 0, 1);
492 log_sql_register_item(s,p,'u', extract_remote_user, "remote_user", 0, 1);
493 log_sql_register_item(s,p,'U', extract_request_uri, "request_uri", 1, 1);
494 log_sql_register_item(s,p,'v', extract_virtual_host, "virtual_host", 0, 1);
495 log_sql_register_item(s,p,'V', extract_server_name, "virtual_host", 0, 1);
496
497 if (global_config.announce) {
498 ap_add_version_component(p, PACKAGE_NAME"/"PACKAGE_VERSION);
499 }
500 /* ap_server_root_relative any default preserve file locations */
501 {
502 server_rec *cur_s;
503 const char *default_p = ap_server_root_relative(p, DEFAULT_PRESERVE_FILE);
504 for (cur_s = s; cur_s != NULL; cur_s= cur_s->next) {
505 logsql_state *cls = ap_get_module_config(cur_s->module_config,
506 &log_sql_module);
507 if (cls->preserve_file == DEFAULT_PRESERVE_FILE)
508 cls->preserve_file = default_p;
509 }
510 }
511 global_config.db.p = p;
512
513#if defined(WITH_APACHE20)
514 return OK;
515#endif
516}
517
518/* This function handles calling the DB module, handling errors
519 * of missing tables and lost DB connections, and falling back to
520 * preserving the DB query.
521 *
522 * Parms: request record, table type, table name, and the full SQL command
523 */
524
525static logsql_query_ret safe_sql_insert(request_rec *r, logsql_tabletype table_type,
526 const char *table_name, const char *query) {
527
528 logsql_query_ret result;
529 logsql_state *cls = ap_get_module_config(r->server->module_config,
530 &log_sql_module);
531
532 if (!global_config.db.connected || global_config.driver == NULL) {
533 /* preserve query */
534 return LOGSQL_QUERY_NOLINK;
535 }
536
537 result = global_config.driver->insert(r,&global_config.db,query);
538
539 /* If we ran the query and it returned an error, try to be robust.
540 * (After all, the module thought it had a valid mysql_log connection but the query
541 * could have failed for a number of reasons, so we have to be extra-safe and check.) */
542 switch (result) {
543 case LOGSQL_QUERY_SUCCESS:
544 return LOGSQL_QUERY_SUCCESS;
545 case LOGSQL_QUERY_NOLINK:
546 return LOGSQL_QUERY_FAIL;
547 /* TODO: What do we do here */
548 case LOGSQL_QUERY_FAIL:
549 global_config.driver->disconnect(&global_config.db);
550 global_config.db.connected = 0;
551 /* re-open the connection and try again */
552 if (log_sql_opendb_link(r->server) != LOGSQL_OPENDB_FAIL) {
553 log_error(APLOG_MARK,APLOG_NOTICE,0, r->server,"db reconnect successful");
554# if defined(WITH_APACHE20)
555 apr_sleep(apr_time_from_sec(0.25)); /* pause for a quarter second */
556# elif defined(WITH_APACHE13)
557# if defined(WIN32)
558 Sleep((DWORD)0.25);
559# else
560 {
561 struct timespec delay, remainder;
562 int nanoret;
563 delay.tv_sec = 0;
564 delay.tv_nsec = 250000000; /* pause for a quarter second */
565 nanoret = nanosleep(&delay, &remainder);
566 if (nanoret && errno != EINTR) {
567 log_error(APLOG_MARK,APLOG_ERR, errno, r->server,"nanosleep unsuccessful");
568 }
569 }
570# endif /* win32 */
571# endif
572 result = global_config.driver->insert(r,&global_config.db,query);
573 if (result == LOGSQL_QUERY_SUCCESS) {
574 return LOGSQL_QUERY_SUCCESS;
575 } else {
576 log_error(APLOG_MARK,APLOG_ERR,0,r->server,"second attempt failed");
577 preserve_entry(r, query);
578 return LOGSQL_QUERY_PRESERVED;
579 }
580 } else {
581 log_error(APLOG_MARK,APLOG_ERR,0,r->server,
582 "reconnect failed, unable to reach database. SQL logging stopped until child regains a db connection.");
583 log_error(APLOG_MARK,APLOG_ERR,0,r->server,
584 "log entries are being preserved in %s",cls->preserve_file);
585 preserve_entry(r, query);
586 return LOGSQL_QUERY_PRESERVED;
587 }
588 break;
589 case LOGSQL_QUERY_NOTABLE:
590 if (global_config.createtables) {
591 log_error(APLOG_MARK,APLOG_ERR,0,r->server,
592 "table doesn't exist...creating now");
593 if ((result = global_config.driver->create_table(r, &global_config.db, table_type,
594 table_name))!=LOGSQL_TABLE_SUCCESS) {
595 log_error(APLOG_MARK,APLOG_ERR,result,r->server,
596 "child attempted but failed to create one or more tables for %s, preserving query", ap_get_server_name(r));
597 preserve_entry(r, query);
598 return LOGSQL_QUERY_PRESERVED;
599 } else {
600 log_error(APLOG_MARK,APLOG_ERR,result, r->server,
601 "tables successfully created - retrying query");
602 if ((result = global_config.driver->insert(r,&global_config.db,query))!=LOGSQL_QUERY_SUCCESS) {
603 log_error(APLOG_MARK,APLOG_ERR,result, r->server,
604 "giving up, preserving query");
605 preserve_entry(r, query);
606 return LOGSQL_QUERY_PRESERVED;
607 } else {
608 log_error(APLOG_MARK,APLOG_NOTICE,0, r->server,
609 "query successful after table creation");
610 return LOGSQL_QUERY_SUCCESS;
611 }
612 }
613 } else {
614 log_error(APLOG_MARK,APLOG_ERR,0,r->server,
615 "table doesn't exist, creation denied by configuration, preserving query");
616 preserve_entry(r, query);
617 return LOGSQL_QUERY_PRESERVED;
618 }
619 break;
620 default:
621 log_error(APLOG_MARK,APLOG_ERR,0, r->server,
622 "Invalid return code from mog_log_query");
623 return LOGSQL_QUERY_FAIL;
624 break;
625 }
626 return LOGSQL_QUERY_FAIL;
627}
628
629/* This function gets called to create a per-server configuration
630 * record. It will always be called for the main server and
631 * for each virtual server that is established. Each server maintains
632 * its own state that is separate from the others' states.
633 *
634 * The return value is a pointer to the created module-specific
635 * structure.
636 */
637static void *log_sql_make_state(apr_pool_t *p, server_rec *s)
638{
639 logsql_state *cls = (logsql_state *) apr_pcalloc(p, sizeof(logsql_state));
640
641 /* These defaults are overridable in the httpd.conf file. */
642 cls->transfer_log_format = DEFAULT_TRANSFER_LOG_FMT;
643 apr_pool_create(&cls->parsed_pool, p);
644 cls->parsed_log_format = apr_pcalloc(cls->parsed_pool,
645 strlen(cls->transfer_log_format) * sizeof(logsql_item *));
646 cls->notes_table_name = DEFAULT_NOTES_TABLE_NAME;
647 cls->hin_table_name = DEFAULT_HIN_TABLE_NAME;
648 cls->hout_table_name = DEFAULT_HOUT_TABLE_NAME;
649 cls->cookie_table_name = DEFAULT_COOKIE_TABLE_NAME;
650 cls->preserve_file = DEFAULT_PRESERVE_FILE;
651
652 cls->transfer_ignore_list = apr_array_make(p, 1, sizeof(char *));
653 cls->transfer_accept_list = apr_array_make(p, 1, sizeof(char *));
654 cls->remhost_ignore_list = apr_array_make(p, 1, sizeof(char *));
655 cls->notes_list = apr_array_make(p, 1, sizeof(char *));
656 cls->hin_list = apr_array_make(p, 1, sizeof(char *));
657 cls->hout_list = apr_array_make(p, 1, sizeof(char *));
658 cls->cookie_list = apr_array_make(p, 1, sizeof(char *));
659
660 return (void *) cls;
661}
662
663
664/* Iterates through an array of char* and searches for a matching element
665 * Returns 0 if not found, 1 if found */
666static int in_array(apr_array_header_t *ary, const char *elem)
667{
668 int itr;
669 for (itr = 0; itr < ary->nelts; itr++) {
670 if (!strcmp(elem,((char **)ary->elts)[itr])) {
671 return 1;
672 }
673 }
674 return 0;
675}
676
677
678/* Parse through cookie lists and merge based on +/- prefixes */
679/* TODO: rewrite as a function */
680#define DO_MERGE_ARRAY(parent,child,pool) \
681if (apr_is_empty_array(child)) { \
682 apr_array_cat(child, parent); \
683} else { \
684 apr_array_header_t *addlist, *dellist; \
685 char **elem, **ptr = (char **)(child->elts); \
686 int itr, overwrite = 0; \
687 addlist = apr_array_make(pool,5,sizeof(char *)); \
688 dellist = apr_array_make(subp,5,sizeof(char *)); \
689\
690 for (itr=0; itr<child->nelts; itr++) { \
691 if (*ptr[itr] == '+') { \
692 elem = (char **)apr_array_push(addlist); \
693 *elem = (ptr[itr]+1); \
694 } else if (*ptr[itr] == '-') { \
695 elem = (char **)apr_array_push(dellist); \
696 *elem = (ptr[itr]+1); \
697 } else { \
698 overwrite = 1; \
699 elem = (char **)apr_array_push(addlist); \
700 *elem = ptr[itr]; \
701 } \
702 } \
703 child = apr_array_make(p,1,sizeof(char *)); \
704 ptr = (char **)(parent->elts); \
705 if (overwrite==0) { \
706 /* if we are not overwriting the existing then prepare for merge */ \
707 for (itr=0; itr<parent->nelts; itr++) { \
708 if (!in_array(addlist, ptr[itr]) && !in_array(dellist,ptr[itr])) { \
709 elem = apr_array_push(child); \
710 *elem = apr_pstrdup(p, ptr[itr]); \
711 } \
712 } \
713 } \
714 apr_array_cat(child, addlist); \
715}
716
717static void *log_sql_merge_state(apr_pool_t *p, void *basev, void *addv)
718{
719 /* Fetch the two states to merge */
720 logsql_state *parent = (logsql_state *) basev;
721 logsql_state *child = (logsql_state *) addv;
722
723 apr_pool_t *subp;
724
725 apr_pool_create(&subp,p);
726
727 /* Child can override these, otherwise they default to parent's choice.
728 * If the parent didn't set them, create reasonable defaults for the
729 * ones that should have such default settings. Leave the others null. */
730
731 /* No default for transfer_table_name because we want its absence
732 * to disable logging. */
733 if (!child->transfer_table_name) {
734 child->transfer_table_name = parent->transfer_table_name;
735 }
736
737 if (child->transfer_log_format == DEFAULT_TRANSFER_LOG_FMT) {
738 child->transfer_log_format = parent->transfer_log_format;
739 /*apr_pool_clear(child->parsed_pool);*/
740 child->parsed_log_format = apr_pcalloc(child->parsed_pool,
741 strlen(child->transfer_log_format) * sizeof(logsql_item *));
742 }
743
744 if (child->preserve_file == DEFAULT_PRESERVE_FILE)
745 child->preserve_file = parent->preserve_file;
746 /* server_root_relative the preserve file location */
747 if (child->preserve_file == DEFAULT_PRESERVE_FILE)
748 child->preserve_file = ap_server_root_relative(p, DEFAULT_PRESERVE_FILE);
749
750 if (child->notes_table_name == DEFAULT_NOTES_TABLE_NAME)
751 child->notes_table_name = parent->notes_table_name;
752
753 if (child->hin_table_name == DEFAULT_HIN_TABLE_NAME)
754 child->hin_table_name = parent->hin_table_name;
755
756 if (child->hout_table_name == DEFAULT_HOUT_TABLE_NAME)
757 child->hout_table_name = parent->hout_table_name;
758
759 if (child->cookie_table_name == DEFAULT_COOKIE_TABLE_NAME)
760 child->cookie_table_name = parent->cookie_table_name;
761
762 DO_MERGE_ARRAY(parent->transfer_ignore_list, child->transfer_ignore_list, subp);
763 DO_MERGE_ARRAY(parent->transfer_accept_list, child->transfer_accept_list, subp);
764 DO_MERGE_ARRAY(parent->remhost_ignore_list, child->remhost_ignore_list, subp);
765 DO_MERGE_ARRAY(parent->notes_list, child->notes_list, subp);
766 DO_MERGE_ARRAY(parent->hin_list, child->hin_list, subp);
767 DO_MERGE_ARRAY(parent->hout_list, child->hout_list, subp);
768 DO_MERGE_ARRAY(parent->cookie_list,child->cookie_list, subp);
769
770 apr_pool_destroy(subp);
771
772 if (!child->cookie_name)
773 child->cookie_name = parent->cookie_name;
774
775
776 return (void*) child;
777}
778
779/* Routine to perform the actual construction and execution of the relevant
780 * INSERT statements.
781 */
782static int log_sql_transaction(request_rec *orig)
783{
784 char **ptrptr, **ptrptr2;
785 logsql_state *cls = ap_get_module_config(orig->server->module_config, &log_sql_module);
786 const char *access_query;
787 request_rec *r;
788 const char *transfer_tablename = cls->transfer_table_name;
789 const char *notes_tablename = cls->notes_table_name;
790 const char *hout_tablename = cls->hout_table_name;
791 const char *hin_tablename = cls->hin_table_name;
792 const char *cookie_tablename = cls->cookie_table_name;
793 if (global_config.driver == NULL) {
794 return OK;
795 }
796 /* We handle mass virtual hosting differently. Dynamically determine the name
797 * of the table from the virtual server's name, and flag it for creation.
798 */
799 if (global_config.massvirtual) {
800 /* TODO: Make these configurable? */
801 char *access_base = "access_";
802 char *notes_base = "notes_";
803 char *hout_base = "headout_";
804 char *hin_base = "headin_";
805 char *cookie_base = "cookies_";
806
807
808 /* Determine the hostname and convert it to all lower-case; */
809 char *servername = apr_pstrdup(orig->pool,(char *)ap_get_server_name(orig));
810
811 char *p=servername;
812 while (*p) {
813 *p = apr_tolower(*p);
814 if (*p == '.') *p = '_';
815 if (*p == '-') *p = '_';
816 ++p;
817 }
818
819 /* Find memory long enough to hold the table name + \0. */
820 transfer_tablename = apr_pstrcat(orig->pool, access_base, servername, NULL);
821 notes_tablename = apr_pstrcat(orig->pool, notes_base, servername, NULL);
822 hin_tablename = apr_pstrcat(orig->pool, hin_base, servername, NULL);
823 hout_tablename = apr_pstrcat(orig->pool, hout_base, servername, NULL);
824 cookie_tablename = apr_pstrcat(orig->pool, cookie_base, servername, NULL);
825
826 /* Tell this virtual server its transfer table name, and
827 * turn on create_tables, which is implied by massvirtual.
828 */
829
830 global_config.createtables = 1;
831 }
832
833 /* Do we have enough info to log? */
834 if (!transfer_tablename) {
835 return DECLINED;
836 } else {
837 const char *thehost;
838 const char *theitem;
839 char *fields = "", *values = "";
840 char *itemsets = "";
841 char *note_query = NULL;
842 char *hin_query = NULL;
843 char *hout_query = NULL;
844 char *cookie_query = NULL;
845 const char *unique_id;
846 const char *formatted_item;
847 int i,length;
848 int proceed;
849
850 for (r = orig; r->next; r = r->next) {
851 continue;
852 }
853
854 /* The following is a stolen upsetting mess of pointers, I'm sorry.
855 * Anyone with the motiviation and/or the time should feel free
856 * to make this cleaner. :) */
857 ptrptr2 = (char **) (cls->transfer_accept_list->elts + (cls->transfer_accept_list->nelts * cls->transfer_accept_list->elt_size));
858
859 /* Go through each element of the accept list and compare it to the
860 * request_uri. If we don't get a match, return without logging */
861 if ((r->uri) && (cls->transfer_accept_list->nelts)) {
862 proceed = 0;
863 for (ptrptr = (char **) cls->transfer_accept_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->transfer_accept_list->elt_size))
864 if (ap_strstr(r->uri, *ptrptr)) {
865 proceed = 1;
866 break;
867 }
868 if (!proceed)
869 return OK;
870 }
871
872 /* Go through each element of the ignore list and compare it to the
873 * request_uri. If we get a match, return without logging */
874 ptrptr2 = (char **) (cls->transfer_ignore_list->elts + (cls->transfer_ignore_list->nelts * cls->transfer_ignore_list->elt_size));
875 if (r->uri) {
876 for (ptrptr = (char **) cls->transfer_ignore_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->transfer_ignore_list->elt_size))
877 if (ap_strstr(r->uri, *ptrptr)) {
878 return OK;
879 }
880 }
881
882 /* Go through each element of the ignore list and compare it to the
883 * remote host. If we get a match, return without logging */
884 ptrptr2 = (char **) (cls->remhost_ignore_list->elts + (cls->remhost_ignore_list->nelts * cls->remhost_ignore_list->elt_size));
885 thehost = ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME, NULL);
886 if (thehost) {
887 for (ptrptr = (char **) cls->remhost_ignore_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->remhost_ignore_list->elt_size))
888 if (ap_strstr(thehost, *ptrptr)) {
889 return OK;
890 }
891 }
892
893
894 /* Iterate through the format characters and set up the INSERT string according to
895 * what the user has configured. */
896 length = strlen(cls->transfer_log_format);
897 for (i = 0; i<length; i++) {
898 logsql_item *item = cls->parsed_log_format[i];
899 if (item==NULL) {
900 log_error(APLOG_MARK, APLOG_ERR, 0, orig->server,
901 "Log Format '%c' unknown",cls->transfer_log_format[i]);
902 continue;
903 }
904
905 /* Yes, this key is one of the configured keys.
906 * Call the key's function and put the returned value into 'formatted_item' */
907 formatted_item = item->func(item->want_orig_default ? orig : r, "");
908
909 /* Massage 'formatted_item' for proper SQL eligibility... */
910 if (!formatted_item) {
911 formatted_item = "";
912 } else if (formatted_item[0] == '-' && formatted_item[1] == '\0' && !item->string_contents) {
913 /* If apache tried to log a '-' character for a numeric field, convert that to a zero
914 * because the database expects a numeral and will reject the '-' character. */
915 formatted_item = "0";
916 }
917
918 /* Append the fieldname and value-to-insert to the appropriate strings, quoting stringvals with ' as appropriate */
919 fields = apr_pstrcat(r->pool, fields, (i ? "," : ""),
920 item->sql_field_name, NULL);
921 values = apr_pstrcat(r->pool, values, (i ? "," : ""),
922 global_config.driver->escape(formatted_item, r->pool,&global_config.db), NULL);
923 }
924
925 /* Work through the list of notes defined by LogSQLWhichNotes */
926 i = 0;
927 unique_id = extract_unique_id(r, "");
928
929 ptrptr2 = (char **) (cls->notes_list->elts + (cls->notes_list->nelts * cls->notes_list->elt_size));
930 for (ptrptr = (char **) cls->notes_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->notes_list->elt_size)) {
931 /* If the specified note (*ptrptr) exists for the current request... */
932 if ((theitem = apr_table_get(r->notes, *ptrptr))) {
933 itemsets = apr_pstrcat(r->pool, itemsets,
934 (i > 0 ? "," : ""),
935 "(",
936 global_config.driver->escape(unique_id, r->pool, &global_config.db),
937 ",",
938 global_config.driver->escape(*ptrptr, r->pool,&global_config.db),
939 ",",
940 global_config.driver->escape(theitem, r->pool,&global_config.db),
941 ")",
942 NULL);
943 i++;
944 }
945 }
946 if ( *itemsets != '\0' ) {
947 note_query = apr_psprintf(r->pool, "insert %s into %s (id, item, val) values %s",
948 /*global_config.insertdelayed?"delayed":*/"", notes_tablename, itemsets);
949
950 log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: note string: %s", note_query);
951 }
952
953 /* Work through the list of headers-out defined by LogSQLWhichHeadersOut*/
954 i = 0;
955 itemsets = "";
956
957 ptrptr2 = (char **) (cls->hout_list->elts + (cls->hout_list->nelts * cls->hout_list->elt_size));
958 for (ptrptr = (char **) cls->hout_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->hout_list->elt_size)) {
959 /* If the specified header (*ptrptr) exists for the current request... */
960 if ((theitem = apr_table_get(r->headers_out, *ptrptr))) {
961 itemsets = apr_pstrcat(r->pool, itemsets,
962 (i > 0 ? "," : ""),
963 "(",
964 global_config.driver->escape(unique_id, r->pool, &global_config.db),
965 ",",
966 global_config.driver->escape(*ptrptr, r->pool,&global_config.db),
967 ",",
968 global_config.driver->escape(theitem, r->pool,&global_config.db),
969 ")",
970 NULL);
971 i++;
972 }
973 }
974 if ( *itemsets != '\0' ) {
975 hout_query = apr_psprintf(r->pool, "insert %s into %s (id, item, val) values %s",
976 /*global_config.insertdelayed?"delayed":*/"", hout_tablename, itemsets);
977
978 log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: header_out string: %s", hout_query);
979 }
980
981
982 /* Work through the list of headers-in defined by LogSQLWhichHeadersIn */
983 i = 0;
984 itemsets = "";
985
986 ptrptr2 = (char **) (cls->hin_list->elts + (cls->hin_list->nelts * cls->hin_list->elt_size));
987 for (ptrptr = (char **) cls->hin_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->hin_list->elt_size)) {
988 /* If the specified header (*ptrptr) exists for the current request... */
989 if ((theitem = apr_table_get(r->headers_in, *ptrptr))) {
990 itemsets = apr_pstrcat(r->pool, itemsets,
991 (i > 0 ? "," : ""),
992 "(",
993 global_config.driver->escape(unique_id, r->pool, &global_config.db),
994 ",",
995 global_config.driver->escape(*ptrptr, r->pool,&global_config.db),
996 ",",
997 global_config.driver->escape(theitem, r->pool,&global_config.db),
998 ")",
999 NULL);
1000 i++;
1001 }
1002 }
1003 if ( *itemsets != '\0' ) {
1004 hin_query = apr_psprintf(r->pool, "insert %s into %s (id, item, val) values %s",
1005 /*global_config.insertdelayed?"delayed":*/"", hin_tablename, itemsets);
1006
1007 log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: header_in string: %s", hin_query);
1008 }
1009
1010
1011 /* Work through the list of cookies defined by LogSQLWhichCookies */
1012 i = 0;
1013 itemsets = "";
1014
1015 ptrptr2 = (char **) (cls->cookie_list->elts + (cls->cookie_list->nelts * cls->cookie_list->elt_size));
1016 for (ptrptr = (char **) cls->cookie_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->cookie_list->elt_size)) {
1017 /* If the specified cookie (*ptrptr) exists for the current request... */
1018 if ( strncmp((theitem = extract_specific_cookie(r, *ptrptr)), "-", 1) ) {
1019 itemsets = apr_pstrcat(r->pool, itemsets,
1020 (i > 0 ? "," : ""),
1021 "(",
1022 global_config.driver->escape(unique_id, r->pool, &global_config.db),
1023 ",",
1024 global_config.driver->escape(*ptrptr, r->pool,&global_config.db),
1025 ",",
1026 global_config.driver->escape(theitem, r->pool,&global_config.db),
1027 ")",
1028 NULL);
1029 i++;
1030 }
1031
1032 }
1033 if ( *itemsets != '\0' ) {
1034 cookie_query = apr_psprintf(r->pool, "insert %s into %s (id, item, val) values %s",
1035 /*global_config.insertdelayed?"delayed":*/"", cookie_tablename, itemsets);
1036
1037 log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: cookie string: %s", cookie_query);
1038 }
1039
1040
1041 /* Set up the actual INSERT statement */
1042 access_query = apr_psprintf(r->pool, "insert %s into %s (%s) values (%s)",
1043 /*global_config.insertdelayed?"delayed":*/"", transfer_tablename, fields, values);
1044
1045 log_error(APLOG_MARK,APLOG_DEBUG,0, r->server,"mod_log_sql: access string: %s", access_query);
1046
1047 /* If the person activated force-preserve, go ahead and push all the entries
1048 * into the preserve file, then return.
1049 */
1050 if (global_config.forcepreserve) {
1051 log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: preservation forced");
1052 preserve_entry(orig, access_query);
1053 if ( note_query != NULL )
1054 preserve_entry(orig, note_query);
1055 if ( hin_query != NULL )
1056 preserve_entry(orig, hin_query);
1057 if ( hout_query != NULL )
1058 preserve_entry(orig, hout_query);
1059 if ( cookie_query != NULL )
1060 preserve_entry(orig, cookie_query);
1061 return OK;
1062 }
1063
1064 /* How's our mysql link integrity? */
1065 if (!global_config.db.connected) {
1066 if (!global_config.forcepreserve) {
1067 /* Make a try to establish the link */
1068 log_sql_opendb_link(r->server);
1069 }
1070 if (!global_config.db.connected) {
1071 /* Unable to re-establish a DB link, so assume that it's really
1072 * gone and send the entry to the preserve file instead.
1073 * This short-circuits safe_sql_query() during a db outage and therefore
1074 * we don't keep logging the db error over and over.
1075 */
1076 preserve_entry(orig, access_query);
1077 if ( note_query != NULL )
1078 preserve_entry(orig, note_query);
1079 if ( hin_query != NULL )
1080 preserve_entry(orig, hin_query);
1081 if ( hout_query != NULL )
1082 preserve_entry(orig, hout_query);
1083 if ( cookie_query != NULL )
1084 preserve_entry(orig, cookie_query);
1085
1086 return OK;
1087 } else {
1088 /* Whew, we got the DB link back */
1089 log_error(APLOG_MARK,APLOG_NOTICE,0, orig->server,"mod_log_sql: child established database connection");
1090 }
1091 }
1092
1093
1094 /* ---> So as of here we have a non-null value of mysql_log. <--- */
1095 /* ---> i.e. we have a good MySQL connection. <--- */
1096
1097 /* Make the access-table insert */
1098 safe_sql_insert(orig,LOGSQL_TABLE_ACCESS,transfer_tablename,access_query);
1099
1100 /* Log the optional notes, headers, etc. */
1101 if (note_query)
1102 safe_sql_insert(orig, LOGSQL_TABLE_NOTES,notes_tablename,note_query);
1103
1104 if (hout_query)
1105 safe_sql_insert(orig, LOGSQL_TABLE_HEADERSOUT,hout_tablename,hout_query);
1106
1107 if (hin_query)
1108 safe_sql_insert(orig, LOGSQL_TABLE_HEADERSIN,hin_tablename,hin_query);
1109
1110 if (cookie_query)
1111 safe_sql_insert(orig, LOGSQL_TABLE_COOKIES,cookie_tablename,cookie_query);
1112
1113 return OK;
1114 }
1115}
1116
1117
1118/* Setup of the available httpd.conf configuration commands.
1119 * Structure: command, function called, NULL, where available, how many arguments, verbose description
1120 */
1121static const command_rec log_sql_cmds[] = {
1122 AP_INIT_FLAG("LogSQLAnnounce", set_global_flag_slot,
1123 (void *)APR_OFFSETOF(global_config_t, announce), RSRC_CONF,
1124 "Whether to announce that mod_log_sql is loaded in the server header")
1125 ,
1126 /* DB connection parameters */
1127 AP_INIT_TAKE13("LogSQLLoginInfo", set_log_sql_info, NULL, RSRC_CONF,
1128 "The database connection URI in the form &quot;driver://user:password@hostname:port/database&quot;")
1129 ,
1130 AP_INIT_TAKE2("LogSQLDBParam", set_dbparam, NULL, RSRC_CONF,
1131 "First argument is the DB parameter, second is the value to assign")
1132 ,
1133 AP_INIT_FLAG("LogSQLForcePreserve", set_global_flag_slot,
1134 (void *)APR_OFFSETOF(global_config_t, forcepreserve), RSRC_CONF,
1135 "Forces logging to preserve file and bypasses database")
1136 ,
1137 AP_INIT_FLAG("LogSQLDisablePreserve", set_global_flag_slot,
1138 (void *)APR_OFFSETOF(global_config_t, disablepreserve), RSRC_CONF,
1139 "Completely disables use of the preserve file")
1140 ,
1141 AP_INIT_TAKE1("LogSQLPreserveFile", set_server_file_slot,
1142 (void *)APR_OFFSETOF(logsql_state,preserve_file), RSRC_CONF,
1143 "Name of the file to use for data preservation during database downtime")
1144 ,
1145 AP_INIT_FLAG("LogSQLCreateTables", set_global_nmv_flag_slot,
1146 (void *)APR_OFFSETOF(global_config_t, createtables), RSRC_CONF,
1147 "Turn on module's capability to create its SQL tables on the fly")
1148 ,
1149 /* Table names */
1150 AP_INIT_FLAG("LogSQLMassVirtualHosting", set_global_flag_slot,
1151 (void *)APR_OFFSETOF(global_config_t, massvirtual), RSRC_CONF,
1152 "Activates option(s) useful for ISPs performing mass virutal hosting")
1153 ,
1154 AP_INIT_TAKE1("LogSQLTransferLogTable", set_server_nmv_string_slot,
1155 (void *)APR_OFFSETOF(logsql_state, transfer_table_name), RSRC_CONF,
1156 "The database table that holds the transfer log")
1157 ,
1158 AP_INIT_TAKE1("LogSQLNotesLogTable", set_server_nmv_string_slot,
1159 (void *)APR_OFFSETOF(logsql_state, notes_table_name), RSRC_CONF,
1160 "The database table that holds the notes")
1161 ,
1162 AP_INIT_TAKE1("LogSQLHeadersOutLogTable", set_server_nmv_string_slot,
1163 (void *)APR_OFFSETOF(logsql_state, hout_table_name), RSRC_CONF,
1164 "The database table that holds the outbound headers")
1165 ,
1166 AP_INIT_TAKE1("LogSQLHeadersInLogTable", set_server_nmv_string_slot,
1167 (void *)APR_OFFSETOF(logsql_state, hin_table_name), RSRC_CONF,
1168 "The database table that holds the inbound headers")
1169 ,
1170 AP_INIT_TAKE1("LogSQLCookieLogTable", set_server_nmv_string_slot,
1171 (void *)APR_OFFSETOF(logsql_state, cookie_table_name), RSRC_CONF,
1172 "The database table that holds the cookie info")
1173 ,
1174 /* Log format */
1175 AP_INIT_TAKE1("LogSQLTransferLogFormat", set_logformat_slot,
1176 NULL, RSRC_CONF,
1177 "Instruct the module what information to log to the database transfer log")
1178 ,
1179 /* Machine ID */
1180 AP_INIT_TAKE1("LogSQLMachineID", set_global_string_slot,
1181 (void *)APR_OFFSETOF(global_config_t, machid), RSRC_CONF,
1182 "Machine ID that the module will log, useful in web clusters to differentiate machines")
1183 ,
1184 /* Limits on logging */
1185 AP_INIT_ITERATE("LogSQLRequestAccept", add_server_string_slot,
1186 (void *)APR_OFFSETOF(logsql_state, transfer_accept_list), RSRC_CONF,
1187 "List of URIs to accept for logging. Accesses that don't match will not be logged")
1188 ,
1189 AP_INIT_ITERATE("LogSQLRequestIgnore", add_server_string_slot,
1190 (void *)APR_OFFSETOF(logsql_state, transfer_ignore_list), RSRC_CONF,
1191 "List of URIs to ignore. Accesses that match will not be logged to database")
1192 ,
1193 AP_INIT_ITERATE("LogSQLRemhostIgnore", add_server_string_slot,
1194 (void *)APR_OFFSETOF(logsql_state, remhost_ignore_list), RSRC_CONF,
1195 "List of remote hosts to ignore. Accesses that match will not be logged to database")
1196 ,
1197 /* Special loggin table configuration */
1198 AP_INIT_TAKE1("LogSQLWhichCookie", set_server_string_slot,
1199 (void *)APR_OFFSETOF(logsql_state, cookie_name), RSRC_CONF,
1200 "The single cookie that you want logged in the access_log when using the 'c' config directive")
1201 ,
1202 AP_INIT_ITERATE("LogSQLWhichNotes", add_server_string_slot,
1203 (void *)APR_OFFSETOF(logsql_state, notes_list), RSRC_CONF,
1204 "Notes that you would like to log in a separate table")
1205 ,
1206 AP_INIT_ITERATE("LogSQLWhichHeadersOut", add_server_string_slot,
1207 (void *)APR_OFFSETOF(logsql_state, hout_list), RSRC_CONF,
1208 "Outbound headers that you would like to log in a separate table")
1209 ,
1210 AP_INIT_ITERATE("LogSQLWhichHeadersIn", add_server_string_slot,
1211 (void *)APR_OFFSETOF(logsql_state, hin_list), RSRC_CONF,
1212 "Inbound headers that you would like to log in a separate table")
1213 ,
1214 AP_INIT_ITERATE("LogSQLWhichCookies", add_server_string_slot,
1215 (void *)APR_OFFSETOF(logsql_state, cookie_list), RSRC_CONF,
1216 "The cookie(s) that you would like to log in a separate table")
1217 ,
1218 AP_INIT_RAW_ARGS("LogSQLDeprecated", ap_set_deprecated, NULL, RSRC_CONF,
1219 "<br><b>Deprecated</b><br>The following Commands are deprecated and should not be used.. <br>Read the documentation for more information<br><b>Deprecated</b>")
1220 ,
1221 /* Deprecated commands */
1222 AP_INIT_TAKE1("LogSQLDatabase", set_dbparam_slot,
1223 (void *)"database", RSRC_CONF,
1224 "<b>(Deprecated) Use LogSQLDBParam database dbname.</b> The name of the database database for logging")
1225 ,
1226 AP_INIT_TAKE1("LogSQLTableType", set_dbparam_slot,
1227 (void *)"tabletype", RSRC_CONF,
1228 "<b>(Deprecated) Use LogSQLDBParam tabletype type.</b> What kind of table to create (MyISAM, InnoDB,...) when creating tables")
1229 ,
1230 AP_INIT_TAKE1("LogSQLSocketFile", set_dbparam_slot,
1231 (void *)"socketfile", RSRC_CONF,
1232 "<b>(Deprecated) Use LogSQLDBParam socketfile socket.</b> Name of the file to employ for socket connections to database")
1233 ,
1234 AP_INIT_TAKE1("LogSQLTCPPort", set_dbparam_slot,
1235 (void *)"port", RSRC_CONF,
1236 "<b>(Deprecated) Use LogSQLDBParam port port.</b> Port number to use for TCP connections to database, defaults to 3306 if not set")
1237 ,
1238 {NULL}
1239};
1240/* The configuration array that sets up the hooks into the module. */
1241#if defined(WITH_APACHE20)
1242static void register_hooks(apr_pool_t *p) {
1243 ap_hook_post_config(log_sql_post_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
1244 ap_hook_child_init(log_sql_child_init, NULL, NULL, APR_HOOK_MIDDLE);
1245 ap_hook_log_transaction(log_sql_transaction, NULL, NULL, APR_HOOK_MIDDLE);
1246}
1247
1248module AP_MODULE_DECLARE_DATA log_sql_module = {
1249 STANDARD20_MODULE_STUFF,
1250 NULL, /* create per-directory config structures */
1251 NULL, /* merge per-directory config structures */
1252 log_sql_make_state, /* create per-server config structures */
1253 log_sql_merge_state, /* merge per-server config structures */
1254 log_sql_cmds, /* command handlers */
1255 register_hooks /* register hooks */
1256};
1257#elif defined(WITH_APACHE13)
1258module MODULE_VAR_EXPORT log_sql_module = {
1259 STANDARD_MODULE_STUFF,
1260 log_sql_module_init, /* module initializer */
1261 NULL, /* create per-dir config */
1262 NULL, /* merge per-dir config */
1263 log_sql_make_state, /* create server config */
1264 log_sql_merge_state, /* merge server config */
1265 log_sql_cmds, /* config directive table */
1266 NULL, /* [9] content handlers */
1267 NULL, /* [2] URI-to-filename translation */
1268 NULL, /* [5] check/validate user_id */
1269 NULL, /* [6] check authorization */
1270 NULL, /* [4] check access by host */
1271 NULL, /* [7] MIME type checker/setter */
1272 NULL, /* [8] fixups */
1273 log_sql_transaction, /* [10] logger */
1274 NULL /* [3] header parser */
1275#if MODULE_MAGIC_NUMBER >= 19970728 /* 1.3-dev or later support these additionals... */
1276 ,log_sql_child_init, /* child process initializer */
1277 log_sql_child_exit, /* process exit/cleanup */
1278 NULL /* [1] post read-request */
1279#endif
1280
1281};
1282#endif