summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Christopher Powell 2001-11-30 08:29:04 +0000
committerGravatar Christopher Powell 2001-11-30 08:29:04 +0000
commit69fa0ad0d21465573b9dcb07c87ae27f993dfe31 (patch)
treec05c2d94edd4d7ff330272e06e8c320d0a504f80
parent92d85f793b1a41bbbde1811004ae2708a47a44aa (diff)
A lot of code cleanup and tweaking, plus cookie logging:1.10
* New capability: log mod_usertrack cookies. * Some code cleanup and commenting. * Referer and User-Agent now set to want_orig=1 ( a very minor detail ) * Corrected mysql_escape_log to properly check for and escape strings with 'dangerous' characters. It appears that it was doing this incorrectly before. * Deleted log_mysql_child(), a function that was never called.
-rw-r--r--CHANGELOG14
-rw-r--r--mod_log_sql.c311
2 files changed, 194 insertions, 131 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 674fbec..9f2295b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,12 +1,24 @@
1$Id: CHANGELOG,v 1.1 2001/11/28 05:26:54 helios Exp $ 1$Id: CHANGELOG,v 1.2 2001/11/30 08:29:04 helios Stab $
2 2
3 3
4TODO: 4TODO:
5* Full commenting of the code. 5* Full commenting of the code.
6* Bounds checking on all data prior to INSERT
6 7
7 8
8CHANGES: 9CHANGES:
9 10
111.10:
12
13* New capability: log mod_usertrack cookies.
14* Some code cleanup and commenting.
15* Referer and User-Agent now set to want_orig=1 ( a very minor detail )
16* Corrected mysql_escape_log to properly check for and escape strings
17 with `dangerous' characters. It appears that it was doing this
18 incorrectly before.
19* Deleted log_mysql_child(), a function that was never called.
20
21
101.09: 221.09:
11 23
12* If the MySQL INSERT causes an error, we re-try that INSERT after 24* If the MySQL INSERT causes an error, we re-try that INSERT after
diff --git a/mod_log_sql.c b/mod_log_sql.c
index 1493e41..0739372 100644
--- a/mod_log_sql.c
+++ b/mod_log_sql.c
@@ -1,6 +1,7 @@
1/* $Id: mod_log_sql.c,v 1.1 2001/11/28 05:26:55 helios Exp $ 1/* $Id: mod_log_sql.c,v 1.2 2001/11/30 08:29:04 helios Stab $
2 * 2 *
3 * mod_log_mysql.c 3 * mod_log_mysql.c
4 * Release v 1.10
4 * 5 *
5 * Hi, I'm the new maintainer of this code. If you have any questions, 6 * Hi, I'm the new maintainer of this code. If you have any questions,
6 * comments or suggestions (which are always welcome), please contact Chris 7 * comments or suggestions (which are always welcome), please contact Chris
@@ -70,15 +71,16 @@
70 */ 71 */
71 72
72 73
74#include <time.h>
75#include <mysql/mysql.h>
76
73#include "httpd.h" 77#include "httpd.h"
74#include "http_config.h" 78#include "http_config.h"
2004-12-09
|
* re-order the cipher types.Gravatar Paul Querna 2004-12-06
| | | | | Add a fixups hook and some Basic Env vars
* setting proper ignores.Gravatar Paul Querna 2004-12-02
| | | | | | | adding an empty cache files trying to fix >16kb writes.
* adding autofoo for memcache supportGravatar Paul Querna 2004-12-02
|
* hey hey, this is working code!Gravatar Paul Querna 2004-12-02
|
* input and output filtersGravatar Paul Querna 2004-09-28
|
* rename structures.Gravatar Paul Querna 2004-09-27
| | | | | | properly prefix all non-static functions with mod_gnutls_ fix build for GnuTLS 1.0.X. (redefine the changed structure names)
* break up the IO functions into their own fileGravatar Paul Querna 2004-09-27
|
* commit before i move everything aroundGravatar Paul Querna 2004-09-27
|
* updatedGravatar Paul Querna 2004-09-27
|
* iniail makefiles and license fooGravatar Paul Querna 2004-09-27
td>extern const char *log_request_time(request_rec * r, char *a); 105extern const char *log_request_time(request_rec *r, char *a); 104extern const char *log_request_timestamp(request_rec * r, char *a); 106extern const char *log_request_timestamp(request_rec *r, char *a); 105extern const char *log_request_duration(request_rec * r, char *a); 107extern const char *log_request_duration(request_rec *r, char *a); 106extern const char *log_request_line(request_rec * r, char *a); 108extern const char *log_request_line(request_rec *r, char *a); 107extern const char *log_request_file(request_rec * r, char *a); 109extern const char *log_request_file(request_rec *r, char *a); 108extern const char *log_request_uri(request_rec * r, char *a); 110extern const char *log_request_uri(request_rec *r, char *a); 109extern const char *log_status(request_rec * r, char *a); 111extern const char *log_status(request_rec *r, char *a); 110extern const char *log_bytes_sent(request_rec * r, char *a); 112extern const char *log_bytes_sent(request_rec *r, char *a); 111extern const char *log_header_in(request_rec * r, char *a); 113extern const char *log_header_in(request_rec *r, char *a); 112extern const char *log_header_out(request_rec * r, char *a); 114extern const char *log_header_out(request_rec *r, char *a); 113extern const char *log_note(request_rec * r, char *a); 115extern const char *log_note(request_rec *r, char *a); 114extern const char *log_env_var(request_rec * r, char *a); 116extern const char *log_env_var(request_rec *r, char *a); 115extern const char *log_virtual_host(request_rec * r, char *a); 117extern const char *log_virtual_host(request_rec *r, char *a); 116extern const char *log_server_port(request_rec * r, char *a); 118extern const char *log_server_port(request_rec *r, char *a); 117extern const char *log_child_pid(request_rec * r, char *a); 119extern const char *log_child_pid(request_rec *r, char *a); 118#else 120#else 119static char *format_integer(pool *p, int i) 121static char *format_integer(pool *p, int i) 120{ 122{@@ -132,17 +134,22 @@ static char *pfmt(pool *p, int i) 132 } 134 } 133} 135} 134 136 135static const char *log_remote_host(request_rec * r, char *a) 137/* Begin the individual functions that, given a request r, 138 * extract the needed information from it and return the 139 * value to the calling entity. 140 */ 141 142static const char *log_remote_host(request_rec *r, char *a) 136{ 143{ 137 return (char *) get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME); 144 return (char *) get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME); 138} 145} 139 146 140static const char *log_remote_logname(request_rec * r, char *a) 147static const char *log_remote_logname(request_rec *r, char *a) 141{ 148{ 142 return (char *) get_remote_logname(r); 149 return (char *) get_remote_logname(r); 143} 150} 144 151 145static const char *log_remote_user(request_rec * r, char *a) 152static const char *log_remote_user(request_rec *r, char *a) 146{ 153{ 147 char *rvalue = r->connection->user; 154 char *rvalue = r->connection->user; 148 155@@ -154,27 +161,27 @@ static const char *log_remote_user(request_rec * r, char *a) 154 return rvalue; 161 return rvalue; 155} 162} 156 163 157static const char *log_request_line(request_rec * r, char *a) 164static const char *log_request_line(request_rec *r, char *a) 158{ 165{ 159 return r->the_request; 166 return r->the_request; 160} 167} 161 168 162static const char *log_request_file(request_rec * r, char *a) 169static const char *log_request_file(request_rec *r, char *a) 163{ 170{ 164 return r->filename; 171 return r->filename; 165} 172} 166 173 167static const char *log_request_uri(request_rec * r, char *a) 174static const char *log_request_uri(request_rec *r, char *a) 168{ 175{ 169 return r->uri; 176 return r->uri; 170} 177} 171 178 172static const char *log_status(request_rec * r, char *a) 179static const char *log_status(request_rec *r, char *a) 173{ 180{ 174 return pfmt(r->pool, r->status); 181 return pfmt(r->pool, r->status); 175} 182} 176 183 177static const char *log_bytes_sent(request_rec * r, char *a) 184static const char *log_bytes_sent(request_rec *r, char *a) 178{ 185{ 179 if (!r->sent_bodyct) { 186 if (!r->sent_bodyct) { 180 return "-"; 187 return "-";@@ -187,12 +194,12 @@ static const char *log_bytes_sent(request_rec * r, char *a) 187 } 194 } 188} 195} 189 196 190static const char *log_header_in(request_rec * r, char *a) 197static const char *log_header_in(request_rec *r, char *a) 191{ 198{ 192 return table_get(r->headers_in, a); 199 return table_get(r->headers_in, a); 193} 200} 194 201 195static const char *log_header_out(request_rec * r, char *a) 202static const char *log_header_out(request_rec *r, char *a) 196{ 203{ 197 const char *cp = table_get(r->headers_out, a); 204 const char *cp = table_get(r->headers_out, a); 198 if (!strcasecmp(a, "Content-type") && r->content_type) { 205 if (!strcasecmp(a, "Content-type") && r->content_type) {@@ -204,7 +211,7 @@ static const char *log_header_out(request_rec * r, char *a) 204 return table_get(r->err_headers_out, a); 211 return table_get(r->err_headers_out, a); 205} 212} 206 213 207static const char *log_request_time(request_rec * r, char *a) 214static const char *log_request_time(request_rec *r, char *a) 208{ 215{ 209 int timz; 216 int timz; 210 struct tm *t; 217 struct tm *t;@@ -227,7 +234,7 @@ static const char *log_request_time(request_rec * r, char *a) 227 return pstrdup(r->pool, tstr); 234 return pstrdup(r->pool, tstr); 228} 235} 229 236 230static const char *log_request_duration(request_rec * r, char *a) 237static const char *log_request_duration(request_rec *r, char *a) 231{ 238{ 232 char duration[22]; /* Long enough for 2^64 */ 239 char duration[22]; /* Long enough for 2^64 */ 233 240@@ -235,12 +242,12 @@ static const char *log_request_duration(request_rec * r, char *a) 235 return pstrdup(r->pool, duration); 242 return pstrdup(r->pool, duration); 236} 243} 237 244 238static const char *log_virtual_host(request_rec * r, char *a) 245static const char *log_virtual_host(request_rec *r, char *a) 239{ 246{ 240 return pstrdup(r->pool, r->server->server_hostname); 247 return pstrdup(r->pool, r->server->server_hostname); 241} 248} 242 249 243static const char *log_server_port(request_rec * r, char *a) 250static const char *log_server_port(request_rec *r, char *a) 244{ 251{ 245 char portnum[22]; 252 char portnum[22]; 246 253@@ -248,14 +255,14 @@ static const char *log_server_port(request_rec * r, char *a) 248 return pstrdup(r->pool, portnum); 255 return pstrdup(r->pool, portnum); 249} 256} 250 257 251static const char *log_child_pid(request_rec * r, char *a) 258static const char *log_child_pid(request_rec *r, char *a) 252{ 259{ 253 char pidnum[22]; 260 char pidnum[22]; 254 ap_snprintf(pidnum, sizeof(pidnum), "%ld", (long) getpid()); 261 ap_snprintf(pidnum, sizeof(pidnum), "%ld", (long) getpid()); 255 return pstrdup(r->pool, pidnum); 262 return pstrdup(r->pool, pidnum); 256} 263} 257 264 258static const char *log_referer(request_rec * r, char *a) 265static const char *log_referer(request_rec *r, char *a) 259{ 266{ 260 const char *tempref; 267 const char *tempref; 261 268@@ -266,10 +273,9 @@ static const char *log_referer(request_rec * r, char *a) 266 } else { 273 } else { 267 return tempref; 274 return tempref; 268 } 275 } 269 270} 276} 271 277 272static const char *log_agent(request_rec * r, char *a) 278static const char *log_agent(request_rec *r, char *a) 273{ 279{ 274 const char *tempag; 280 const char *tempag; 275 281 @@ -282,7 +288,54 @@ static const char *log_agent(request_rec * r, char *a) 282 } 288 } 283} 289} 284 290 285const char *log_request_timestamp(request_rec * r, char *a) 291static const char *log_cookie(request_rec *r, char *a) 292{ 293 const char *cookiestr; 294 char *cookieend; 295 296 cookiestr = table_get(r->headers_in, "cookie"); 297 298 /* First look for Cookie2: header */ 299 if ( (cookiestr = table_get(r->headers_in, "cookie2")) ) { 300 cookieend = strchr(cookiestr, ';'); 301 if (cookieend) 302 *cookieend = '\0'; /* Ignore anything after a ; */ 303 return cookiestr; 304 } 305 306 /* Then try a Cookie: header */ 307 else if ( (cookiestr = table_get(r->headers_in, "cookie")) ) { 308 cookieend = strchr(cookiestr, ';'); 309 if (cookieend) 310 *cookieend = '\0'; 311 return cookiestr; 312 } 313 314 /* Still none? Use the Set-Cookie: header. I feel a little 315 * guilty about this, because some clients refuse cookies. The 316 * log will in their cases log a ton of different Set-Cookie requests 317 * that aren't being honored. However, it's necessary to insert this 318 * check so that the first request of a series doesn't log a - ... 319 */ 320 else if ( (cookiestr = table_get(r->headers_out, "set-cookie")) ) { 321 cookieend = strchr(cookiestr, ';'); 322 if (cookieend) 323 *cookieend = '\0'; 324 return cookiestr; 325 } 326 327 /* Okay, fine, no eligible headers. Return a - instead. 328 * I /could/ insert a look for the Set-Cookie2: header here, but I think 329 * it would be imprudent. It's apparent that the current browsers don't 330 * support Cookie2 cookies, so why bother logging a bunch of Set-Cookie2: 331 * requests that aren't even going to be honored? 332 */ 333 else { 334 return "-"; 335 } 336} 337 338const char *log_request_timestamp(request_rec *r, char *a) 286{ 339{ 287 char tstr[32]; 340 char tstr[32]; 288 341@@ -290,51 +343,56 @@ const char *log_request_timestamp(request_rec * r, char *a) 290 return pstrdup(r->pool, tstr); 343 return pstrdup(r->pool, tstr); 291} 344} 292 345 293static const char *log_note(request_rec * r, char *a) 346static const char *log_note(request_rec *r, char *a) 294{ 347{ 295 return table_get(r->notes, a); 348 return table_get(r->notes, a); 296} 349} 297 350 298static const char *log_env_var(request_rec * r, char *a) 351static const char *log_env_var(request_rec *r, char *a) 299{ 352{ 300 return table_get(r->subprocess_env, a); 353 return table_get(r->subprocess_env, a); 301} 354} 302#endif 355#endif 303 356 357 358/* End declarations of various log_ functions */ 359 360 304struct log_mysql_item_list { 361struct log_mysql_item_list { 305 char ch; 362 char ch; 306 item_key_func func; 363 item_key_func func; 307 const char *sql_field_name; 364 const char *sql_field_name; 308 int want_orig_default; 365 int want_orig_default; 309 int string_contents; 366 int string_contents; 310} log_mysql_item_keys[] = { 367 } log_mysql_item_keys[] = { 311 368 312 { 'h', log_remote_host, "remote_host", 0, 1 }, 369 { 'A', log_agent, "agent", 1, 1 }, 313 { 'l', log_remote_logname, "remote_logname", 0, 1 }, 370 { 'b', log_bytes_sent, "bytes_sent", 0, 0 }, 314 { 'u', log_remote_user, "remote_user", 0, 1 }, 371 { 'c', log_cookie, "cookie", 0, 1 }, 315 { 't', log_request_time, "request_time", 0, 1 }, 372 { 'e', log_env_var, "env_var", 0, 1 }, 316 { 'S', log_request_timestamp, "time_stamp", 0, 0 }, 373 { 'f', log_request_file, "request_file", 0, 1 }, 317 { 'T', log_request_duration, "request_duration", 1, 0 }, 374 { 'h', log_remote_host, "remote_host", 0, 1 }, 318 { 'r', log_request_line, "request_line", 1, 1 }, 375 { 'i', log_header_in, "header_in", 0, 1 }, 319 { 'f', log_request_file, "request_file", 0, 1 }, 376 { 'l', log_remote_logname, "remote_logname", 0, 1 }, 320 { 'U', log_request_uri, "request_uri", 1, 1 }, 377 { 'n', log_note, "note", 0, 1 }, 321 { 's', log_status, "status", 1, 0 }, 378 { 'o', log_header_out, "header_out", 0, 1 }, 322 { 'b', log_bytes_sent, "bytes_sent", 0, 0 }, 379 { 'P', log_child_pid, "child_pid", 0, 0 }, 323 { 'i', log_header_in, "header_in", 0, 1 }, 380 { 'p', log_server_port, "server_port", 0, 0 }, 324 { 'o', log_header_out, "header_out", 0, 1 }, 381 { 'R', log_referer, "referer", 1, 1 }, 325 { 'n', log_note, "note", 0, 1 }, 382 { 'r', log_request_line, "request_line", 1, 1 }, 326 { 'e', log_env_var, "env_var", 0, 1 }, 383 { 'S', log_request_timestamp, "time_stamp", 0, 0 }, 327 { 'v', log_virtual_host, "virtual_host", 0, 1 }, 384 { 's', log_status, "status", 1, 0 }, 328 { 'p', log_server_port, "server_port", 0, 0 }, 385 { 'T', log_request_duration, "request_duration", 1, 0 }, 329 { 'P', log_child_pid, "child_pid", 0, 0 }, 386 { 't', log_request_time, "request_time", 0, 1 }, 330 { 'R', log_referer, "referer", 0, 1 }, 387 { 'u', log_remote_user, "remote_user", 0, 1 }, 331 { 'A', log_agent, "agent", 0, 1 }, 388 { 'U', log_request_uri, "request_uri", 1, 1 }, 332 { '\0'} 389 { 'v', log_virtual_host, "virtual_host", 0, 1 }, 390 {'\0'} 333}; 391}; 334 392 335 393 336/* Routine to escape 'dangerous' characters that would otherwise 394/* Routine to escape 'dangerous' characters that would otherwise 337 * corrupt the INSERT string. 395 * corrupt the INSERT string: ', \, and " 338 */ 396 */ 339const char *mysql_escape_log(const char *str, pool *p) 397const char *mysql_escape_log(const char *str, pool *p) 340{ 398{@@ -344,10 +402,12 @@ const char *mysql_escape_log(const char *str, pool *p) 344 if (!str) { 402 if (!str) { 345 return NULL; 403 return NULL; 346 } 404 } 347 /* first find out if we need to escape */ 405 406 /* First find out if we need to escape. */ 348 i = 0; 407 i = 0; 349 while (str[i]) { 408 while (str[i]) { 350 if (str[i] != '\'' || str[i] != '\\' || str[i] != '\"') { 409 /* WAS THIS WRONG in 1.05?!? if (str[i] != '\'' || str[i] != '\\' || str[i] != '\"') { */ 410 if (str[i] == '\'' || str[i] == '\\' || str[i] == '\"') { 351 need_to_escape = 1; 411 need_to_escape = 1; 352 break; 412 break; 353 } 413 }@@ -358,10 +418,15 @@ const char *mysql_escape_log(const char *str, pool *p) 358 char *tmp_str; 418 char *tmp_str; 359 int length = strlen(str); 419 int length = strlen(str); 360 420 361 tmp_str = (char *) palloc(p, length * 2 + 1); /* worst case situation, which wouldn't be a pretty sight :) */ 421 /* Pre-allocate a new string that could hold twice the original, which would only 422 * happen if the whole original string was 'dangerous' characters. 423 */ 424 tmp_str = (char *) palloc(p, length *2 + 1); 362 if (!tmp_str) { 425 if (!tmp_str) { 363 return str; 426 return str; 364 } 427 } 428 429 /* Walk through character-by-character, escaping any dangerous characters found. */ 365 for (i = 0, j = 0; i < length; i++, j++) { 430 for (i = 0, j = 0; i < length; i++, j++) { 366 switch (str[i]) { 431 switch (str[i]) { 367 case '\'': 432 case '\'':@@ -373,7 +438,7 @@ const char *mysql_escape_log(const char *str, pool *p) 373 tmp_str[j] = str[i]; 438 tmp_str[j] = str[i]; 374 } 439 } 375 } 440 } 376 tmp_str[j] = 0; 441 tmp_str[j] = '\0'; 377 return tmp_str; 442 return tmp_str; 378 } else { 443 } else { 379 return str; 444 return str;@@ -387,7 +452,6 @@ void open_log_dblink() 387 return; 452 return; 388 } 453 } 389 if (log_db_name) { /* open an SQL link */ 454 if (log_db_name) { /* open an SQL link */ 390 /* link to the MySQL database and register its cleanup!@$ */ 391 mysql_log = mysql_connect(&log_sql_server, db_host, db_user, db_pwd); 455 mysql_log = mysql_connect(&log_sql_server, db_host, db_user, db_pwd); 392 if (mysql_log) { /* link opened */ 456 if (mysql_log) { /* link opened */ 393 if (mysql_select_db(mysql_log, log_db_name) != 0) { /* unable to select database */ 457 if (mysql_select_db(mysql_log, log_db_name) != 0) { /* unable to select database */@@ -399,7 +463,7 @@ void open_log_dblink() 399} 463} 400 464 401 465 402void *make_log_mysql_state(pool *p, server_rec * s) 466void *make_log_mysql_state(pool *p, server_rec *s) 403{ 467{ 404 log_mysql_state *cls = (log_mysql_state *) palloc(p, sizeof(log_mysql_state)); 468 log_mysql_state *cls = (log_mysql_state *) palloc(p, sizeof(log_mysql_state)); 405 469@@ -411,7 +475,7 @@ void *make_log_mysql_state(pool *p, server_rec * s) 411 return (void *) cls; 475 return (void *) cls; 412} 476} 413 477 414const char *set_referer_log_mysql_table(cmd_parms * parms, void *dummy, char *arg) 478const char *set_referer_log_mysql_table(cmd_parms *parms, void *dummy, char *arg) 415{ 479{ 416 log_mysql_state *cls = get_module_config(parms->server->module_config, 480 log_mysql_state *cls = get_module_config(parms->server->module_config, 417 &mysql_log_module); 481 &mysql_log_module);@@ -421,7 +485,7 @@ const char *set_referer_log_mysql_table(cmd_parms * parms, void *dummy, char *ar 421} 485} 422 486 423 487 424const char *set_agent_log_mysql_table(cmd_parms * parms, void *dummy, char *arg) 488const char *set_agent_log_mysql_table(cmd_parms *parms, void *dummy, char *arg) 425{ 489{ 426 log_mysql_state *cls = get_module_config(parms->server->module_config, 490 log_mysql_state *cls = get_module_config(parms->server->module_config, 427 &mysql_log_module); 491 &mysql_log_module);@@ -431,7 +495,7 @@ const char *set_agent_log_mysql_table(cmd_parms * parms, void *dummy, char *arg) 431} 495} 432 496 433 497 434const char *set_transfer_log_mysql_table(cmd_parms * parms, void *dummy, char *arg) 498const char *set_transfer_log_mysql_table(cmd_parms *parms, void *dummy, char *arg) 435{ 499{ 436 log_mysql_state *cls = get_module_config(parms->server->module_config, 500 log_mysql_state *cls = get_module_config(parms->server->module_config, 437 &mysql_log_module); 501 &mysql_log_module);@@ -441,7 +505,7 @@ const char *set_transfer_log_mysql_table(cmd_parms * parms, void *dummy, char *a 441} 505} 442 506 443 507 444const char *set_transfer_log_format(cmd_parms * parms, void *dummy, char *arg) 508const char *set_transfer_log_format(cmd_parms *parms, void *dummy, char *arg) 445{ 509{ 446 log_mysql_state *cls = get_module_config(parms->server->module_config, 510 log_mysql_state *cls = get_module_config(parms->server->module_config, 447 &mysql_log_module); 511 &mysql_log_module);@@ -451,13 +515,13 @@ const char *set_transfer_log_format(cmd_parms * parms, void *dummy, char *arg) 451} 515} 452 516 453 517 454const char *set_log_mysql_db(cmd_parms * parms, void *dummy, char *arg) 518const char *set_log_mysql_db(cmd_parms *parms, void *dummy, char *arg) 455{ 519{ 456 log_db_name = arg; 520 log_db_name = arg; 457 return NULL; 521 return NULL; 458} 522} 459 523 460const char *set_log_mysql_info(cmd_parms * parms, void *dummy, char *host, char *user, char *pwd) 524const char *set_log_mysql_info(cmd_parms *parms, void *dummy, char *host, char *user, char *pwd) 461{ 525{ 462 if (*host != '.') { 526 if (*host != '.') { 463 db_host = host; 527 db_host = host;@@ -472,7 +536,7 @@ const char *set_log_mysql_info(cmd_parms * parms, void *dummy, char *host, char 472} 536} 473 537 474 538 475const char *add_referer_mysql_ignore(cmd_parms * parms, void *dummy, char *arg) 539const char *add_referer_mysql_ignore(cmd_parms *parms, void *dummy, char *arg) 476{ 540{ 477 char **addme; 541 char **addme; 478 log_mysql_state *cls = get_module_config(parms->server->module_config, 542 log_mysql_state *cls = get_module_config(parms->server->module_config,@@ -483,7 +547,7 @@ const char *add_referer_mysql_ignore(cmd_parms * parms, void *dummy, char *arg) 483 return NULL; 547 return NULL; 484} 548} 485 549 486const char *add_transfer_mysql_ignore(cmd_parms * parms, void *dummy, char *arg) 550const char *add_transfer_mysql_ignore(cmd_parms *parms, void *dummy, char *arg) 487{ 551{ 488 char **addme; 552 char **addme; 489 log_mysql_state *cls = get_module_config(parms->server->module_config, 553 log_mysql_state *cls = get_module_config(parms->server->module_config,@@ -494,7 +558,7 @@ const char *add_transfer_mysql_ignore(cmd_parms * parms, void *dummy, char *arg) 494 return NULL; 558 return NULL; 495} 559} 496 560 497const char *add_remhost_mysql_ignore(cmd_parms * parms, void *dummy, char *arg) 561const char *add_remhost_mysql_ignore(cmd_parms *parms, void *dummy, char *arg) 498{ 562{ 499 char **addme; 563 char **addme; 500 log_mysql_state *cls = get_module_config(parms->server->module_config, 564 log_mysql_state *cls = get_module_config(parms->server->module_config,@@ -537,28 +601,7 @@ command_rec log_mysql_cmds[] = { 537}; 601}; 538 602 539 603 540void log_mysql_child(void *cmd) 604int safe_mysql_query(request_rec *r, const char *query) 541{ 542 /* Child process code for 'RefererLog "|..."'; 543 * may want a common framework for this, since I expect it will 544 * be common for other foo-loggers to want this sort of thing... 545 */ 546 547 cleanup_for_exec(); 548 signal(SIGHUP, SIG_IGN); 549#ifdef __EMX__ 550 /* For OS/2 we need to use a '/' */ 551 execl(SHELL_PATH, SHELL_PATH, "/c", (char *) cmd, NULL); 552#else 553 execl(SHELL_PATH, SHELL_PATH, "-c", (char *) cmd, NULL); 554#endif 555 perror("execl"); 556 fprintf(stderr, "Exec of shell for logging failed!!!\n"); 557 exit(1); 558} 559 560 561int safe_mysql_query(request_rec * r, const char *query) 562{ 605{ 563 int error = 1; 606 int error = 1; 564 struct timespec delay, remainder; 607 struct timespec delay, remainder;@@ -566,8 +609,10 @@ int safe_mysql_query(request_rec * r, const char *query) 566 char *str; 609 char *str; 567 void (*handler) (int); 610 void (*handler) (int); 568 611 569 handler = signal(SIGPIPE, SIG_IGN); /* a failed mysql_query() may send a SIGPIPE */ 612 /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */ 613 handler = signal(SIGPIPE, SIG_IGN); 570 614 615 /* If there's no DB link, or if we run the query and it gacks, try to be graceful */ 571 if ( !mysql_log || 616 if ( !mysql_log || 572 ( 617 ( 573 (error = mysql_query(mysql_log, query)) && 618 (error = mysql_query(mysql_log, query)) && @@ -576,13 +621,12 @@ int safe_mysql_query(request_rec * r, const char *query) 576 ) 621 ) 577 622 578 { /* We need to restart the server link */ 623 { /* We need to restart the server link */ 579 580 mysql_log = NULL; 624 mysql_log = NULL; 581 log_error("MySQL: connection lost, attempting reconnect", r->server); 625 log_error("MySQL: connection lost, attempting reconnect", r->server); 582 626 583 open_log_dblink(); 627 open_log_dblink(); 584 628 585 if (mysql_log == NULL) { /* unable to link */ 629 if (mysql_log == NULL) { /* still unable to link */ 586 signal(SIGPIPE, handler); 630 signal(SIGPIPE, handler); 587 log_error("MySQL: reconnect failed.", r->server); 631 log_error("MySQL: reconnect failed.", r->server); 588 return error; 632 return error;@@ -590,13 +634,13 @@ int safe_mysql_query(request_rec * r, const char *query) 590 634 591 log_error("MySQL: reconnect successful.", r->server); 635 log_error("MySQL: reconnect successful.", r->server); 592 error = mysql_query(mysql_log, query); 636 error = mysql_query(mysql_log, query); 593 } 637 } 594 638 639 /* Restore SIGPIPE to its original handler function */ 595 signal(SIGPIPE, handler); 640 signal(SIGPIPE, handler); 596 641 597 if (error) { 642 if (error) { 598 /* Attempt a single re-try... First sleep for a tiny amount of time. */ 643 /* Attempt a single re-try... First sleep for a tiny amount of time. */ 599 600 delay.tv_sec = 0; 644 delay.tv_sec = 0; 601 delay.tv_nsec = 500000000; /* max is 999999999 (nine nines) */ 645 delay.tv_nsec = 500000000; /* max is 999999999 (nine nines) */ 602 ret = nanosleep(&delay, &remainder); 646 ret = nanosleep(&delay, &remainder);@@ -622,7 +666,7 @@ int safe_mysql_query(request_rec * r, const char *query) 622/* Routine to perform the actual construction and execution of the relevant 666/* Routine to perform the actual construction and execution of the relevant 623 * INSERT statements. 667 * INSERT statements. 624 */ 668 */ 625int log_mysql_transaction(request_rec * orig) 669int log_mysql_transaction(request_rec *orig) 626{ 670{ 627 char **ptrptr, **ptrptr2; 671 char **ptrptr, **ptrptr2; 628 log_mysql_state *cls = get_module_config(orig->server->module_config, 672 log_mysql_state *cls = get_module_config(orig->server->module_config,@@ -633,7 +677,7 @@ int log_mysql_transaction(request_rec * orig) 633 int retvalue = DECLINED; 677 int retvalue = DECLINED; 634 int referer_needed, agent_needed, transfer_needed; 678 int referer_needed, agent_needed, transfer_needed; 635 679 636 /* Are there configuration directives for these logs? For each found 680 /* Are there configuration directives for these SQL logs? For each found 637 * config directive that is found, mark that type as 'needed'. 681 * config directive that is found, mark that type as 'needed'. 638 */ 682 */ 639 referer_needed = ((cls->referer_table_name[0] != '\0') ? 1 : 0); 683 referer_needed = ((cls->referer_table_name[0] != '\0') ? 1 : 0);@@ -643,12 +687,14 @@ int log_mysql_transaction(request_rec * orig) 643 if (!referer_needed && !agent_needed && !transfer_needed) { 687 if (!referer_needed && !agent_needed && !transfer_needed) { 644 return OK; 688 return OK; 645 } 689 } 690 646 if (mysql_log == NULL) { /* mysql link not up, hopefully we can do something about it */ 691 if (mysql_log == NULL) { /* mysql link not up, hopefully we can do something about it */ 647 open_log_dblink(); 692 open_log_dblink(); 648 if (mysql_log == NULL) { 693 if (mysql_log == NULL) { 649 return OK; 694 return OK; 650 } 695 } 651 } 696 } 697 652 for (r = orig; r->next; r = r->next) { 698 for (r = orig; r->next; r = r->next) { 653 continue; 699 continue; 654 } 700 }@@ -660,12 +706,12 @@ int log_mysql_transaction(request_rec * orig) 660 if (referer != NULL) { 706 if (referer != NULL) { 661 707 662 /* The following is an upsetting mess of pointers, I'm sorry 708 /* The following is an upsetting mess of pointers, I'm sorry 663 Anyone with the motiviation and/or the time should feel free 709 * Anyone with the motiviation and/or the time should feel free 664 to make this cleaner... */ 710 * to make this cleaner... */ 665 ptrptr2 = (char **) (cls->referer_ignore_list->elts + (cls->referer_ignore_list->nelts * cls->referer_ignore_list->elt_size)); 711 ptrptr2 = (char **) (cls->referer_ignore_list->elts + (cls->referer_ignore_list->nelts * cls->referer_ignore_list->elt_size)); 666 712 667 /* Go through each element of the ignore list and compare it to the 713 /* Go through each element of the ignore list and compare it to the 668 referer_host. If we get a match, return without logging */ 714 * referer_host. If we get a match, return without logging */ 669 for (ptrptr = (char **) cls->referer_ignore_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->referer_ignore_list->elt_size)) { 715 for (ptrptr = (char **) cls->referer_ignore_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->referer_ignore_list->elt_size)) { 670 if (strstr(referer, *ptrptr)) { 716 if (strstr(referer, *ptrptr)) { 671 return OK; 717 return OK;@@ -679,8 +725,10 @@ int log_mysql_transaction(request_rec * orig) 679 /* Log the 'user agent' to its own log if configured to do so. */ 725 /* Log the 'user agent' to its own log if configured to do so. */ 680 if (agent_needed) { 726 if (agent_needed) { 681 const char *agent, *str; 727 const char *agent, *str; 728 682 retvalue = OK; 729 retvalue = OK; 683 agent = table_get(orig->headers_in, "User-Agent"); 730 agent = table_get(orig->headers_in, "User-Agent"); 731 684 if (agent != NULL) { 732 if (agent != NULL) { 685 str = pstrcat(orig->pool, "insert into ", cls->agent_table_name, "(agent,time_stamp) values ('", mysql_escape_log(agent, orig->pool), "',unix_timestamp(now()) )", NULL); 733 str = pstrcat(orig->pool, "insert into ", cls->agent_table_name, "(agent,time_stamp) values ('", mysql_escape_log(agent, orig->pool), "',unix_timestamp(now()) )", NULL); 686 safe_mysql_query(orig, str); 734 safe_mysql_query(orig, str);@@ -699,12 +747,12 @@ int log_mysql_transaction(request_rec * orig) 699 747 700 748 701 /* The following is a stolen upsetting mess of pointers, I'm sorry 749 /* The following is a stolen upsetting mess of pointers, I'm sorry 702 Anyone with the motiviation and/or the time should feel free 750 * Anyone with the motiviation and/or the time should feel free 703 to make this cleaner, and while at it, clean the same mess at the RefererLog part :) */ 751 * to make this cleaner, and while at it, clean the same mess at the RefererLog part :) */ 704 ptrptr2 = (char **) (cls->transfer_ignore_list->elts + (cls->transfer_ignore_list->nelts * cls->transfer_ignore_list->elt_size)); 752 ptrptr2 = (char **) (cls->transfer_ignore_list->elts + (cls->transfer_ignore_list->nelts * cls->transfer_ignore_list->elt_size)); 705 753 706 /* Go through each element of the ignore list and compare it to the 754 /* Go through each element of the ignore list and compare it to the 707 request_uri. If we get a match, return without logging */ 755 * request_uri. If we get a match, return without logging */ 708 if (r->uri) { 756 if (r->uri) { 709 for (ptrptr = (char **) cls->transfer_ignore_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->transfer_ignore_list->elt_size)) { 757 for (ptrptr = (char **) cls->transfer_ignore_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->transfer_ignore_list->elt_size)) { 710 if (strstr(r->uri, *ptrptr)) { 758 if (strstr(r->uri, *ptrptr)) {@@ -713,9 +761,8 @@ int log_mysql_transaction(request_rec * orig) 713 } 761 } 714 } 762 } 715 763 716 717 /* Go through each element of the ignore list and compare it to the 764 /* Go through each element of the ignore list and compare it to the 718 remote host. If we get a match, return without logging */ 765 * remote host. If we get a match, return without logging */ 719 ptrptr2 = (char **) (cls->remhost_ignore_list->elts + (cls->remhost_ignore_list->nelts * cls->remhost_ignore_list->elt_size)); 766 ptrptr2 = (char **) (cls->remhost_ignore_list->elts + (cls->remhost_ignore_list->nelts * cls->remhost_ignore_list->elt_size)); 720 thehost = get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME); 767 thehost = get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME); 721 if (thehost) { 768 if (thehost) {@@ -726,21 +773,23 @@ int log_mysql_transaction(request_rec * orig) 726 } 773 } 727 } 774 } 728 775 729 776 /* If not specified by the user, use the default format */ 730 if (cls->transfer_log_format[0] == '\0') { 777 if (cls->transfer_log_format[0] == '\0') { 731 /* If not specified by the user, use the default format */ 732 cls->transfer_log_format = "huSUsbTvRA"; 778 cls->transfer_log_format = "huSUsbTvRA"; 733 } 779 } 734 length = strlen(cls->transfer_log_format); 780 length = strlen(cls->transfer_log_format); 735 781 736 /* Iterate through the characters and set up the INSERT string according to 782 /* Iterate through the format characters and set up the INSERT string according to 737 * what the user has configured. */ 783 * what the user has configured. */ 738 for (i = 0; i < length; i++) { 784 for (i = 0; i < length; i++) { 739 j = 0; 785 j = 0; 740 while (log_mysql_item_keys[j].ch) { 786 while (log_mysql_item_keys[j].ch) { 741 if (log_mysql_item_keys[j].ch == cls->transfer_log_format[i]) { 787 if (log_mysql_item_keys[j].ch == cls->transfer_log_format[i]) { 742 /* Yes, this key is one of the configured keys */ 788 /* Yes, this key is one of the configured keys. 789 * Call the key's function and put the returned value into 'formatted_item' */ 743 formatted_item = log_mysql_item_keys[j].func(log_mysql_item_keys[j].want_orig_default ? orig : r, ""); 790 formatted_item = log_mysql_item_keys[j].func(log_mysql_item_keys[j].want_orig_default ? orig : r, ""); 791 792 /* Massage 'formatted_item' for proper SQL eligibility... */ 744 if (!formatted_item) { 793 if (!formatted_item) { 745 formatted_item = ""; 794 formatted_item = ""; 746 } else if (formatted_item[0] == '-' && formatted_item[1] == '\0' && !log_mysql_item_keys[j].string_contents) { 795 } else if (formatted_item[0] == '-' && formatted_item[1] == '\0' && !log_mysql_item_keys[j].string_contents) {@@ -748,6 +797,8 @@ int log_mysql_transaction(request_rec * orig) 748 * because the database expects an integer. */ 797 * because the database expects an integer. */ 749 formatted_item = "0"; 798 formatted_item = "0"; 750 } 799 } 800 801 /* Append the fieldname and value-to-insert to teh appropriate strings, quoting stringvals with ' as appropriate */ 751 fields = pstrcat(orig->pool, fields, (i > 0 ? "," : ""), log_mysql_item_keys[j].sql_field_name, NULL); 802 fields = pstrcat(orig->pool, fields, (i > 0 ? "," : ""), log_mysql_item_keys[j].sql_field_name, NULL); 752 values = pstrcat(orig->pool, values, (i > 0 ? "," : ""), (log_mysql_item_keys[j].string_contents ? "'" : ""), mysql_escape_log(formatted_item, orig->pool), (log_mysql_item_keys[j].string_contents ? "'" : ""), NULL); 803 values = pstrcat(orig->pool, values, (i > 0 ? "," : ""), (log_mysql_item_keys[j].string_contents ? "'" : ""), mysql_escape_log(formatted_item, orig->pool), (log_mysql_item_keys[j].string_contents ? "'" : ""), NULL); 753 break; 804 break;