diff options
Diffstat (limited to 'mod_log_sql.c')
-rw-r--r-- | mod_log_sql.c | 468 |
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 */ |
106 | module mysql_log_module; | 34 | module mysql_log_module; |
107 | MYSQL log_sql_server, *mysql_log = NULL; | 35 | |
108 | char *log_db_name = NULL, *db_host = NULL, *db_user = NULL, *db_pwd = NULL, *cookie_name = NULL; | 36 | MYSQL sql_server, *mysql_log = NULL; |
37 | |||
38 | char *db_name = NULL; | ||
39 | char *db_host = NULL; | ||
40 | char *db_user = NULL; | ||
41 | char *db_pwd = NULL; | ||
42 | char *cookie_name = NULL; | ||
109 | 43 | ||
110 | typedef const char *(*item_key_func) (request_rec *, char *); | 44 | typedef const char *(*item_key_func) (request_rec *, char *); |
45 | |||
111 | typedef struct { | 46 | typedef 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 */ |
122 | extern const char *log_request_protocol(request_rec *r, char *a); | ||
123 | extern const char *log_request_method(request_rec *r, char *a); | ||
124 | extern const char *log_remote_host(request_rec *r, char *a); | ||
125 | extern const char *log_remote_logname(request_rec *r, char *a); | ||
126 | extern const char *log_remote_user(request_rec *r, char *a); | ||
127 | extern const char *log_request_time(request_rec *r, char *a); | ||
128 | extern const char *log_request_timestamp(request_rec *r, char *a); | ||
129 | extern const char *log_request_duration(request_rec *r, char *a); | ||
130 | extern const char *log_request_line(request_rec *r, char *a); | ||
131 | extern const char *log_request_file(request_rec *r, char *a); | ||
132 | extern const char *log_request_uri(request_rec *r, char *a); | ||
133 | extern const char *log_status(request_rec *r, char *a); | ||
134 | extern const char *log_bytes_sent(request_rec *r, char *a); | ||
135 | extern const char *log_header_in(request_rec *r, char *a); | ||
136 | extern const char *log_header_out(request_rec *r, char *a); | ||
137 | extern const char *log_note(request_rec *r, char *a); | ||
138 | extern const char *log_env_var(request_rec *r, char *a); | ||
139 | extern const char *log_virtual_host(request_rec *r, char *a); | ||
140 | extern const char *log_server_port(request_rec *r, char *a); | ||
141 | extern const char *log_child_pid(request_rec *r, char *a); | ||
142 | #else | ||
143 | |||
144 | static char *format_integer(pool *p, int i) | 59 | static 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 | ||
165 | static const char *log_remote_host(request_rec *r, char *a) | 80 | static 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 | ||
170 | static const char *log_remote_logname(request_rec *r, char *a) | 85 | static 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 | ||
175 | static const char *log_remote_user(request_rec *r, char *a) | 90 | static 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 |
188 | static const char *log_ssl_keysize(request_rec *r, char *a) | 103 | static 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 | ||
205 | static const char *log_ssl_maxkeysize(request_rec *r, char *a) | 120 | static 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 | ||
222 | static const char *log_ssl_cipher(request_rec *r, char *a) | 137 | static 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 | ||
240 | static const char *log_request_method(request_rec *r, char *a) | 155 | static const char *extract_request_method(request_rec *r, char *a) |
241 | { | 156 | { |
242 | return r->method; | 157 | return r->method; |
243 | } | 158 | } |
244 | 159 | ||
245 | static const char *log_request_protocol(request_rec *r, char *a) | 160 | static const char *extract_request_protocol(request_rec *r, char *a) |
246 | { | 161 | { |
247 | return r->protocol; | 162 | return r->protocol; |
248 | } | 163 | } |
249 | 164 | ||
250 | static const char *log_request_line(request_rec *r, char *a) | 165 | static 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 | ||
255 | static const char *log_request_file(request_rec *r, char *a) | 170 | static const char *extract_request_file(request_rec *r, char *a) |
256 | { | 171 | { |
257 | return r->filename; | 172 | return r->filename; |
258 | } | 173 | } |
259 | 174 | ||
260 | static const char *log_request_uri(request_rec *r, char *a) | 175 | static const char *extract_request_uri(request_rec *r, char *a) |
261 | { | 176 | { |
262 | return r->uri; | 177 | return r->uri; |
263 | } | 178 | } |
264 | 179 | ||
265 | static const char *log_status(request_rec *r, char *a) | 180 | static 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 | ||
270 | static const char *log_bytes_sent(request_rec *r, char *a) | 185 | static 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 | ||
283 | static const char *log_header_in(request_rec *r, char *a) | 198 | static 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 | ||
288 | static const char *log_header_out(request_rec *r, char *a) | 203 | static 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 | ||
300 | static const char *log_request_time(request_rec *r, char *a) | 215 | static 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 | ||
323 | static const char *log_request_duration(request_rec *r, char *a) | 238 | static 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 | ||
331 | static const char *log_virtual_host(request_rec *r, char *a) | 246 | static 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 | ||
336 | static const char *log_server_port(request_rec *r, char *a) | 251 | static 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 | ||
344 | static const char *log_child_pid(request_rec *r, char *a) | 259 | static 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 | ||
351 | static const char *log_referer(request_rec *r, char *a) | 266 | static 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 | ||
364 | static const char *log_agent(request_rec *r, char *a) | 279 | static 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 | ||
377 | static const char *log_cookie(request_rec *r, char *a) | 292 | static 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 | 350 | static const char *extract_request_timestamp(request_rec *r, char *a) | |
438 | const 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 | ||
446 | static const char *log_note(request_rec *r, char *a) | 358 | static 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 | ||
451 | static const char *log_env_var(request_rec *r, char *a) | 363 | static 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 | ||
461 | struct log_mysql_item_list { | 372 | struct 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 | */ |
504 | const char *mysql_escape_log(const char *str, pool *p) | 415 | const 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 | 466 | void open_logdb_link() | |
556 | void 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 | 482 | int safe_mysql_query(request_rec *r, const char *query) | |
573 | void *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 | |||
585 | const char *set_referer_log_mysql_table(cmd_parms *parms, void *dummy, char *arg) | 545 | const 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 | ||
595 | const char *set_agent_log_mysql_table(cmd_parms *parms, void *dummy, char *arg) | 554 | const 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 | ||
605 | const char *set_transfer_log_mysql_table(cmd_parms *parms, void *dummy, char *arg) | 563 | const 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 | ||
615 | const char *set_transfer_log_format(cmd_parms *parms, void *dummy, char *arg) | 572 | const 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 | ||
625 | const char *set_log_mysql_db(cmd_parms *parms, void *dummy, char *arg) | 581 | const 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 */ | ||
649 | void *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 | */ | ||
685 | command_rec log_mysql_cmds[] = { | 667 | command_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 | ||
720 | int 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 */ | ||
857 | static 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. */ | ||
936 | module mysql_log_module = { | 864 | module 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 | }; |