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.c468
1 files changed, 201 insertions, 267 deletions
diff --git a/mod_log_sql.c b/mod_log_sql.c
index 5bb992b..efbf45c 100644
--- a/mod_log_sql.c
+++ b/mod_log_sql.c
@@ -1,85 +1,11 @@
1/* $Id: mod_log_sql.c,v 1.3 2001/12/03 19:54:02 helios Exp $ 1/* $Id: mod_log_sql.c,v 1.4 2001/12/07 03:52:56 helios Exp $ */
2 *
3 * mod_log_mysql.c
4 * Release v 1.10
5 *
6 * Hi, I'm the new maintainer of this code. If you have any questions,
7 * comments or suggestions (which are always welcome), please contact Chris
8 * Powell <chris@grubbybaby.com>. This code still falls under the rules of
9 * the Apache license, and all credit for the code up to my changes is still
10 * preserved below.
11 *
12 * ====================================================================
13 *
14 * The original preface from version 1.05: This module was patched, wrapped
15 * and coded by Zeev Suraski <bourbon@netvision.net.il>
16 *
17 * It may be used freely, with the same restrictions as its predecessors
18 * (specified below). This module is based on code from standard apache
19 * modules. Their copyright notice follows.
20 *
21 * ====================================================================
22 * Copyright (c) 1995-1997 The Apache Group. All rights reserved.
23 *
24 * Redistribution and use in source and binary forms, with or without
25 * modification, are permitted provided that the following conditions
26 * are met:
27 *
28 * 1. Redistributions of source code must retain the above copyright
29 * notice, this list of conditions and the following disclaimer.
30 *
31 * 2. Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in
33 * the documentation and/or other materials provided with the
34 * distribution.
35 *
36 * 3. All advertising materials mentioning features or use of this
37 * software must display the following acknowledgment:
38 * "This product includes software developed by the Apache Group
39 * for use in the Apache HTTP server project (http://www.apache.org/)."
40 *
41 * 4. The names "Apache Server" and "Apache Group" must not be used to
42 * endorse or promote products derived from this software without
43 * prior written permission.
44 *
45 * 5. Redistributions of any form whatsoever must retain the following
46 * acknowledgment:
47 * "This product includes software developed by the Apache Group
48 * for use in the Apache HTTP server project (http://www.apache.org/)."
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
51 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
54 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
56 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
59 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
61 * OF THE POSSIBILITY OF SUCH DAMAGE.
62 * ====================================================================
63 *
64 * This software consists of voluntary contributions made by many
65 * individuals on behalf of the Apache Group and was originally based
66 * on public domain software written at the National Center for
67 * Supercomputing Applications, University of Illinois, Urbana-Champaign.
68 * For more information on the Apache Group and the Apache HTTP server
69 * project, please see <http://www.apache.org/>.
70 *
71 */
72 2
73 3
74/* DEFINES */ 4/* DEFINES */
75#define MYSQL_ERROR(mysql) ((mysql)?(mysql_error(mysql)):"MySQL server has gone away") 5#define MYSQL_ERROR(mysql) ((mysql)?(mysql_error(mysql)):"MySQL server has gone away")
76
77#define ERRLEVEL APLOG_ERR|APLOG_NOERRNO 6#define ERRLEVEL APLOG_ERR|APLOG_NOERRNO
78 7#define DEBUGLEVEL APLOG_INFO|APLOG_NOERRNO
79#undef DEBUG 8/* (DEBUG and WANT_SSL_LOGGING are defined in the Makefile DEFS line.) */
80#ifdef DEBUG
81 #define DEBUGLEVEL APLOG_INFO|APLOG_NOERRNO
82#endif
83 9
84 10
85 11
@@ -92,24 +18,35 @@
92#include "http_config.h" 18#include "http_config.h"
93#include "http_log.h" 19#include "http_log.h"
94#include "http_core.h" 20#include "http_core.h"
95#if MODULE_MAGIC_NUMBER >= 19980324 21
22/* M_M_N is defined in /usr/local/Apache/include/ap_mmn.h, 19990320 as of this writing. */
23#if MODULE_MAGIC_NUMBER >= 19980324 /* 1.3b6 or later */
96 #include "ap_compat.h" 24 #include "ap_compat.h"
97#endif 25#endif
98 26
99#ifdef WANT_SSL_LOGGING 27#ifdef WANT_SSL_LOGGING /* Defined in Makefile */
100 #include "/usr/local/src/apache_1.3.22/src/modules/ssl/mod_ssl.h" 28 #include "mod_ssl.h"
101#endif 29#endif
102 30
103 31
104 32
105/* DECLARATIONS */ 33/* DECLARATIONS */
106module mysql_log_module; 34module mysql_log_module;
107MYSQL log_sql_server, *mysql_log = NULL; 35
108char *log_db_name = NULL, *db_host = NULL, *db_user = NULL, *db_pwd = NULL, *cookie_name = NULL; 36MYSQL sql_server, *mysql_log = NULL;
37
38char *db_name = NULL;
39char *db_host = NULL;
40char *db_user = NULL;
41char *db_pwd = NULL;
42char *cookie_name = NULL;
109 43
110typedef const char *(*item_key_func) (request_rec *, char *); 44typedef const char *(*item_key_func) (request_rec *, char *);
45
111typedef struct { 46typedef struct {
112 char *referer_table_name, *agent_table_name, *transfer_table_name; 47 char *referer_table_name;
48 char *agent_table_name;
49 char *transfer_table_name;
113 array_header *referer_ignore_list; 50 array_header *referer_ignore_list;
114 array_header *transfer_ignore_list; 51 array_header *transfer_ignore_list;
115 array_header *remhost_ignore_list; 52 array_header *remhost_ignore_list;
@@ -118,29 +55,7 @@ typedef struct {
118 55
119 56
120 57
121#if MODULE_MAGIC_NUMBER < 19970103 /* Defined in /usr/local/Apache/include/ap_mmn.h, 19990320 as of this writing. */ 58/* FUNCTIONS */
122extern const char *log_request_protocol(request_rec *r, char *a);
123extern const char *log_request_method(request_rec *r, char *a);
124extern const char *log_remote_host(request_rec *r, char *a);
125extern const char *log_remote_logname(request_rec *r, char *a);
126extern const char *log_remote_user(request_rec *r, char *a);
127extern const char *log_request_time(request_rec *r, char *a);
128extern const char *log_request_timestamp(request_rec *r, char *a);
129extern const char *log_request_duration(request_rec *r, char *a);
130extern const char *log_request_line(request_rec *r, char *a);
131extern const char *log_request_file(request_rec *r, char *a);
132extern const char *log_request_uri(request_rec *r, char *a);
133extern const char *log_status(request_rec *r, char *a);
134extern const char *log_bytes_sent(request_rec *r, char *a);
135extern const char *log_header_in(request_rec *r, char *a);
136extern const char *log_header_out(request_rec *r, char *a);
137extern const char *log_note(request_rec *r, char *a);
138extern const char *log_env_var(request_rec *r, char *a);
139extern const char *log_virtual_host(request_rec *r, char *a);
140extern const char *log_server_port(request_rec *r, char *a);
141extern const char *log_child_pid(request_rec *r, char *a);
142#else
143
144static char *format_integer(pool *p, int i) 59static char *format_integer(pool *p, int i)
145{ 60{
146 char dummy[40]; 61 char dummy[40];
@@ -162,17 +77,17 @@ static char *pfmt(pool *p, int i)
162 * value to the calling entity. 77 * value to the calling entity.
163 */ 78 */
164 79
165static const char *log_remote_host(request_rec *r, char *a) 80static const char *extract_remote_host(request_rec *r, char *a)
166{ 81{
167 return (char *) get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME); 82 return (char *) get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME);
168} 83}
169 84
170static const char *log_remote_logname(request_rec *r, char *a) 85static const char *extract_remote_logname(request_rec *r, char *a)
171{ 86{
172 return (char *) get_remote_logname(r); 87 return (char *) get_remote_logname(r);
173} 88}
174 89
175static const char *log_remote_user(request_rec *r, char *a) 90static const char *extract_remote_user(request_rec *r, char *a)
176{ 91{
177 char *rvalue = r->connection->user; 92 char *rvalue = r->connection->user;
178 93
@@ -185,7 +100,7 @@ static const char *log_remote_user(request_rec *r, char *a)
185} 100}
186 101
187#ifdef WANT_SSL_LOGGING 102#ifdef WANT_SSL_LOGGING
188static const char *log_ssl_keysize(request_rec *r, char *a) 103static const char *extract_ssl_keysize(request_rec *r, char *a)
189{ 104{
190 char *result = NULL; 105 char *result = NULL;
191 106
@@ -202,7 +117,7 @@ static const char *log_ssl_keysize(request_rec *r, char *a)
202 } 117 }
203} 118}
204 119
205static const char *log_ssl_maxkeysize(request_rec *r, char *a) 120static const char *extract_ssl_maxkeysize(request_rec *r, char *a)
206{ 121{
207 char *result = NULL; 122 char *result = NULL;
208 123
@@ -219,7 +134,7 @@ static const char *log_ssl_maxkeysize(request_rec *r, char *a)
219 } 134 }
220} 135}
221 136
222static const char *log_ssl_cipher(request_rec *r, char *a) 137static const char *extract_ssl_cipher(request_rec *r, char *a)
223{ 138{
224 char *result = NULL; 139 char *result = NULL;
225 140
@@ -232,42 +147,42 @@ static const char *log_ssl_cipher(request_rec *r, char *a)
232 result = NULL; 147 result = NULL;
233 return result; 148 return result;
234 } else { 149 } else {
235 return "0"; 150 return "-";
236 } 151 }
237} 152}
238#endif /* WANT_SSL_LOGGING */ 153#endif /* WANT_SSL_LOGGING */
239 154
240static const char *log_request_method(request_rec *r, char *a) 155static const char *extract_request_method(request_rec *r, char *a)
241{ 156{
242 return r->method; 157 return r->method;
243} 158}
244 159
245static const char *log_request_protocol(request_rec *r, char *a) 160static const char *extract_request_protocol(request_rec *r, char *a)
246{ 161{
247 return r->protocol; 162 return r->protocol;
248} 163}
249 164
250static const char *log_request_line(request_rec *r, char *a) 165static const char *extract_request_line(request_rec *r, char *a)
251{ 166{
252 return r->the_request; 167 return r->the_request;
253} 168}
254 169
255static const char *log_request_file(request_rec *r, char *a) 170static const char *extract_request_file(request_rec *r, char *a)
256{ 171{
257 return r->filename; 172 return r->filename;
258} 173}
259 174
260static const char *log_request_uri(request_rec *r, char *a) 175static const char *extract_request_uri(request_rec *r, char *a)
261{ 176{
262 return r->uri; 177 return r->uri;
263} 178}
264 179
265static const char *log_status(request_rec *r, char *a) 180static const char *extract_status(request_rec *r, char *a)
266{ 181{
267 return pfmt(r->pool, r->status); 182 return pfmt(r->pool, r->status);
268} 183}
269 184
270static const char *log_bytes_sent(request_rec *r, char *a) 185static const char *extract_bytes_sent(request_rec *r, char *a)
271{ 186{
272 if (!r->sent_bodyct) { 187 if (!r->sent_bodyct) {
273 return "-"; 188 return "-";
@@ -280,12 +195,12 @@ static const char *log_bytes_sent(request_rec *r, char *a)
280 } 195 }
281} 196}
282 197
283static const char *log_header_in(request_rec *r, char *a) 198static const char *extract_header_in(request_rec *r, char *a)
284{ 199{
285 return table_get(r->headers_in, a); 200 return table_get(r->headers_in, a);
286} 201}
287 202
288static const char *log_header_out(request_rec *r, char *a) 203static const char *extract_header_out(request_rec *r, char *a)
289{ 204{
290 const char *cp = table_get(r->headers_out, a); 205 const char *cp = table_get(r->headers_out, a);
291 if (!strcasecmp(a, "Content-type") && r->content_type) { 206 if (!strcasecmp(a, "Content-type") && r->content_type) {
@@ -297,7 +212,7 @@ static const char *log_header_out(request_rec *r, char *a)
297 return table_get(r->err_headers_out, a); 212 return table_get(r->err_headers_out, a);
298} 213}
299 214
300static const char *log_request_time(request_rec *r, char *a) 215static const char *extract_request_time(request_rec *r, char *a)
301{ 216{
302 int timz; 217 int timz;
303 struct tm *t; 218 struct tm *t;
@@ -320,7 +235,7 @@ static const char *log_request_time(request_rec *r, char *a)
320 return pstrdup(r->pool, tstr); 235 return pstrdup(r->pool, tstr);
321} 236}
322 237
323static const char *log_request_duration(request_rec *r, char *a) 238static const char *extract_request_duration(request_rec *r, char *a)
324{ 239{
325 char duration[22]; /* Long enough for 2^64 */ 240 char duration[22]; /* Long enough for 2^64 */
326 241
@@ -328,12 +243,12 @@ static const char *log_request_duration(request_rec *r, char *a)
328 return pstrdup(r->pool, duration); 243 return pstrdup(r->pool, duration);
329} 244}
330 245
331static const char *log_virtual_host(request_rec *r, char *a) 246static const char *extract_virtual_host(request_rec *r, char *a)
332{ 247{
333 return pstrdup(r->pool, r->server->server_hostname); 248 return pstrdup(r->pool, r->server->server_hostname);
334} 249}
335 250
336static const char *log_server_port(request_rec *r, char *a) 251static const char *extract_server_port(request_rec *r, char *a)
337{ 252{
338 char portnum[22]; 253 char portnum[22];
339 254
@@ -341,14 +256,14 @@ static const char *log_server_port(request_rec *r, char *a)
341 return pstrdup(r->pool, portnum); 256 return pstrdup(r->pool, portnum);
342} 257}
343 258
344static const char *log_child_pid(request_rec *r, char *a) 259static const char *extract_child_pid(request_rec *r, char *a)
345{ 260{
346 char pidnum[22]; 261 char pidnum[22];
347 ap_snprintf(pidnum, sizeof(pidnum), "%ld", (long) getpid()); 262 ap_snprintf(pidnum, sizeof(pidnum), "%ld", (long) getpid());
348 return pstrdup(r->pool, pidnum); 263 return pstrdup(r->pool, pidnum);
349} 264}
350 265
351static const char *log_referer(request_rec *r, char *a) 266static const char *extract_referer(request_rec *r, char *a)
352{ 267{
353 const char *tempref; 268 const char *tempref;
354 269
@@ -361,7 +276,7 @@ static const char *log_referer(request_rec *r, char *a)
361 } 276 }
362} 277}
363 278
364static const char *log_agent(request_rec *r, char *a) 279static const char *extract_agent(request_rec *r, char *a)
365{ 280{
366 const char *tempag; 281 const char *tempag;
367 282
@@ -374,7 +289,7 @@ static const char *log_agent(request_rec *r, char *a)
374 } 289 }
375} 290}
376 291
377static const char *log_cookie(request_rec *r, char *a) 292static const char *extract_cookie(request_rec *r, char *a)
378{ 293{
379 const char *cookiestr; 294 const char *cookiestr;
380 char *cookieend; 295 char *cookieend;
@@ -396,7 +311,6 @@ static const char *log_cookie(request_rec *r, char *a)
396 return cookiebuf; 311 return cookiebuf;
397 } 312 }
398 } 313 }
399
400 314
401 cookiestr = (char *)table_get(r->headers_in, "cookie"); 315 cookiestr = (char *)table_get(r->headers_in, "cookie");
402 if (cookiestr != NULL) { 316 if (cookiestr != NULL) {
@@ -414,7 +328,6 @@ static const char *log_cookie(request_rec *r, char *a)
414 } 328 }
415 } 329 }
416 330
417
418 cookiestr = table_get(r->headers_out, "set-cookie"); 331 cookiestr = table_get(r->headers_out, "set-cookie");
419 if (cookiestr != NULL) { 332 if (cookiestr != NULL) {
420 #ifdef DEBUG 333 #ifdef DEBUG
@@ -434,8 +347,7 @@ static const char *log_cookie(request_rec *r, char *a)
434 return "-"; 347 return "-";
435} 348}
436 349
437 350static const char *extract_request_timestamp(request_rec *r, char *a)
438const char *log_request_timestamp(request_rec *r, char *a)
439{ 351{
440 char tstr[32]; 352 char tstr[32];
441 353
@@ -443,19 +355,18 @@ const char *log_request_timestamp(request_rec *r, char *a)
443 return pstrdup(r->pool, tstr); 355 return pstrdup(r->pool, tstr);
444} 356}
445 357
446static const char *log_note(request_rec *r, char *a) 358static const char *extract_note(request_rec *r, char *a)
447{ 359{
448 return table_get(r->notes, a); 360 return table_get(r->notes, a);
449} 361}
450 362
451static const char *log_env_var(request_rec *r, char *a) 363static const char *extract_env_var(request_rec *r, char *a)
452{ 364{
453 return table_get(r->subprocess_env, a); 365 return table_get(r->subprocess_env, a);
454} 366}
455#endif /* MODULE_MAGIC_NUMBER */
456 367
368/* End declarations of various extract_ functions */
457 369
458/* End declarations of various log_ functions */
459 370
460 371
461struct log_mysql_item_list { 372struct log_mysql_item_list {
@@ -466,39 +377,39 @@ struct log_mysql_item_list {
466 int string_contents; 377 int string_contents;
467 } log_mysql_item_keys[] = { 378 } log_mysql_item_keys[] = {
468 379
469 { 'A', log_agent, "agent", 1, 1 }, 380 { 'A', extract_agent, "agent", 1, 1 },
470 { 'b', log_bytes_sent, "bytes_sent", 0, 0 }, 381 { 'b', extract_bytes_sent, "bytes_sent", 0, 0 },
471 { 'c', log_cookie, "cookie", 0, 1 }, 382 { 'c', extract_cookie, "cookie", 0, 1 },
472 { 'e', log_env_var, "env_var", 0, 1 }, 383 { 'e', extract_env_var, "env_var", 0, 1 },
473 { 'f', log_request_file, "request_file", 0, 1 }, 384 { 'f', extract_request_file, "request_file", 0, 1 },
474 { 'H', log_request_protocol, "request_protocol", 0, 1 }, 385 { 'H', extract_request_protocol, "request_protocol", 0, 1 },
475 { 'h', log_remote_host, "remote_host", 0, 1 }, 386 { 'h', extract_remote_host, "remote_host", 0, 1 },
476 { 'i', log_header_in, "header_in", 0, 1 }, 387 { 'i', extract_header_in, "header_in", 0, 1 },
477 { 'l', log_remote_logname, "remote_logname", 0, 1 }, 388 { 'l', extract_remote_logname, "remote_logname", 0, 1 },
478 { 'm', log_request_method, "request_method", 0, 1 }, 389 { 'm', extract_request_method, "request_method", 0, 1 },
479 { 'n', log_note, "note", 0, 1 }, 390 { 'n', extract_note, "note", 0, 1 },
480 { 'o', log_header_out, "header_out", 0, 1 }, 391 { 'o', extract_header_out, "header_out", 0, 1 },
481 { 'P', log_child_pid, "child_pid", 0, 0 }, 392 { 'P', extract_child_pid, "child_pid", 0, 0 },
482 { 'p', log_server_port, "server_port", 0, 0 }, 393 { 'p', extract_server_port, "server_port", 0, 0 },
483 { 'R', log_referer, "referer", 1, 1 }, 394 { 'R', extract_referer, "referer", 1, 1 },
484 { 'r', log_request_line, "request_line", 1, 1 }, 395 { 'r', extract_request_line, "request_line", 1, 1 },
485 { 'S', log_request_timestamp, "time_stamp", 0, 0 }, 396 { 'S', extract_request_timestamp, "time_stamp", 0, 0 },
486 { 's', log_status, "status", 1, 0 }, 397 { 's', extract_status, "status", 1, 0 },
487 { 'T', log_request_duration, "request_duration", 1, 0 }, 398 { 'T', extract_request_duration, "request_duration", 1, 0 },
488 { 't', log_request_time, "request_time", 0, 1 }, 399 { 't', extract_request_time, "request_time", 0, 1 },
489 { 'u', log_remote_user, "remote_user", 0, 1 }, 400 { 'u', extract_remote_user, "remote_user", 0, 1 },
490 { 'U', log_request_uri, "request_uri", 1, 1 }, 401 { 'U', extract_request_uri, "request_uri", 1, 1 },
491 { 'v', log_virtual_host, "virtual_host", 0, 1 }, 402 { 'v', extract_virtual_host, "virtual_host", 0, 1 },
492 #ifdef WANT_SSL_LOGGING 403 #ifdef WANT_SSL_LOGGING
493 { 'q', log_ssl_keysize, "ssl_keysize", 0, 1 }, 404 { 'q', extract_ssl_keysize, "ssl_keysize", 0, 1 },
494 { 'Q', log_ssl_maxkeysize, "ssl_maxkeysize", 0, 1 }, 405 { 'Q', extract_ssl_maxkeysize, "ssl_maxkeysize", 0, 1 },
495 { 'z', log_ssl_cipher, "ssl_cipher", 0, 1 }, 406 { 'z', extract_ssl_cipher, "ssl_cipher", 0, 1 },
496 #endif 407 #endif
497 {'\0'} 408 {'\0'}
498}; 409};
499 410
500 411
501/* Routine to escape 'dangerous' characters that would otherwise 412/* Routine to escape the 'dangerous' characters that would otherwise
502 * corrupt the INSERT string: ', \, and " 413 * corrupt the INSERT string: ', \, and "
503 */ 414 */
504const char *mysql_escape_log(const char *str, pool *p) 415const char *mysql_escape_log(const char *str, pool *p)
@@ -528,7 +439,7 @@ const char *mysql_escape_log(const char *str, pool *p)
528 /* Pre-allocate a new string that could hold twice the original, which would only 439 /* Pre-allocate a new string that could hold twice the original, which would only
529 * happen if the whole original string was 'dangerous' characters. 440 * happen if the whole original string was 'dangerous' characters.
530 */ 441 */
531 tmp_str = (char *) palloc(p, length *2 + 1); 442 tmp_str = (char *) palloc(p, length * 2 + 1);
532 if (!tmp_str) { 443 if (!tmp_str) {
533 return str; 444 return str;
534 } 445 }
@@ -552,16 +463,15 @@ const char *mysql_escape_log(const char *str, pool *p)
552 } 463 }
553} 464}
554 465
555 466void open_logdb_link()
556void open_log_dblink()
557{ 467{
558 if (mysql_log != NULL) { /* virtual database link shared with main server */ 468 if (mysql_log != NULL) { /* virtual database link shared with main server */
559 return; 469 return;
560 } 470 }
561 if (log_db_name) { /* open an SQL link */ 471 if (db_name) { /* open an SQL link */
562 mysql_log = mysql_connect(&log_sql_server, db_host, db_user, db_pwd); 472 mysql_log = mysql_connect(&sql_server, db_host, db_user, db_pwd);
563 if (mysql_log) { /* link opened */ 473 if (mysql_log) { /* link opened */
564 if (mysql_select_db(mysql_log, log_db_name) != 0) { /* unable to select database */ 474 if (mysql_select_db(mysql_log, db_name) != 0) { /* unable to select database */
565 mysql_close(mysql_log); 475 mysql_close(mysql_log);
566 mysql_log = NULL; 476 mysql_log = NULL;
567 } 477 }
@@ -569,23 +479,72 @@ void open_log_dblink()
569 } 479 }
570} 480}
571 481
572 482int safe_mysql_query(request_rec *r, const char *query)
573void *make_log_mysql_state(pool *p, server_rec *s)
574{ 483{
575 log_mysql_state *cls = (log_mysql_state *) palloc(p, sizeof(log_mysql_state)); 484 int retval = 1;
485 struct timespec delay, remainder;
486 int ret;
487 char *str;
488 void (*handler) (int);
576 489
577 cls->referer_table_name = cls->agent_table_name = cls->transfer_table_name = ""; 490 /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */
578 cls->referer_ignore_list = make_array(p, 1, sizeof(char *)); 491 handler = signal(SIGPIPE, SIG_IGN);
579 cls->transfer_ignore_list = make_array(p, 1, sizeof(char *)); 492
580 cls->remhost_ignore_list = make_array(p, 1, sizeof(char *)); 493 /* If there's no DB link, or if we run the query and it gacks, try to be graceful */
581 cls->transfer_log_format = ""; 494 if ( !mysql_log ||
582 return (void *) cls; 495 (
496 (retval = mysql_query(mysql_log, query)) &&
497 (mysql_errno(mysql_log) != 0)
498 )
499 )
500
501 { /* We need to restart the server link */
502 mysql_log = NULL;
503 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: connection lost, attempting reconnect");
504
505 open_logdb_link();
506
507 if (mysql_log == NULL) { /* still unable to link */
508 signal(SIGPIPE, handler);
509 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: reconnect failed");
510 return retval;
511 }
512
513 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: reconnect successful");
514 retval = mysql_query(mysql_log, query);
515 }
516
517 /* Restore SIGPIPE to its original handler function */
518 signal(SIGPIPE, handler);
519
520 if (retval) {
521 /* Attempt a single re-try... First sleep for a tiny amount of time. */
522 delay.tv_sec = 0;
523 delay.tv_nsec = 500000000; /* max is 999999999 (nine nines) */
524 ret = nanosleep(&delay, &remainder);
525 if (ret && errno != EINTR)
526 perror("nanosleep");
527
528 /* Now re-attempt */
529 retval = mysql_query(mysql_log,query);
530
531 if (retval) {
532 str = pstrcat(r->pool, "MySQL insert failed: ", query, NULL);
533 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,str);
534 str = pstrcat(r->pool, "MySQL failure reason: ", MYSQL_ERROR(mysql_log), NULL);
535 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,str);
536 } else {
537 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: insert successful after a delayed retry.");
538 }
539 }
540 return retval;
583} 541}
584 542
543
544
585const char *set_referer_log_mysql_table(cmd_parms *parms, void *dummy, char *arg) 545const char *set_referer_log_mysql_table(cmd_parms *parms, void *dummy, char *arg)
586{ 546{
587 log_mysql_state *cls = get_module_config(parms->server->module_config, 547 log_mysql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module);
588 &mysql_log_module);
589 548
590 cls->referer_table_name = arg; 549 cls->referer_table_name = arg;
591 return NULL; 550 return NULL;
@@ -594,8 +553,7 @@ const char *set_referer_log_mysql_table(cmd_parms *parms, void *dummy, char *arg
594 553
595const char *set_agent_log_mysql_table(cmd_parms *parms, void *dummy, char *arg) 554const char *set_agent_log_mysql_table(cmd_parms *parms, void *dummy, char *arg)
596{ 555{
597 log_mysql_state *cls = get_module_config(parms->server->module_config, 556 log_mysql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module);
598 &mysql_log_module);
599 557
600 cls->agent_table_name = arg; 558 cls->agent_table_name = arg;
601 return NULL; 559 return NULL;
@@ -604,8 +562,7 @@ const char *set_agent_log_mysql_table(cmd_parms *parms, void *dummy, char *arg)
604 562
605const char *set_transfer_log_mysql_table(cmd_parms *parms, void *dummy, char *arg) 563const char *set_transfer_log_mysql_table(cmd_parms *parms, void *dummy, char *arg)
606{ 564{
607 log_mysql_state *cls = get_module_config(parms->server->module_config, 565 log_mysql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module);
608 &mysql_log_module);
609 566
610 cls->transfer_table_name = arg; 567 cls->transfer_table_name = arg;
611 return NULL; 568 return NULL;
@@ -614,8 +571,7 @@ const char *set_transfer_log_mysql_table(cmd_parms *parms, void *dummy, char *ar
614 571
615const char *set_transfer_log_format(cmd_parms *parms, void *dummy, char *arg) 572const char *set_transfer_log_format(cmd_parms *parms, void *dummy, char *arg)
616{ 573{
617 log_mysql_state *cls = get_module_config(parms->server->module_config, 574 log_mysql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module);
618 &mysql_log_module);
619 575
620 cls->transfer_log_format = arg; 576 cls->transfer_log_format = arg;
621 return NULL; 577 return NULL;
@@ -624,7 +580,7 @@ const char *set_transfer_log_format(cmd_parms *parms, void *dummy, char *arg)
624 580
625const char *set_log_mysql_db(cmd_parms *parms, void *dummy, char *arg) 581const char *set_log_mysql_db(cmd_parms *parms, void *dummy, char *arg)
626{ 582{
627 log_db_name = arg; 583 db_name = arg;
628 return NULL; 584 return NULL;
629} 585}
630 586
@@ -682,103 +638,68 @@ const char *add_remhost_mysql_ignore(cmd_parms *parms, void *dummy, char *arg)
682 return NULL; 638 return NULL;
683} 639}
684 640
641
642/*
643 * Apache-specific hooks into the module code
644 * that are defined in the array 'mysql_lgog_module' (at EOF)
645 */
646
647
648/* Set up space for the various major configuration options */
649void *log_mysql_make_state(pool *p, server_rec *s)
650{
651 log_mysql_state *cls = (log_mysql_state *) palloc(p, sizeof(log_mysql_state));
652
653 cls->referer_table_name = cls->agent_table_name = cls->transfer_table_name = "";
654
655 cls->referer_ignore_list = make_array(p, 1, sizeof(char *));
656 cls->transfer_ignore_list = make_array(p, 1, sizeof(char *));
657 cls->remhost_ignore_list = make_array(p, 1, sizeof(char *));
658
659 cls->transfer_log_format = "";
660 return (void *) cls;
661}
662
663
664/* Setup of the available httpd.conf configuration commands.
665 * command, function called, NULL, where available, how many arguments, verbose description
666 */
685command_rec log_mysql_cmds[] = { 667command_rec log_mysql_cmds[] = {
686 {"MySQLRefererLogTable", set_referer_log_mysql_table, NULL, RSRC_CONF, TAKE1, 668 {"MySQLRefererLogTable", set_referer_log_mysql_table, NULL, RSRC_CONF, TAKE1,
687 "The MySQL table that holds the referer log"} 669 "The MySQL table that holds the referer log"}
688 , 670 ,
689 {"MySQLAgentLogTable", set_agent_log_mysql_table, NULL, RSRC_CONF, TAKE1, 671 {"MySQLAgentLogTable", set_agent_log_mysql_table, NULL, RSRC_CONF, TAKE1,
690 "The MySQL table that holds the agent log"} 672 "The MySQL table that holds the agent log"}
691 , 673 ,
692 {"MySQLTransferLogTable", set_transfer_log_mysql_table, NULL, RSRC_CONF, TAKE1, 674 {"MySQLTransferLogTable", set_transfer_log_mysql_table, NULL, RSRC_CONF, TAKE1,
693 "The MySQL table that holds the transfer log"} 675 "The MySQL table that holds the transfer log"}
694 , 676 ,
695 {"MySQLTransferLogFormat", set_transfer_log_format, NULL, RSRC_CONF, TAKE1, 677 {"MySQLTransferLogFormat", set_transfer_log_format, NULL, RSRC_CONF, TAKE1,
696 "Instruct the module what information to log to the MySQL transfer log"} 678 "Instruct the module what information to log to the MySQL transfer log"}
697 , 679 ,
698 {"MySQLRefererIgnore", add_referer_mysql_ignore, NULL, RSRC_CONF, ITERATE, 680 {"MySQLRefererIgnore", add_referer_mysql_ignore, NULL, RSRC_CONF, ITERATE,
699 "List of referers to ignore, accesses that match will not be logged to MySQL"} 681 "List of referers to ignore. Accesses that match will not be logged to MySQL"}
700 , 682 ,
701 {"MySQLRequestIgnore", add_transfer_mysql_ignore, NULL, RSRC_CONF, ITERATE, 683 {"MySQLRequestIgnore", add_transfer_mysql_ignore, NULL, RSRC_CONF, ITERATE,
702 "List of URIs to ignore, accesses that match will not be logged to MySQL"} 684 "List of URIs to ignore. Accesses that match will not be logged to MySQL"}
703 , 685 ,
704 {"MySQLRemhostIgnore", add_remhost_mysql_ignore, NULL, RSRC_CONF, ITERATE, 686 {"MySQLRemhostIgnore", add_remhost_mysql_ignore, NULL, RSRC_CONF, ITERATE,
705 "List of remote hosts to ignore, accesses that match will not be logged to MySQL"} 687 "List of remote hosts to ignore. Accesses that match will not be logged to MySQL"}
706 , 688 ,
707 {"MySQLDatabase", set_log_mysql_db, NULL, RSRC_CONF, TAKE1, 689 {"MySQLDatabase", set_log_mysql_db, NULL, RSRC_CONF, TAKE1,
708 "The name of the MySQL database for logging"} 690 "The name of the MySQL database for logging"}
709 , 691 ,
710 {"MySQLWhichCookie", set_log_mysql_cookie, NULL, RSRC_CONF, TAKE1, 692 {"MySQLWhichCookie", set_log_mysql_cookie, NULL, RSRC_CONF, TAKE1,
711 "The CookieName that you want logged when using the 'c' config directive"} 693 "The CookieName that you want logged when using the 'c' config directive"}
712 , 694 ,
713 {"MySQLLoginInfo", set_log_mysql_info, NULL, RSRC_CONF, TAKE3, 695 {"MySQLLoginInfo", set_log_mysql_info, NULL, RSRC_CONF, TAKE3,
714 "The MySQL host, user-id and password for logging"} 696 "The MySQL host, user-id and password for logging"}
715 , 697 ,
716 {NULL} 698 {NULL}
717}; 699};
718 700
719 701
720int safe_mysql_query(request_rec *r, const char *query) 702
721{
722 int error = 1;
723 struct timespec delay, remainder;
724 int ret;
725 char *str;
726 void (*handler) (int);
727
728 /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */
729 handler = signal(SIGPIPE, SIG_IGN);
730
731 /* If there's no DB link, or if we run the query and it gacks, try to be graceful */
732 if ( !mysql_log ||
733 (
734 (error = mysql_query(mysql_log, query)) &&
735 !strcasecmp(mysql_error(mysql_log), "MySQL server has gone away")
736 )
737 )
738
739 { /* We need to restart the server link */
740 mysql_log = NULL;
741 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: connection lost, attempting reconnect");
742
743 open_log_dblink();
744
745 if (mysql_log == NULL) { /* still unable to link */
746 signal(SIGPIPE, handler);
747 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: reconnect failed.");
748 return error;
749 }
750
751 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: reconnect successful.");
752 error = mysql_query(mysql_log, query);
753 }
754
755 /* Restore SIGPIPE to its original handler function */
756 signal(SIGPIPE, handler);
757
758 if (error) {
759 /* Attempt a single re-try... First sleep for a tiny amount of time. */
760 delay.tv_sec = 0;
761 delay.tv_nsec = 500000000; /* max is 999999999 (nine nines) */
762 ret = nanosleep(&delay, &remainder);
763 if (ret && errno != EINTR)
764 perror("nanosleep");
765
766 /* Now re-attempt */
767 error = mysql_query(mysql_log,query);
768
769 if (error) {
770 str = pstrcat(r->pool, "MySQL query failed: ", query, NULL);
771 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,str);
772 str = pstrcat(r->pool, "MySQL failure reason: ", MYSQL_ERROR(mysql_log), NULL);
773 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,str);
774 } else {
775 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: insert successful after a delayed retry.");
776 }
777 }
778 return error;
779}
780
781
782/* Routine to perform the actual construction and execution of the relevant 703/* Routine to perform the actual construction and execution of the relevant
783 * INSERT statements. 704 * INSERT statements.
784 */ 705 */
@@ -805,7 +726,7 @@ int log_mysql_transaction(request_rec *orig)
805 } 726 }
806 727
807 if (mysql_log == NULL) { /* mysql link not up, hopefully we can do something about it */ 728 if (mysql_log == NULL) { /* mysql link not up, hopefully we can do something about it */
808 open_log_dblink(); 729 open_logdb_link();
809 if (mysql_log == NULL) { 730 if (mysql_log == NULL) {
810 return OK; 731 return OK;
811 } 732 }
@@ -932,13 +853,20 @@ int log_mysql_transaction(request_rec *orig)
932} 853}
933 854
934 855
856/* Called on the exit of an httpd child process */
857static void log_mysql_child_exit(server_rec *s, pool *p)
858{
859 mysql_close(mysql_log);
860}
935 861
862
863/* The configuration array that sets up the hooks into the module. */
936module mysql_log_module = { 864module mysql_log_module = {
937 STANDARD_MODULE_STUFF, 865 STANDARD_MODULE_STUFF,
938 NULL, /* initializer */ 866 NULL, /* initializer */
939 NULL, /* create per-dir config */ 867 NULL, /* create per-dir config */
940 NULL, /* merge per-dir config */ 868 NULL, /* merge per-dir config */
941 make_log_mysql_state, /* server config */ 869 log_mysql_make_state, /* server config */
942 NULL, /* merge server config */ 870 NULL, /* merge server config */
943 log_mysql_cmds, /* command table */ 871 log_mysql_cmds, /* command table */
944 NULL, /* handlers */ 872 NULL, /* handlers */
@@ -949,5 +877,11 @@ module mysql_log_module = {
949 NULL, /* type_checker */ 877 NULL, /* type_checker */
950 NULL, /* fixups */ 878 NULL, /* fixups */
951 log_mysql_transaction, /* logger */ 879 log_mysql_transaction, /* logger */
952 NULL /* header parser */ 880 NULL, /* header parser */
881#if MODULE_MAGIC_NUMBER >= 19970728 /* 1.3-dev or later support these additionals... */
882 NULL, /* child_init */
883 log_mysql_child_exit, /* process exit/cleanup */
884 NULL /* [#0] post read-request */
885#endif
886
953}; 887};