diff options
Diffstat (limited to 'mod_log_sql.c')
| -rw-r--r-- | mod_log_sql.c | 992 |
1 files changed, 532 insertions, 460 deletions
diff --git a/mod_log_sql.c b/mod_log_sql.c index fc9dcc0..7320f66 100644 --- a/mod_log_sql.c +++ b/mod_log_sql.c | |||
| @@ -1,4 +1,19 @@ | |||
| 1 | /* $Id$ */ | 1 | /* $Header: /home/cvs/mod_log_sql/mod_log_sql.c,v 1.14 2004/02/05 21:59:46 urkle Exp $ */ |
| 2 | /* --------* | ||
| 3 | * DEFINES * | ||
| 4 | * --------*/ | ||
| 5 | |||
| 6 | /* The enduser may wish to modify this */ | ||
| 7 | #define DEBUG | ||
| 8 | |||
| 9 | /* The enduser won't modify these */ | ||
| 10 | #define MYSQL_ERROR(mysql) ((mysql)?(mysql_error(mysql)):"MySQL server has gone away") | ||
| 11 | |||
| 12 | /* ---------* | ||
| 13 | * INCLUDES * | ||
| 14 | * ---------*/ | ||
| 15 | #include "mysql.h" | ||
| 16 | #include "mysqld_error.h" | ||
| 2 | 17 | ||
| 3 | #if defined(WITH_APACHE20) | 18 | #if defined(WITH_APACHE20) |
| 4 | # include "apache20.h" | 19 | # include "apache20.h" |
| @@ -36,7 +51,7 @@ | |||
| 36 | #define DEFAULT_HIN_TABLE_NAME "headers_in" | 51 | #define DEFAULT_HIN_TABLE_NAME "headers_in" |
| 37 | #define DEFAULT_HOUT_TABLE_NAME "headers_out" | 52 | #define DEFAULT_HOUT_TABLE_NAME "headers_out" |
| 38 | #define DEFAULT_COOKIE_TABLE_NAME "cookies" | 53 | #define DEFAULT_COOKIE_TABLE_NAME "cookies" |
| 39 | #define DEFAULT_PRESERVE_FILE "logs/mod_log_sql-preserve" | 54 | #define DEFAULT_PRESERVE_FILE "/tmp/sql-preserve" |
| 40 | 55 | ||
| 41 | /* -------------* | 56 | /* -------------* |
| 42 | * DECLARATIONS * | 57 | * DECLARATIONS * |
| @@ -54,11 +69,17 @@ typedef struct { | |||
| 54 | int massvirtual; | 69 | int massvirtual; |
| 55 | int createtables; | 70 | int createtables; |
| 56 | int forcepreserve; | 71 | int forcepreserve; |
| 57 | int disablepreserve; | 72 | char *tabletype; |
| 73 | char *dbname; | ||
| 74 | char *dbhost; | ||
| 75 | char *dbuser; | ||
| 76 | char *dbpwd; | ||
| 58 | char *machid; | 77 | char *machid; |
| 59 | int announce; | 78 | char *socketfile; |
| 60 | logsql_dbconnection db; | 79 | unsigned int tcpport; |
| 61 | logsql_dbdriver *driver; | 80 | int insertdelayed; |
| 81 | MYSQL server; | ||
| 82 | MYSQL *server_p; | ||
| 62 | } global_config_t; | 83 | } global_config_t; |
| 63 | 84 | ||
| 64 | static global_config_t global_config; | 85 | static global_config_t global_config; |
| @@ -66,11 +87,11 @@ static global_config_t global_config; | |||
| 66 | /* structure to hold helper function info */ | 87 | /* structure to hold helper function info */ |
| 67 | typedef struct { | 88 | typedef struct { |
| 68 | char key; /* item letter character */ | 89 | char key; /* item letter character */ |
| 69 | logsql_item_func *func; /* its extraction function */ | 90 | log_sql_item_func *func; /* its extraction function */ |
| 70 | const char *sql_field_name; /* its column in SQL */ | 91 | const char *sql_field_name; /* its column in SQL */ |
| 71 | int want_orig_default; /* if it requires the original request prior to internal redirection */ | 92 | int want_orig_default; /* if it requires the original request prior to internal redirection */ |
| 72 | int string_contents; /* if it returns a string */ | 93 | int string_contents; /* if it returns a string */ |
| 73 | } logsql_item; | 94 | } log_sql_item; |
| 74 | 95 | ||
| 75 | /* But the contents of this structure will vary by virtual server. | 96 | /* But the contents of this structure will vary by virtual server. |
| 76 | * This permits each virtual server to vary its configuration slightly | 97 | * This permits each virtual server to vary its configuration slightly |
| @@ -93,28 +114,33 @@ typedef struct { | |||
| 93 | const char *transfer_table_name; | 114 | const char *transfer_table_name; |
| 94 | const char *transfer_log_format; | 115 | const char *transfer_log_format; |
| 95 | apr_pool_t *parsed_pool; | 116 | apr_pool_t *parsed_pool; |
| 96 | logsql_item **parsed_log_format; | 117 | log_sql_item **parsed_log_format; |
| 97 | const char *preserve_file; | 118 | const char *preserve_file; |
| 98 | const char *cookie_name; | 119 | const char *cookie_name; |
| 99 | } logsql_state; | 120 | } logsql_state; |
| 100 | 121 | ||
| 101 | 122 | ||
| 102 | /* list of "handlers" for log types */ | 123 | /* -----------------* |
| 103 | static apr_array_header_t *logsql_item_list; | 124 | * HELPER FUNCTIONS * |
| 125 | * -----------------*/ | ||
| 126 | |||
| 127 | static int safe_create_tables(logsql_state *cls, request_rec *r); | ||
| 104 | 128 | ||
| 105 | /* Registration function for extract functions * | 129 | static apr_array_header_t *log_sql_item_list; |
| 130 | |||
| 131 | /* Registration Function for extract functions * | ||
| 106 | * and update parse cache for transfer_log_format * | 132 | * and update parse cache for transfer_log_format * |
| 107 | * this is exported from the module */ | 133 | * this is exported from the module */ |
| 108 | LOGSQL_DECLARE(void) log_sql_register_item(server_rec *s, apr_pool_t *p, | 134 | LOGSQL_DECLARE(void) log_sql_register_item(server_rec *s, apr_pool_t *p, |
| 109 | char key, logsql_item_func *func, const char *sql_field_name, | 135 | char key, log_sql_item_func *func, const char *sql_field_name, |
| 110 | int want_orig_default, int string_contents) | 136 | int want_orig_default, int string_contents) |
| 111 | { | 137 | { |
| 112 | server_rec *ts; | 138 | server_rec *ts; |
| 113 | logsql_item *item; | 139 | log_sql_item *item; |
| 114 | if (!logsql_item_list) | 140 | if (!log_sql_item_list) |
| 115 | logsql_item_list = apr_array_make(p,10, sizeof(logsql_item)); | 141 | log_sql_item_list = apr_array_make(p,10, sizeof(log_sql_item)); |
| 116 | 142 | ||
| 117 | item= apr_array_push(logsql_item_list); | 143 | item= apr_array_push(log_sql_item_list); |
| 118 | item->key = key; | 144 | item->key = key; |
| 119 | item->func = func; | 145 | item->func = func; |
| 120 | item->sql_field_name = sql_field_name; | 146 | item->sql_field_name = sql_field_name; |
| @@ -128,21 +154,14 @@ LOGSQL_DECLARE(void) log_sql_register_item(server_rec *s, apr_pool_t *p, | |||
| 128 | char *pos; | 154 | char *pos; |
| 129 | 155 | ||
| 130 | if (cfg->transfer_log_format) { | 156 | if (cfg->transfer_log_format) { |
| 131 | if ( (pos = ap_strchr_c(cfg->transfer_log_format,key))!=NULL) { | 157 | if ( (pos = strchr(cfg->transfer_log_format,key))!=NULL) { |
| 132 | cfg->parsed_log_format[pos - cfg->transfer_log_format] = item; | 158 | cfg->parsed_log_format[pos - cfg->transfer_log_format] = item; |
| 133 | } | 159 | } |
| 134 | } | 160 | } |
| 135 | } | 161 | } |
| 136 | } | 162 | } |
| 137 | 163 | ||
| 138 | /* Registration function for database drivers */ | 164 | /* Include all the extract functions */ |
| 139 | LOGSQL_DECLARE(void) log_sql_register_driver(apr_pool_t *p, | ||
| 140 | logsql_dbdriver *driver) | ||
| 141 | { | ||
| 142 | global_config.driver = driver; | ||
| 143 | } | ||
| 144 | |||
| 145 | /* Include all the core extract functions */ | ||
| 146 | #include "functions.h" | 165 | #include "functions.h" |
| 147 | #if defined(WITH_APACHE13) | 166 | #if defined(WITH_APACHE13) |
| 148 | # include "functions13.h" | 167 | # include "functions13.h" |
| @@ -150,33 +169,82 @@ LOGSQL_DECLARE(void) log_sql_register_driver(apr_pool_t *p, | |||
| 150 | # include "functions20.h" | 169 | # include "functions20.h" |
| 151 | #endif | 170 | #endif |
| 152 | 171 | ||
| 153 | static logsql_opendb_ret log_sql_opendb_link(server_rec* s) | 172 | /* Routine to escape the 'dangerous' characters that would otherwise |
| 173 | * corrupt the INSERT string: ', \, and " | ||
| 174 | */ | ||
| 175 | static const char *escape_query(const char *from_str, apr_pool_t *p) | ||
| 154 | { | 176 | { |
| 155 | logsql_opendb_ret result; | 177 | if (!from_str) |
| 156 | if (global_config.forcepreserve) { | 178 | return NULL; |
| 157 | global_config.db.connected = 1; | 179 | else { |
| 158 | return LOGSQL_OPENDB_PRESERVE; | 180 | char *to_str; |
| 159 | } | 181 | unsigned long length = strlen(from_str); |
| 160 | if (global_config.db.connected) { | 182 | unsigned long retval; |
| 161 | return LOGSQL_OPENDB_ALREADY; | 183 | |
| 184 | /* Pre-allocate a new string that could hold twice the original, which would only | ||
| 185 | * happen if the whole original string was 'dangerous' characters. | ||
| 186 | */ | ||
| 187 | to_str = (char *) apr_palloc(p, length * 2 + 1); | ||
| 188 | if (!to_str) { | ||
| 189 | return from_str; | ||
| 190 | } | ||
| 191 | |||
| 192 | if (!global_config.server_p) { | ||
| 193 | /* Well, I would have liked to use the current database charset. mysql is | ||
| 194 | * unavailable, however, so I fall back to the slightly less respectful | ||
| 195 | * mysql_escape_string() function that uses the default charset. | ||
| 196 | */ | ||
| 197 | retval = mysql_escape_string(to_str, from_str, length); | ||
| 198 | } else { | ||
| 199 | /* MySQL is available, so I'll go ahead and respect the current charset when | ||
| 200 | * I perform the escape. | ||
| 201 | */ | ||
| 202 | retval = mysql_real_escape_string(global_config.server_p, to_str, from_str, length); | ||
| 203 | } | ||
| 204 | |||
| 205 | if (retval) | ||
| 206 | return to_str; | ||
| 207 | else | ||
| 208 | return from_str; | ||
| 162 | } | 209 | } |
| 163 | /* database | 210 | } |
| 164 | host | 211 | |
| 165 | user | 212 | static int open_logdb_link(server_rec* s) |
| 166 | passwd | 213 | { |
| 214 | /* Returns: | ||
| 215 | 3 if preserve forced | ||
| 216 | 2 if already connected | ||
| 217 | 1 if successful | ||
| 218 | 0 if unsuccessful | ||
| 167 | */ | 219 | */ |
| 168 | if (global_config.db.parms) { | 220 | |
| 169 | result = global_config.driver->connect(s, &global_config.db); | 221 | if (global_config.forcepreserve) |
| 170 | if (result==LOGSQL_OPENDB_FAIL) { | 222 | return 3; |
| 171 | global_config.db.connected = 0; | 223 | |
| 224 | if (global_config.server_p) | ||
| 225 | return 2; | ||
| 226 | |||
| 227 | if ((global_config.dbname) && (global_config.dbhost) && (global_config.dbuser) && (global_config.dbpwd)) { | ||
| 228 | mysql_init(&global_config.server); | ||
| 229 | global_config.server_p = mysql_real_connect(&global_config.server, global_config.dbhost, global_config.dbuser, global_config.dbpwd, global_config.dbname, global_config.tcpport, global_config.socketfile, 0); | ||
| 230 | |||
| 231 | if (global_config.server_p) { | ||
| 232 | #ifdef DEBUG | ||
| 233 | log_error(APLOG_MARK,APLOG_DEBUG,s,"HOST: '%s' PORT: '%d' DB: '%s' USER: '%s' SOCKET: '%s'", | ||
| 234 | global_config.dbhost, global_config.tcpport, global_config.dbname, global_config.dbuser, global_config.socketfile); | ||
| 235 | #endif | ||
| 236 | return 1; | ||
| 172 | } else { | 237 | } else { |
| 173 | global_config.db.connected = 1; | 238 | #ifdef DEBUG |
| 239 | log_error(APLOG_MARK,APLOG_DEBUG,s,"mod_log_sql: database connection error: %s",MYSQL_ERROR(&global_config.server)); | ||
| 240 | log_error(APLOG_MARK,APLOG_DEBUG,s,"HOST: '%s' PORT: '%d' DB: '%s' USER: '%s' SOCKET: '%s'", | ||
| 241 | global_config.dbhost, global_config.tcpport, global_config.dbname, global_config.dbuser, global_config.socketfile); | ||
| 242 | #endif | ||
| 243 | return 0; | ||
| 174 | } | 244 | } |
| 175 | return result; | ||
| 176 | } else { | 245 | } else { |
| 177 | log_error(APLOG_MARK, APLOG_ERR, 0, s, | 246 | log_error(APLOG_MARK,APLOG_ERR,s,"mod_log_sql: insufficient configuration info to establish database link"); |
| 178 | "mod_log_sql: insufficient configuration info to establish database link"); | 247 | return 0; |
| 179 | return LOGSQL_OPENDB_FAIL; | ||
| 180 | } | 248 | } |
| 181 | } | 249 | } |
| 182 | 250 | ||
| @@ -194,22 +262,15 @@ static void preserve_entry(request_rec *r, const char *query) | |||
| 194 | #if defined(WITH_APACHE20) | 262 | #if defined(WITH_APACHE20) |
| 195 | apr_file_t *fp; | 263 | apr_file_t *fp; |
| 196 | apr_status_t result; | 264 | apr_status_t result; |
| 265 | result = apr_file_open(&fp, cls->preserve_file,APR_APPEND, APR_OS_DEFAULT, r->pool); | ||
| 197 | #elif defined(WITH_APACHE13) | 266 | #elif defined(WITH_APACHE13) |
| 198 | FILE *fp; | 267 | FILE *fp; |
| 199 | int result; | 268 | int result; |
| 200 | #endif | ||
| 201 | /* If preserve file is disabled bail out */ | ||
| 202 | if (global_config.disablepreserve) | ||
| 203 | return; | ||
| 204 | #if defined(WITH_APACHE20) | ||
| 205 | result = apr_file_open(&fp, cls->preserve_file,APR_APPEND | APR_WRITE | APR_CREATE, APR_OS_DEFAULT, r->pool); | ||
| 206 | #elif defined(WITH_APACHE13) | ||
| 207 | fp = ap_pfopen(r->pool, cls->preserve_file, "a"); | 269 | fp = ap_pfopen(r->pool, cls->preserve_file, "a"); |
| 208 | result = (fp)?0:errno; | 270 | result = (fp)?0:1; |
| 209 | #endif | 271 | #endif |
| 210 | if (result != APR_SUCCESS) { | 272 | if (result != APR_SUCCESS) { |
| 211 | log_error(APLOG_MARK, APLOG_ERR, result, r->server, | 273 | log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: attempted append of local preserve file but failed."); |
| 212 | "attempted append of local preserve file '%s' but failed.",cls->preserve_file); | ||
| 213 | } else { | 274 | } else { |
| 214 | #if defined(WITH_APACHE20) | 275 | #if defined(WITH_APACHE20) |
| 215 | apr_file_printf(fp,"%s;\n", query); | 276 | apr_file_printf(fp,"%s;\n", query); |
| @@ -218,12 +279,252 @@ static void preserve_entry(request_rec *r, const char *query) | |||
| 218 | fprintf(fp,"%s;\n", query); | 279 | fprintf(fp,"%s;\n", query); |
| 219 | ap_pfclose(r->pool, fp); | 280 | ap_pfclose(r->pool, fp); |
| 220 | #endif | 281 | #endif |
| 221 | log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, | 282 | #ifdef DEBUG |
| 222 | "mod_log_sql: entry preserved in %s", cls->preserve_file); | 283 | log_error(APLOG_MARK,APLOG_DEBUG,r->server,"mod_log_sql: entry preserved in %s", cls->preserve_file); |
| 284 | #endif | ||
| 223 | } | 285 | } |
| 224 | } | 286 | } |
| 225 | 287 | ||
| 226 | 288 | ||
| 289 | /*-----------------------------------------------------* | ||
| 290 | * safe_sql_query: perform a database query with * | ||
| 291 | * a degree of safety and error checking. * | ||
| 292 | * * | ||
| 293 | * Parms: request record, SQL insert statement * | ||
| 294 | * Returns: 0 (OK) on success * | ||
| 295 | * 1 if have no log handle * | ||
| 296 | * 2 if insert delayed failed (kluge) * | ||
| 297 | * the actual MySQL return code on error * | ||
| 298 | *-----------------------------------------------------*/ | ||
| 299 | static unsigned int safe_sql_query(request_rec *r, const char *query) | ||
| 300 | { | ||
| 301 | int retval; | ||
| 302 | struct timespec delay, remainder; | ||
| 303 | int ret; | ||
| 304 | void (*handler) (int); | ||
| 305 | logsql_state *cls; | ||
| 306 | unsigned int real_error = 0; | ||
| 307 | const char *real_error_str = NULL; | ||
| 308 | |||
| 309 | /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */ | ||
| 310 | handler = signal(SIGPIPE, SIG_IGN); | ||
| 311 | |||
| 312 | /* First attempt for the query */ | ||
| 313 | if (!global_config.server_p) { | ||
| 314 | signal(SIGPIPE, handler); | ||
| 315 | return 1; | ||
| 316 | } else if (!(retval = mysql_query(global_config.server_p, query))) { | ||
| 317 | signal(SIGPIPE, handler); | ||
| 318 | return 0; | ||
| 319 | } | ||
| 320 | |||
| 321 | /* If we ran the query and it returned an error, try to be robust. | ||
| 322 | * (After all, the module thought it had a valid mysql_log connection but the query | ||
| 323 | * could have failed for a number of reasons, so we have to be extra-safe and check.) */ | ||
| 324 | if (global_config.insertdelayed) { | ||
| 325 | real_error_str = MYSQL_ERROR(global_config.server_p); | ||
| 326 | } else { | ||
| 327 | real_error = mysql_errno(global_config.server_p); | ||
| 328 | } | ||
| 329 | |||
| 330 | /* Check to see if the error is "nonexistent table" */ | ||
| 331 | if (global_config.insertdelayed) { | ||
| 332 | retval = (strstr(real_error_str, "Table")) && (strstr(real_error_str,"doesn't exist")); | ||
| 333 | } else { | ||
| 334 | retval = (real_error == ER_NO_SUCH_TABLE); | ||
| 335 | } | ||
| 336 | if (retval) { | ||
| 337 | if (global_config.createtables) { | ||
| 338 | log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: table doesn't exist...creating now"); | ||
| 339 | cls = ap_get_module_config(r->server->module_config, &log_sql_module); | ||
| 340 | if (safe_create_tables(cls, r)) { | ||
| 341 | log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: child attempted but failed to create one or more tables for %s, preserving query", ap_get_server_name(r)); | ||
| 342 | preserve_entry(r, query); | ||
| 343 | retval = mysql_errno(global_config.server_p); | ||
| 344 | } else { | ||
| 345 | log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: tables successfully created - retrying query"); | ||
| 346 | if (mysql_query(global_config.server_p, query)) { | ||
| 347 | log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: giving up, preserving query"); | ||
| 348 | preserve_entry(r, query); | ||
| 349 | retval = mysql_errno(global_config.server_p); | ||
| 350 | } else | ||
| 351 | log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: query successful after table creation"); | ||
| 352 | retval = 0; | ||
| 353 | } | ||
| 354 | } else { | ||
| 355 | log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql, table doesn't exist, creation denied by configuration, preserving query"); | ||
| 356 | preserve_entry(r, query); | ||
| 357 | retval = ER_NO_SUCH_TABLE; | ||
| 358 | } | ||
| 359 | /* Restore SIGPIPE to its original handler function */ | ||
| 360 | signal(SIGPIPE, handler); | ||
| 361 | return retval; | ||
| 362 | } | ||
| 363 | |||
| 364 | /* Handle all other types of errors */ | ||
| 365 | |||
| 366 | cls = ap_get_module_config(r->server->module_config, &log_sql_module); | ||
| 367 | |||
| 368 | /* Something went wrong, so start by trying to restart the db link. */ | ||
| 369 | if (global_config.insertdelayed) { | ||
| 370 | real_error = 2; | ||
| 371 | } else { | ||
| 372 | real_error = mysql_errno(global_config.server_p); | ||
| 373 | } | ||
| 374 | |||
| 375 | log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: first attempt failed, API said: error %d, \"%s\"", real_error, MYSQL_ERROR(global_config.server_p)); | ||
| 376 | mysql_close(global_config.server_p); | ||
| 377 | global_config.server_p = NULL; | ||
| 378 | open_logdb_link(r->server); | ||
| 379 | |||
| 380 | if (global_config.server_p == NULL) { /* still unable to link */ | ||
| 381 | signal(SIGPIPE, handler); | ||
| 382 | log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: reconnect failed, unable to reach database. SQL logging stopped until child regains a db connection."); | ||
| 383 | log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: log entries are being preserved in %s", cls->preserve_file); | ||
| 384 | return 1; | ||
| 385 | } else | ||
| 386 | log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: db reconnect successful"); | ||
| 387 | |||
| 388 | /* First sleep for a tiny amount of time. */ | ||
| 389 | delay.tv_sec = 0; | ||
| 390 | delay.tv_nsec = 250000000; /* max is 999999999 (nine nines) */ | ||
| 391 | ret = nanosleep(&delay, &remainder); | ||
| 392 | if (ret && errno != EINTR) | ||
| 393 | log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: nanosleep unsuccessful"); | ||
| 394 | |||
| 395 | /* Then make our second attempt */ | ||
| 396 | retval = mysql_query(global_config.server_p,query); | ||
| 397 | |||
| 398 | /* If this one also failed, log that and append to our local offline file */ | ||
| 399 | if (retval) { | ||
| 400 | if (global_config.insertdelayed) { | ||
| 401 | real_error = 2; | ||
| 402 | } else { | ||
| 403 | real_error = mysql_errno(global_config.server_p); | ||
| 404 | } | ||
| 405 | |||
| 406 | log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: second attempt failed, API said: error %d, \"%s\" -- preserving", real_error, MYSQL_ERROR(global_config.server_p)); | ||
| 407 | preserve_entry(r, query); | ||
| 408 | retval = real_error; | ||
| 409 | } else | ||
| 410 | log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: second attempt successful"); | ||
| 411 | |||
| 412 | /* Restore SIGPIPE to its original handler function */ | ||
| 413 | signal(SIGPIPE, handler); | ||
| 414 | return retval; | ||
| 415 | } | ||
| 416 | |||
| 417 | /*-----------------------------------------------------* | ||
| 418 | * safe_create_tables: create SQL table set for the * | ||
| 419 | * virtual server represented by cls. * | ||
| 420 | * * | ||
| 421 | * Parms: virtserver structure, request record * | ||
| 422 | * Returns: 0 on no errors * | ||
| 423 | * mysql error code on failure * | ||
| 424 | *-----------------------------------------------------*/ | ||
| 425 | static int safe_create_tables(logsql_state *cls, request_rec *r) | ||
| 426 | { | ||
| 427 | int retval; | ||
| 428 | unsigned int create_results; | ||
| 429 | char *create_access = NULL; | ||
| 430 | char *create_notes = NULL; | ||
| 431 | char *create_hout = NULL; | ||
| 432 | char *create_hin = NULL; | ||
| 433 | char *create_cookies = NULL; | ||
| 434 | |||
| 435 | char *type_suffix = NULL; | ||
| 436 | |||
| 437 | char *createprefix = "create table if not exists `"; | ||
| 438 | char *access_suffix = | ||
| 439 | "` (id char(19),\ | ||
| 440 | agent varchar(255),\ | ||
| 441 | bytes_sent int unsigned,\ | ||
| 442 | child_pid smallint unsigned,\ | ||
| 443 | cookie varchar(255),\ | ||
| 444 | machine_id varchar(25),\ | ||
| 445 | request_file varchar(255),\ | ||
| 446 | referer varchar(255),\ | ||
| 447 | remote_host varchar(50),\ | ||
| 448 | remote_logname varchar(50),\ | ||
| 449 | remote_user varchar(50),\ | ||
| 450 | request_duration smallint unsigned,\ | ||
| 451 | request_line varchar(255),\ | ||
| 452 | request_method varchar(10),\ | ||
| 453 | request_protocol varchar(10),\ | ||
| 454 | request_time char(28),\ | ||
| 455 | request_uri varchar(255),\ | ||
| 456 | request_args varchar(255),\ | ||
| 457 | server_port smallint unsigned,\ | ||
| 458 | ssl_cipher varchar(25),\ | ||
| 459 | ssl_keysize smallint unsigned,\ | ||
| 460 | ssl_maxkeysize smallint unsigned,\ | ||
| 461 | status smallint unsigned,\ | ||
| 462 | time_stamp int unsigned,\ | ||
| 463 | virtual_host varchar(255))"; | ||
| 464 | |||
| 465 | char *notes_suffix = | ||
| 466 | "` (id char(19),\ | ||
| 467 | item varchar(80),\ | ||
| 468 | val varchar(80))"; | ||
| 469 | |||
| 470 | char *headers_suffix = | ||
| 471 | "` (id char(19),\ | ||
| 472 | item varchar(80),\ | ||
| 473 | val varchar(80))"; | ||
| 474 | |||
| 475 | char *cookies_suffix = | ||
| 476 | "` (id char(19),\ | ||
| 477 | item varchar(80),\ | ||
| 478 | val varchar(80))"; | ||
| 479 | if (global_config.tabletype) { | ||
| 480 | type_suffix = apr_pstrcat(r->pool, " TYPE=", global_config.tabletype, NULL); | ||
| 481 | } | ||
| 482 | /* Find memory long enough to hold the whole CREATE string + \0 */ | ||
| 483 | create_access = apr_pstrcat(r->pool, createprefix, cls->transfer_table_name, access_suffix, type_suffix, NULL); | ||
| 484 | create_notes = apr_pstrcat(r->pool, createprefix, cls->notes_table_name, notes_suffix, type_suffix, NULL); | ||
| 485 | create_hout = apr_pstrcat(r->pool, createprefix, cls->hout_table_name, headers_suffix, type_suffix, NULL); | ||
| 486 | create_hin = apr_pstrcat(r->pool, createprefix, cls->hin_table_name, headers_suffix, type_suffix, NULL); | ||
| 487 | create_cookies= apr_pstrcat(r->pool, createprefix, cls->cookie_table_name, cookies_suffix, type_suffix, NULL); | ||
| 488 | |||
| 489 | #ifdef DEBUG | ||
| 490 | log_error(APLOG_MARK,APLOG_DEBUG,r->server,"mod_log_sql: create string: %s", create_access); | ||
| 491 | log_error(APLOG_MARK,APLOG_DEBUG,r->server,"mod_log_sql: create string: %s", create_notes); | ||
| 492 | log_error(APLOG_MARK,APLOG_DEBUG,r->server,"mod_log_sql: create string: %s", create_hout); | ||
| 493 | log_error(APLOG_MARK,APLOG_DEBUG,r->server,"mod_log_sql: create string: %s", create_hin); | ||
| 494 | log_error(APLOG_MARK,APLOG_DEBUG,r->server,"mod_log_sql: create string: %s", create_cookies); | ||
| 495 | #endif | ||
| 496 | |||
| 497 | /* Assume that things worked unless told otherwise */ | ||
| 498 | retval = 0; | ||
| 499 | |||
| 500 | if ((create_results = safe_sql_query(r, create_access))) { | ||
| 501 | log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: failed to create access table"); | ||
| 502 | retval = create_results; | ||
| 503 | } | ||
| 504 | |||
| 505 | if ((create_results = safe_sql_query(r, create_notes))) { | ||
| 506 | log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: failed to create notes table"); | ||
| 507 | retval = create_results; | ||
| 508 | } | ||
| 509 | |||
| 510 | if ((create_results = safe_sql_query(r, create_hin))) { | ||
| 511 | log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: failed to create header_in table"); | ||
| 512 | retval = create_results; | ||
| 513 | } | ||
| 514 | |||
| 515 | if ((create_results = safe_sql_query(r, create_hout))) { | ||
| 516 | log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: failed to create header_out table"); | ||
| 517 | retval = create_results; | ||
| 518 | } | ||
| 519 | |||
| 520 | if ((create_results = safe_sql_query(r, create_cookies))) { | ||
| 521 | log_error(APLOG_MARK,APLOG_ERR,r->server,"mod_log_sql: failed to create cookies table"); | ||
| 522 | retval = create_results; | ||
| 523 | } | ||
| 524 | |||
| 525 | return retval; | ||
| 526 | } | ||
| 527 | |||
| 227 | /* ------------------------------------------------* | 528 | /* ------------------------------------------------* |
| 228 | * Command handlers that are called according * | 529 | * Command handlers that are called according * |
| 229 | * to the directives found at Apache runtime. * | 530 | * to the directives found at Apache runtime. * |
| @@ -266,6 +567,7 @@ static const char *set_global_string_slot(cmd_parms *cmd, | |||
| 266 | *(const char **)((char *)ptr + offset) = apr_pstrdup(cmd->pool,arg); | 567 | *(const char **)((char *)ptr + offset) = apr_pstrdup(cmd->pool,arg); |
| 267 | return NULL; | 568 | return NULL; |
| 268 | } | 569 | } |
| 570 | |||
| 269 | static const char *set_server_string_slot(cmd_parms *cmd, | 571 | static const char *set_server_string_slot(cmd_parms *cmd, |
| 270 | void *struct_ptr, | 572 | void *struct_ptr, |
| 271 | const char *arg) | 573 | const char *arg) |
| @@ -279,27 +581,6 @@ static const char *set_server_string_slot(cmd_parms *cmd, | |||
| 279 | return NULL; | 581 | return NULL; |
| 280 | } | 582 | } |
| 281 | 583 | ||
| 282 | static const char *set_server_file_slot(cmd_parms *cmd, | ||
| 283 | void *struct_ptr, | ||
| 284 | const char *arg) | ||
| 285 | { | ||
| 286 | void *ptr = ap_get_module_config(cmd->server->module_config, | ||
| 287 | &log_sql_module); | ||
| 288 | int offset = (int)(long)cmd->info; | ||
| 289 | const char *path; | ||
| 290 | |||
| 291 | path = ap_server_root_relative(cmd->pool, (char *)arg); | ||
| 292 | |||
| 293 | if (!path) { | ||
| 294 | return apr_pstrcat(cmd->pool, "Invalid file path ", | ||
| 295 | arg, NULL); | ||
| 296 | } | ||
| 297 | |||
| 298 | *(const char **)((char*)ptr + offset) = path; | ||
| 299 | |||
| 300 | return NULL; | ||
| 301 | } | ||
| 302 | |||
| 303 | static const char *set_logformat_slot(cmd_parms *cmd, | 584 | static const char *set_logformat_slot(cmd_parms *cmd, |
| 304 | void *struct_ptr, | 585 | void *struct_ptr, |
| 305 | const char *arg) | 586 | const char *arg) |
| @@ -310,7 +591,7 @@ static const char *set_logformat_slot(cmd_parms *cmd, | |||
| 310 | cfg->transfer_log_format = arg; | 591 | cfg->transfer_log_format = arg; |
| 311 | /* apr_pool_clear(cfg->parsed_pool);*/ | 592 | /* apr_pool_clear(cfg->parsed_pool);*/ |
| 312 | cfg->parsed_log_format = apr_pcalloc(cfg->parsed_pool, | 593 | cfg->parsed_log_format = apr_pcalloc(cfg->parsed_pool, |
| 313 | strlen(arg) * sizeof(logsql_item *)); | 594 | strlen(arg) * sizeof(log_sql_item *)); |
| 314 | return NULL; | 595 | return NULL; |
| 315 | } | 596 | } |
| 316 | 597 | ||
| @@ -326,69 +607,16 @@ static const char *set_server_nmv_string_slot(cmd_parms *parms, | |||
| 326 | return set_server_string_slot(parms,struct_ptr,arg); | 607 | return set_server_string_slot(parms,struct_ptr,arg); |
| 327 | } | 608 | } |
| 328 | 609 | ||
| 329 | /* Set a DB connection parameter */ | 610 | static const char *set_log_sql_info(cmd_parms *cmd, void *dummy, const char *host, const char *user, const char *pwd) |
| 330 | static const char *set_dbparam(cmd_parms *cmd, | ||
| 331 | void *struct_ptr, | ||
| 332 | const char *key, | ||
| 333 | const char *val) | ||
| 334 | { | 611 | { |
| 335 | if (!global_config.db.parms) { | 612 | if (*host != '.') { |
| 336 | global_config.db.parms = apr_table_make(cmd->pool,5); | 613 | global_config.dbhost = apr_pstrdup(cmd->pool,host); |
| 337 | } | 614 | } |
| 338 | apr_table_set(global_config.db.parms,key,val); | 615 | if (*user != '.') { |
| 339 | return NULL; | 616 | global_config.dbuser = apr_pstrdup(cmd->pool,user); |
| 340 | } | 617 | } |
| 341 | 618 | if (*pwd != '.') { | |
| 342 | static const char *set_dbparam_slot(cmd_parms *cmd, | 619 | global_config.dbpwd = apr_pstrdup(cmd->pool,pwd); |
| 343 | void *struct_ptr, | ||
| 344 | const char *arg) | ||
| 345 | { | ||
| 346 | const char *param = (char *)cmd->info; | ||
| 347 | set_dbparam(cmd,NULL,param,arg); | ||
| 348 | return NULL; | ||
| 349 | } | ||
| 350 | |||
| 351 | /* Sets basic connection info */ | ||
| 352 | static const char *set_log_sql_info(cmd_parms *cmd, void *dummy, | ||
| 353 | const char *host, const char *user, const char *pwd) | ||
| 354 | { | ||
| 355 | if (!user) { /* user is null, so only one arg passed */ | ||
| 356 | /* TODO: to more error checking/force all params to be set */ | ||
| 357 | apr_uri_t uri; | ||
| 358 | apr_uri_parse(cmd->pool, host, &uri); | ||
| 359 | if (uri.scheme) { | ||
| 360 | set_dbparam(cmd, NULL, "driver", uri.scheme); | ||
| 361 | } | ||
| 362 | if (uri.hostname) { | ||
| 363 | set_dbparam(cmd, NULL, "hostname", uri.hostname); | ||
| 364 | } | ||
| 365 | if (uri.user) { | ||
| 366 | set_dbparam(cmd, NULL, "username", uri.user); | ||
| 367 | } | ||
| 368 | if (uri.password) { | ||
| 369 | set_dbparam(cmd, NULL, "password", uri.password); | ||
| 370 | } | ||
| 371 | if (uri.port_str) { | ||
| 372 | set_dbparam(cmd, NULL, "port", uri.port_str); | ||
| 373 | } | ||
| 374 | if (uri.path) { | ||
| 375 | /* extract Database name */ | ||
| 376 | char *off = ap_strchr(++uri.path,'/'); | ||
| 377 | if (off) | ||
| 378 | *off='\0'; | ||
| 379 | set_dbparam(cmd, NULL, "database", uri.path); | ||
| 380 | |||
| 381 | } | ||
| 382 | } else { | ||
| 383 | if (*host != '.') { | ||
| 384 | set_dbparam(cmd, NULL, "hostname", host); | ||
| 385 | } | ||
| 386 | if (*user != '.') { | ||
| 387 | set_dbparam(cmd, NULL, "username", user); | ||
| 388 | } | ||
| 389 | if (*pwd != '.') { | ||
| 390 | set_dbparam(cmd, NULL, "password", pwd); | ||
| 391 | } | ||
| 392 | } | 620 | } |
| 393 | return NULL; | 621 | return NULL; |
| 394 | } | 622 | } |
| @@ -401,13 +629,20 @@ static const char *add_server_string_slot(cmd_parms *cmd, | |||
| 401 | void *ptr = ap_get_module_config(cmd->server->module_config, | 629 | void *ptr = ap_get_module_config(cmd->server->module_config, |
| 402 | &log_sql_module); | 630 | &log_sql_module); |
| 403 | int offset = (int)(long)cmd->info; | 631 | int offset = (int)(long)cmd->info; |
| 404 | apr_array_header_t *ary = *(apr_array_header_t **)((char *)ptr + offset); | 632 | apr_array_header_t *ary = *(apr_array_header_t **)(ptr + offset); |
| 405 | addme = apr_array_push(ary); | 633 | addme = apr_array_push(ary); |
| 406 | *addme = apr_pstrdup(ary->pool, arg); | 634 | *addme = apr_pstrdup(ary->pool, arg); |
| 407 | 635 | ||
| 408 | return NULL; | 636 | return NULL; |
| 409 | } | 637 | } |
| 410 | 638 | ||
| 639 | static const char *set_log_sql_tcp_port(cmd_parms *parms, void *dummy, const char *arg) | ||
| 640 | { | ||
| 641 | global_config.tcpport = (unsigned int)atoi(arg); | ||
| 642 | |||
| 643 | return NULL; | ||
| 644 | } | ||
| 645 | |||
| 411 | /*------------------------------------------------------------* | 646 | /*------------------------------------------------------------* |
| 412 | * Apache-specific hooks into the module code * | 647 | * Apache-specific hooks into the module code * |
| 413 | * that are defined in the array 'mysql_lgog_module' (at EOF) * | 648 | * that are defined in the array 'mysql_lgog_module' (at EOF) * |
| @@ -416,47 +651,59 @@ static const char *add_server_string_slot(cmd_parms *cmd, | |||
| 416 | #if defined(WITH_APACHE20) | 651 | #if defined(WITH_APACHE20) |
| 417 | static apr_status_t log_sql_close_link(void *data) | 652 | static apr_status_t log_sql_close_link(void *data) |
| 418 | { | 653 | { |
| 419 | global_config.driver->disconnect(&global_config.db); | 654 | mysql_close(global_config.server_p); |
| 420 | return APR_SUCCESS; | 655 | return APR_SUCCESS; |
| 421 | } | 656 | } |
| 422 | #elif defined(WITH_APACHE13) | 657 | #elif defined(WITH_APACHE13) |
| 423 | static void log_sql_child_exit(server_rec *s, apr_pool_t *p) | 658 | static void log_sql_child_exit(server_rec *s, apr_pool_t *p) |
| 424 | { | 659 | { |
| 425 | global_config.driver->disconnect(&global_config.db); | 660 | mysql_close(global_config.server_p); |
| 426 | } | 661 | } |
| 427 | #endif | 662 | #endif |
| 428 | 663 | ||
| 429 | /* Child Init */ | 664 | /* Child Init */ |
| 430 | #if defined(WITH_APACHE20) | 665 | #if defined(WITH_APACHE20) |
| 431 | static void log_sql_child_init(apr_pool_t *p, server_rec *s) | 666 | static void log_sql_child_init(apr_pool_t *p, server_rec *s) |
| 667 | { | ||
| 668 | apr_pool_cleanup_register(p, NULL, log_sql_close_link, log_sql_close_link); | ||
| 669 | } | ||
| 670 | |||
| 671 | static int log_sql_open(apr_pool_t *pc, apr_pool_t *p, apr_pool_t *pt, server_rec *s) | ||
| 432 | #elif defined(WITH_APACHE13) | 672 | #elif defined(WITH_APACHE13) |
| 433 | static void log_sql_child_init(server_rec *s, apr_pool_t *p) | 673 | static void log_sql_child_init(server_rec *s, apr_pool_t *p) |
| 434 | #endif | 674 | #endif |
| 435 | { | 675 | { |
| 436 | logsql_opendb_ret retval; | 676 | int retval; |
| 437 | # if defined(WITH_APACHE20) | 677 | /* Open a link to the database */ |
| 438 | /* Register cleanup hook to close DDB connection (apache 2 doesn't have child_exit) */ | 678 | retval = open_logdb_link(s); |
| 439 | apr_pool_cleanup_register(p, NULL, log_sql_close_link, log_sql_close_link); | 679 | if (!retval) |
| 440 | # endif | 680 | log_error(APLOG_MARK,APLOG_ERR,s,"mod_log_sql: child spawned but unable to open database link"); |
| 441 | /* Open a link to the database */ | 681 | |
| 442 | retval = log_sql_opendb_link(s); | 682 | #ifdef DEBUG |
| 443 | switch (retval) { | 683 | if ( (retval == 1) || (retval == 2) ) |
| 444 | case LOGSQL_OPENDB_FAIL: | 684 | log_error(APLOG_MARK,APLOG_DEBUG,s,"mod_log_sql: open_logdb_link successful"); |
| 445 | log_error(APLOG_MARK, APLOG_ERR, 0, s, | 685 | if (retval == 3) |
| 446 | "mod_log_sql: child spawned but unable to open database link"); | 686 | log_error(APLOG_MARK,APLOG_DEBUG,s,"mod_log_sql: open_logdb_link said that preservation is forced"); |
| 447 | break; | 687 | #endif |
| 448 | case LOGSQL_OPENDB_SUCCESS: | 688 | #if defined(WITH_APACHE20) |
| 449 | case LOGSQL_OPENDB_ALREADY: | 689 | return OK; |
| 450 | log_error(APLOG_MARK,APLOG_DEBUG,0, s, | 690 | #endif |
| 451 | "mod_log_sql: open_logdb_link successful"); | ||
| 452 | break; | ||
| 453 | case LOGSQL_OPENDB_PRESERVE: | ||
| 454 | log_error(APLOG_MARK,APLOG_DEBUG, 0, s, | ||
| 455 | "mod_log_sql: open_logdb_link said that preservation is forced"); | ||
| 456 | break; | ||
| 457 | } | ||
| 458 | } | 691 | } |
| 692 | /* | ||
| 693 | void *log_sql_initializer(server_rec *main_server, apr_pool_t *p) | ||
| 694 | { | ||
| 695 | server_rec *s; | ||
| 696 | |||
| 697 | logsql_state main_conf = ap_get_module_config(main_server->module_config, &log_sql_module); | ||
| 698 | |||
| 699 | for (server_rec *s = main_server; s; s = s->next) { | ||
| 700 | conf = ap_get_module_config(s->module_config, &log_sql_module); | ||
| 701 | if (conf->transfer_log_format == NULL && s != main_server) { | ||
| 702 | *conf = *main_conf; | ||
| 703 | } | ||
| 459 | 704 | ||
| 705 | } | ||
| 706 | */ | ||
| 460 | /* post_config / module_init */ | 707 | /* post_config / module_init */ |
| 461 | #if defined(WITH_APACHE20) | 708 | #if defined(WITH_APACHE20) |
| 462 | static int log_sql_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) | 709 | static int log_sql_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) |
| @@ -464,6 +711,12 @@ static int log_sql_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptem | |||
| 464 | static void log_sql_module_init(server_rec *s, apr_pool_t *p) | 711 | static void log_sql_module_init(server_rec *s, apr_pool_t *p) |
| 465 | #endif | 712 | #endif |
| 466 | { | 713 | { |
| 714 | /* Initialize Global configuration */ | ||
| 715 | if (!global_config.socketfile) | ||
| 716 | global_config.socketfile = "/tmp/mysql.sock"; | ||
| 717 | if (!global_config.tcpport) | ||
| 718 | global_config.tcpport = 3306; | ||
| 719 | |||
| 467 | /* TODO: Add local_address, remote_address, server_name, connection_status */ | 720 | /* TODO: Add local_address, remote_address, server_name, connection_status */ |
| 468 | /* Register handlers */ | 721 | /* Register handlers */ |
| 469 | log_sql_register_item(s,p,'A', extract_agent, "agent", 1, 1); | 722 | log_sql_register_item(s,p,'A', extract_agent, "agent", 1, 1); |
| @@ -490,136 +743,11 @@ static void log_sql_module_init(server_rec *s, apr_pool_t *p) | |||
| 490 | log_sql_register_item(s,p,'U', extract_request_uri, "request_uri", 1, 1); | 743 | log_sql_register_item(s,p,'U', extract_request_uri, "request_uri", 1, 1); |
| 491 | log_sql_register_item(s,p,'v', extract_virtual_host, "virtual_host", 0, 1); | 744 | log_sql_register_item(s,p,'v', extract_virtual_host, "virtual_host", 0, 1); |
| 492 | 745 | ||
| 493 | if (global_config.announce) { | ||
| 494 | ap_add_version_component(p, PACKAGE_NAME"/"PACKAGE_VERSION); | ||
| 495 | } | ||
| 496 | /* ap_server_root_relative any default preserve file locations */ | ||
| 497 | { | ||
| 498 | server_rec *cur_s; | ||
| 499 | const char *default_p = ap_server_root_relative(p, DEFAULT_PRESERVE_FILE); | ||
| 500 | for (cur_s = s; cur_s != NULL; cur_s= cur_s->next) { | ||
| 501 | logsql_state *cls = ap_get_module_config(cur_s->module_config, | ||
| 502 | &log_sql_module); | ||
| 503 | if (cls->preserve_file == DEFAULT_PRESERVE_FILE) | ||
| 504 | cls->preserve_file = default_p; | ||
| 505 | } | ||
| 506 | } | ||
| 507 | #if defined(WITH_APACHE20) | 746 | #if defined(WITH_APACHE20) |
| 508 | return OK; | 747 | return OK; |
| 509 | #endif | 748 | #endif |
| 510 | } | 749 | } |
| 511 | 750 | ||
| 512 | /* This function handles calling the DB module, handling errors | ||
| 513 | * of missing tables and lost DB connections, and falling back to | ||
| 514 | * preserving the DB query. | ||
| 515 | * | ||
| 516 | * Parms: request record, table type, table name, and the full SQL command | ||
| 517 | */ | ||
| 518 | |||
| 519 | static logsql_query_ret safe_sql_insert(request_rec *r, logsql_tabletype table_type, | ||
| 520 | const char *table_name, const char *query) { | ||
| 521 | |||
| 522 | logsql_query_ret result; | ||
| 523 | logsql_state *cls = ap_get_module_config(r->server->module_config, | ||
| 524 | &log_sql_module); | ||
| 525 | |||
| 526 | if (!global_config.db.connected) { | ||
| 527 | /* preserve query */ | ||
| 528 | return LOGSQL_QUERY_NOLINK; | ||
| 529 | } | ||
| 530 | |||
| 531 | result = global_config.driver->insert(r,&global_config.db,query); | ||
| 532 | |||
| 533 | /* If we ran the query and it returned an error, try to be robust. | ||
| 534 | * (After all, the module thought it had a valid mysql_log connection but the query | ||
| 535 | * could have failed for a number of reasons, so we have to be extra-safe and check.) */ | ||
| 536 | switch (result) { | ||
| 537 | case LOGSQL_QUERY_SUCCESS: | ||
| 538 | return LOGSQL_QUERY_SUCCESS; | ||
| 539 | case LOGSQL_QUERY_NOLINK: | ||
| 540 | return LOGSQL_QUERY_FAIL; | ||
| 541 | /* TODO: What do we do here */ | ||
| 542 | case LOGSQL_QUERY_FAIL: | ||
| 543 | global_config.driver->disconnect(&global_config.db); | ||
| 544 | global_config.db.connected = 0; | ||
| 545 | /* re-open the connection and try again */ | ||
| 546 | if (log_sql_opendb_link(r->server) != LOGSQL_OPENDB_FAIL) { | ||
| 547 | log_error(APLOG_MARK,APLOG_NOTICE,0, r->server,"db reconnect successful"); | ||
| 548 | # if defined(WITH_APACHE20) | ||
| 549 | apr_sleep(apr_time_from_sec(0.25)); /* pause for a quarter second */ | ||
| 550 | # elif defined(WITH_APACHE13) | ||
| 551 | # if defined(WIN32) | ||
| 552 | Sleep((DWORD)0.25); | ||
| 553 | # else | ||
| 554 | { | ||
| 555 | struct timespec delay, remainder; | ||
| 556 | int nanoret; | ||
| 557 | delay.tv_sec = 0; | ||
| 558 | delay.tv_nsec = 250000000; /* pause for a quarter second */ | ||
| 559 | nanoret = nanosleep(&delay, &remainder); | ||
| 560 | if (nanoret && errno != EINTR) { | ||
| 561 | log_error(APLOG_MARK,APLOG_ERR, errno, r->server,"nanosleep unsuccessful"); | ||
| 562 | } | ||
| 563 | } | ||
| 564 | # endif /* win32 */ | ||
| 565 | # endif | ||
| 566 | result = global_config.driver->insert(r,&global_config.db,query); | ||
| 567 | if (result == LOGSQL_QUERY_SUCCESS) { | ||
| 568 | return LOGSQL_QUERY_SUCCESS; | ||
| 569 | } else { | ||
| 570 | log_error(APLOG_MARK,APLOG_ERR,0,r->server,"second attempt failed"); | ||
| 571 | preserve_entry(r, query); | ||
| 572 | return LOGSQL_QUERY_PRESERVED; | ||
| 573 | } | ||
| 574 | } else { | ||
| 575 | log_error(APLOG_MARK,APLOG_ERR,0,r->server, | ||
| 576 | "reconnect failed, unable to reach database. SQL logging stopped until child regains a db connection."); | ||
| 577 | log_error(APLOG_MARK,APLOG_ERR,0,r->server, | ||
| 578 | "log entries are being preserved in %s",cls->preserve_file); | ||
| 579 | preserve_entry(r, query); | ||
| 580 | return LOGSQL_QUERY_PRESERVED; | ||
| 581 | } | ||
| 582 | break; | ||
| 583 | case LOGSQL_QUERY_NOTABLE: | ||
| 584 | if (global_config.createtables) { | ||
| 585 | log_error(APLOG_MARK,APLOG_ERR,0,r->server, | ||
| 586 | "table doesn't exist...creating now"); | ||
| 587 | if ((result = global_config.driver->create_table(r, &global_config.db, table_type, | ||
| 588 | table_name))!=LOGSQL_TABLE_SUCCESS) { | ||
| 589 | log_error(APLOG_MARK,APLOG_ERR,result,r->server, | ||
| 590 | "child attempted but failed to create one or more tables for %s, preserving query", ap_get_server_name(r)); | ||
| 591 | preserve_entry(r, query); | ||
| 592 | return LOGSQL_QUERY_PRESERVED; | ||
| 593 | } else { | ||
| 594 | log_error(APLOG_MARK,APLOG_ERR,result, r->server, | ||
| 595 | "tables successfully created - retrying query"); | ||
| 596 | if ((result = global_config.driver->insert(r,&global_config.db,query))!=LOGSQL_QUERY_SUCCESS) { | ||
| 597 | log_error(APLOG_MARK,APLOG_ERR,result, r->server, | ||
| 598 | "giving up, preserving query"); | ||
| 599 | preserve_entry(r, query); | ||
| 600 | return LOGSQL_QUERY_PRESERVED; | ||
| 601 | } else { | ||
| 602 | log_error(APLOG_MARK,APLOG_NOTICE,0, r->server, | ||
| 603 | "query successful after table creation"); | ||
| 604 | return LOGSQL_QUERY_SUCCESS; | ||
| 605 | } | ||
| 606 | } | ||
| 607 | } else { | ||
| 608 | log_error(APLOG_MARK,APLOG_ERR,0,r->server, | ||
| 609 | "table doesn't exist, creation denied by configuration, preserving query"); | ||
| 610 | preserve_entry(r, query); | ||
| 611 | return LOGSQL_QUERY_PRESERVED; | ||
| 612 | } | ||
| 613 | break; | ||
| 614 | default: | ||
| 615 | log_error(APLOG_MARK,APLOG_ERR,0, r->server, | ||
| 616 | "Invalid return code from mog_log_query"); | ||
| 617 | return LOGSQL_QUERY_FAIL; | ||
| 618 | break; | ||
| 619 | } | ||
| 620 | return LOGSQL_QUERY_FAIL; | ||
| 621 | } | ||
| 622 | |||
| 623 | /* This function gets called to create a per-server configuration | 751 | /* This function gets called to create a per-server configuration |
| 624 | * record. It will always be called for the main server and | 752 | * record. It will always be called for the main server and |
| 625 | * for each virtual server that is established. Each server maintains | 753 | * for each virtual server that is established. Each server maintains |
| @@ -636,7 +764,7 @@ static void *log_sql_make_state(apr_pool_t *p, server_rec *s) | |||
| 636 | cls->transfer_log_format = DEFAULT_TRANSFER_LOG_FMT; | 764 | cls->transfer_log_format = DEFAULT_TRANSFER_LOG_FMT; |
| 637 | apr_pool_create(&cls->parsed_pool, p); | 765 | apr_pool_create(&cls->parsed_pool, p); |
| 638 | cls->parsed_log_format = apr_pcalloc(cls->parsed_pool, | 766 | cls->parsed_log_format = apr_pcalloc(cls->parsed_pool, |
| 639 | strlen(cls->transfer_log_format) * sizeof(logsql_item *)); | 767 | strlen(cls->transfer_log_format) * sizeof(log_sql_item *)); |
| 640 | cls->notes_table_name = DEFAULT_NOTES_TABLE_NAME; | 768 | cls->notes_table_name = DEFAULT_NOTES_TABLE_NAME; |
| 641 | cls->hin_table_name = DEFAULT_HIN_TABLE_NAME; | 769 | cls->hin_table_name = DEFAULT_HIN_TABLE_NAME; |
| 642 | cls->hout_table_name = DEFAULT_HOUT_TABLE_NAME; | 770 | cls->hout_table_name = DEFAULT_HOUT_TABLE_NAME; |
| @@ -654,92 +782,31 @@ static void *log_sql_make_state(apr_pool_t *p, server_rec *s) | |||
| 654 | return (void *) cls; | 782 | return (void *) cls; |
| 655 | } | 783 | } |
| 656 | 784 | ||
| 657 | |||
| 658 | /* Iterates through an array of char* and searches for a matching element | ||
| 659 | * Returns 0 if not found, 1 if found */ | ||
| 660 | static int in_array(apr_array_header_t *ary, const char *elem) | ||
| 661 | { | ||
| 662 | int itr; | ||
| 663 | for (itr = 0; itr < ary->nelts; itr++) { | ||
| 664 | if (!strcmp(elem,((char **)ary->elts)[itr])) { | ||
| 665 | return 1; | ||
| 666 | } | ||
| 667 | } | ||
| 668 | return 0; | ||
| 669 | } | ||
| 670 | |||
| 671 | |||
| 672 | /* Parse through cookie lists and merge based on +/- prefixes */ | ||
| 673 | #define DO_MERGE_ARRAY(parent,child,pool) \ | ||
| 674 | if (apr_is_empty_array(child)) { \ | ||
| 675 | apr_array_cat(child, parent); \ | ||
| 676 | } else { \ | ||
| 677 | apr_array_header_t *addlist, *dellist; \ | ||
| 678 | char **elem, **ptr = (char **)(child->elts); \ | ||
| 679 | int itr, overwrite = 0; \ | ||
| 680 | addlist = apr_array_make(pool,5,sizeof(char *)); \ | ||
| 681 | dellist = apr_array_make(subp,5,sizeof(char *)); \ | ||
| 682 | \ | ||
| 683 | for (itr=0; itr<child->nelts; itr++) { \ | ||
| 684 | if (*ptr[itr] == '+') { \ | ||
| 685 | elem = (char **)apr_array_push(addlist); \ | ||
| 686 | *elem = (ptr[itr]+1); \ | ||
| 687 | } else if (*ptr[itr] == '-') { \ | ||
| 688 | elem = (char **)apr_array_push(dellist); \ | ||
| 689 | *elem = (ptr[itr]+1); \ | ||
| 690 | } else { \ | ||
| 691 | overwrite = 1; \ | ||
| 692 | elem = (char **)apr_array_push(addlist); \ | ||
| 693 | *elem = ptr[itr]; \ | ||
| 694 | } \ | ||
| 695 | } \ | ||
| 696 | child = apr_array_make(p,1,sizeof(char *)); \ | ||
| 697 | ptr = (char **)(parent->elts); \ | ||
| 698 | if (overwrite==0) { \ | ||
| 699 | /* if we are not overwriting the existing then prepare for merge */ \ | ||
| 700 | for (itr=0; itr<parent->nelts; itr++) { \ | ||
| 701 | if (!in_array(addlist, ptr[itr]) && !in_array(dellist,ptr[itr])) { \ | ||
| 702 | elem = apr_array_push(child); \ | ||
| 703 | *elem = apr_pstrdup(p, ptr[itr]); \ | ||
| 704 | } \ | ||
| 705 | } \ | ||
| 706 | } \ | ||
| 707 | apr_array_cat(child, addlist); \ | ||
| 708 | } | ||
| 709 | |||
| 710 | static void *log_sql_merge_state(apr_pool_t *p, void *basev, void *addv) | 785 | static void *log_sql_merge_state(apr_pool_t *p, void *basev, void *addv) |
| 711 | { | 786 | { |
| 712 | /* Fetch the two states to merge */ | 787 | /* Fetch the two states to merge */ |
| 713 | logsql_state *parent = (logsql_state *) basev; | 788 | logsql_state *parent = (logsql_state *) basev; |
| 714 | logsql_state *child = (logsql_state *) addv; | 789 | logsql_state *child = (logsql_state *) addv; |
| 715 | 790 | ||
| 716 | apr_pool_t *subp; | ||
| 717 | |||
| 718 | apr_pool_create(&subp,p); | ||
| 719 | |||
| 720 | /* Child can override these, otherwise they default to parent's choice. | 791 | /* Child can override these, otherwise they default to parent's choice. |
| 721 | * If the parent didn't set them, create reasonable defaults for the | 792 | * If the parent didn't set them, create reasonable defaults for the |
| 722 | * ones that should have such default settings. Leave the others null. */ | 793 | * ones that should have such default settings. Leave the others null. */ |
| 723 | 794 | ||
| 795 | child->transfer_table_name = child->transfer_table_name ? | ||
| 796 | child->transfer_table_name : parent->transfer_table_name; | ||
| 724 | /* No default for transfer_table_name because we want its absence | 797 | /* No default for transfer_table_name because we want its absence |
| 725 | * to disable logging. */ | 798 | * to disable logging. */ |
| 726 | if (!child->transfer_table_name) { | ||
| 727 | child->transfer_table_name = parent->transfer_table_name; | ||
| 728 | } | ||
| 729 | 799 | ||
| 730 | if (child->transfer_log_format == DEFAULT_TRANSFER_LOG_FMT) { | 800 | if (child->transfer_log_format == DEFAULT_TRANSFER_LOG_FMT) { |
| 731 | child->transfer_log_format = parent->transfer_log_format; | 801 | child->transfer_log_format = parent->transfer_log_format; |
| 732 | /*apr_pool_clear(child->parsed_pool);*/ | 802 | /*apr_pool_clear(child->parsed_pool);*/ |
| 733 | child->parsed_log_format = apr_pcalloc(child->parsed_pool, | 803 | child->parsed_log_format = apr_pcalloc(child->parsed_pool, |
| 734 | strlen(child->transfer_log_format) * sizeof(logsql_item *)); | 804 | strlen(child->transfer_log_format) * sizeof(log_sql_item *)); |
| 735 | } | 805 | } |
| 736 | 806 | ||
| 737 | if (child->preserve_file == DEFAULT_PRESERVE_FILE) | 807 | if (child->preserve_file == DEFAULT_PRESERVE_FILE) |
| 738 | child->preserve_file = parent->preserve_file; | 808 | child->preserve_file = parent->preserve_file; |
| 739 | /* server_root_relative the preserve file location */ | 809 | |
| 740 | if (child->preserve_file == DEFAULT_PRESERVE_FILE) | ||
| 741 | child->preserve_file = ap_server_root_relative(p, DEFAULT_PRESERVE_FILE); | ||
| 742 | |||
| 743 | if (child->notes_table_name == DEFAULT_NOTES_TABLE_NAME) | 810 | if (child->notes_table_name == DEFAULT_NOTES_TABLE_NAME) |
| 744 | child->notes_table_name = parent->notes_table_name; | 811 | child->notes_table_name = parent->notes_table_name; |
| 745 | 812 | ||
| @@ -752,20 +819,30 @@ static void *log_sql_merge_state(apr_pool_t *p, void *basev, void *addv) | |||
| 752 | if (child->cookie_table_name == DEFAULT_COOKIE_TABLE_NAME) | 819 | if (child->cookie_table_name == DEFAULT_COOKIE_TABLE_NAME) |
| 753 | child->cookie_table_name = parent->cookie_table_name; | 820 | child->cookie_table_name = parent->cookie_table_name; |
| 754 | 821 | ||
| 755 | DO_MERGE_ARRAY(parent->transfer_ignore_list, child->transfer_ignore_list, subp); | 822 | if (apr_is_empty_array(child->transfer_ignore_list)) |
| 756 | DO_MERGE_ARRAY(parent->transfer_accept_list, child->transfer_accept_list, subp); | 823 | apr_array_cat(child->transfer_ignore_list, parent->transfer_ignore_list); |
| 757 | DO_MERGE_ARRAY(parent->remhost_ignore_list, child->remhost_ignore_list, subp); | 824 | |
| 758 | DO_MERGE_ARRAY(parent->notes_list, child->notes_list, subp); | 825 | if (apr_is_empty_array(child->transfer_accept_list)) |
| 759 | DO_MERGE_ARRAY(parent->hin_list, child->hin_list, subp); | 826 | apr_array_cat(child->transfer_accept_list, parent->transfer_accept_list); |
| 760 | DO_MERGE_ARRAY(parent->hout_list, child->hout_list, subp); | 827 | |
| 761 | DO_MERGE_ARRAY(parent->cookie_list,child->cookie_list, subp); | 828 | if (apr_is_empty_array(child->remhost_ignore_list)) |
| 829 | apr_array_cat(child->remhost_ignore_list, parent->remhost_ignore_list); | ||
| 762 | 830 | ||
| 763 | apr_pool_destroy(subp); | 831 | if (apr_is_empty_array(child->notes_list)) |
| 832 | apr_array_cat(child->notes_list, parent->notes_list); | ||
| 833 | |||
| 834 | if (apr_is_empty_array(child->hin_list)) | ||
| 835 | apr_array_cat(child->hin_list, parent->hin_list); | ||
| 836 | |||
| 837 | if (apr_is_empty_array(child->hout_list)) | ||
| 838 | apr_array_cat(child->hout_list, parent->hout_list); | ||
| 839 | |||
| 840 | if (apr_is_empty_array(child->cookie_list)) | ||
| 841 | apr_array_cat(child->cookie_list, parent->cookie_list); | ||
| 764 | 842 | ||
| 765 | if (!child->cookie_name) | 843 | if (!child->cookie_name) |
| 766 | child->cookie_name = parent->cookie_name; | 844 | child->cookie_name = parent->cookie_name; |
| 767 | 845 | ||
| 768 | |||
| 769 | return (void*) child; | 846 | return (void*) child; |
| 770 | } | 847 | } |
| 771 | 848 | ||
| @@ -850,7 +927,7 @@ static int log_sql_transaction(request_rec *orig) | |||
| 850 | if ((r->uri) && (cls->transfer_accept_list->nelts)) { | 927 | if ((r->uri) && (cls->transfer_accept_list->nelts)) { |
| 851 | proceed = 0; | 928 | proceed = 0; |
| 852 | for (ptrptr = (char **) cls->transfer_accept_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->transfer_accept_list->elt_size)) | 929 | for (ptrptr = (char **) cls->transfer_accept_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->transfer_accept_list->elt_size)) |
| 853 | if (ap_strstr(r->uri, *ptrptr)) { | 930 | if (strstr(r->uri, *ptrptr)) { |
| 854 | proceed = 1; | 931 | proceed = 1; |
| 855 | break; | 932 | break; |
| 856 | } | 933 | } |
| @@ -863,7 +940,7 @@ static int log_sql_transaction(request_rec *orig) | |||
| 863 | ptrptr2 = (char **) (cls->transfer_ignore_list->elts + (cls->transfer_ignore_list->nelts * cls->transfer_ignore_list->elt_size)); | 940 | ptrptr2 = (char **) (cls->transfer_ignore_list->elts + (cls->transfer_ignore_list->nelts * cls->transfer_ignore_list->elt_size)); |
| 864 | if (r->uri) { | 941 | if (r->uri) { |
| 865 | for (ptrptr = (char **) cls->transfer_ignore_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->transfer_ignore_list->elt_size)) | 942 | for (ptrptr = (char **) cls->transfer_ignore_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->transfer_ignore_list->elt_size)) |
| 866 | if (ap_strstr(r->uri, *ptrptr)) { | 943 | if (strstr(r->uri, *ptrptr)) { |
| 867 | return OK; | 944 | return OK; |
| 868 | } | 945 | } |
| 869 | } | 946 | } |
| @@ -874,7 +951,7 @@ static int log_sql_transaction(request_rec *orig) | |||
| 874 | thehost = ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME, NULL); | 951 | thehost = ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME, NULL); |
| 875 | if (thehost) { | 952 | if (thehost) { |
| 876 | for (ptrptr = (char **) cls->remhost_ignore_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->remhost_ignore_list->elt_size)) | 953 | for (ptrptr = (char **) cls->remhost_ignore_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->remhost_ignore_list->elt_size)) |
| 877 | if (ap_strstr(thehost, *ptrptr)) { | 954 | if (strstr(thehost, *ptrptr)) { |
| 878 | return OK; | 955 | return OK; |
| 879 | } | 956 | } |
| 880 | } | 957 | } |
| @@ -884,9 +961,9 @@ static int log_sql_transaction(request_rec *orig) | |||
| 884 | * what the user has configured. */ | 961 | * what the user has configured. */ |
| 885 | length = strlen(cls->transfer_log_format); | 962 | length = strlen(cls->transfer_log_format); |
| 886 | for (i = 0; i<length; i++) { | 963 | for (i = 0; i<length; i++) { |
| 887 | logsql_item *item = cls->parsed_log_format[i]; | 964 | log_sql_item *item = cls->parsed_log_format[i]; |
| 888 | if (item==NULL) { | 965 | if (item==NULL) { |
| 889 | log_error(APLOG_MARK, APLOG_ERR, 0, orig->server, | 966 | log_error(APLOG_MARK, APLOG_ERR, orig->server, |
| 890 | "Log Format '%c' unknown",cls->transfer_log_format[i]); | 967 | "Log Format '%c' unknown",cls->transfer_log_format[i]); |
| 891 | continue; | 968 | continue; |
| 892 | } | 969 | } |
| @@ -909,7 +986,7 @@ static int log_sql_transaction(request_rec *orig) | |||
| 909 | item->sql_field_name, NULL); | 986 | item->sql_field_name, NULL); |
| 910 | values = apr_pstrcat(r->pool, values, (i ? "," : ""), | 987 | values = apr_pstrcat(r->pool, values, (i ? "," : ""), |
| 911 | (item->string_contents ? "'" : ""), | 988 | (item->string_contents ? "'" : ""), |
| 912 | global_config.driver->escape(formatted_item, r->pool,&global_config.db), | 989 | escape_query(formatted_item, r->pool), |
| 913 | (item->string_contents ? "'" : ""), NULL); | 990 | (item->string_contents ? "'" : ""), NULL); |
| 914 | } | 991 | } |
| 915 | 992 | ||
| @@ -926,9 +1003,9 @@ static int log_sql_transaction(request_rec *orig) | |||
| 926 | "('", | 1003 | "('", |
| 927 | unique_id, | 1004 | unique_id, |
| 928 | "','", | 1005 | "','", |
| 929 | global_config.driver->escape(*ptrptr, r->pool,&global_config.db), | 1006 | escape_query(*ptrptr, r->pool), |
| 930 | "','", | 1007 | "','", |
| 931 | global_config.driver->escape(theitem, r->pool,&global_config.db), | 1008 | escape_query(theitem, r->pool), |
| 932 | "')", | 1009 | "')", |
| 933 | NULL); | 1010 | NULL); |
| 934 | i++; | 1011 | i++; |
| @@ -936,9 +1013,11 @@ static int log_sql_transaction(request_rec *orig) | |||
| 936 | } | 1013 | } |
| 937 | if ( itemsets != "" ) { | 1014 | if ( itemsets != "" ) { |
| 938 | note_query = apr_psprintf(r->pool, "insert %s into `%s` (id, item, val) values %s", | 1015 | note_query = apr_psprintf(r->pool, "insert %s into `%s` (id, item, val) values %s", |
| 939 | /*global_config.insertdelayed?"delayed":*/"", notes_tablename, itemsets); | 1016 | global_config.insertdelayed?"delayed":"", notes_tablename, itemsets); |
| 940 | 1017 | ||
| 941 | log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: note string: %s", note_query); | 1018 | #ifdef DEBUG |
| 1019 | log_error(APLOG_MARK,APLOG_DEBUG,orig->server,"mod_log_sql: note string: %s", note_query); | ||
| 1020 | #endif | ||
| 942 | } | 1021 | } |
| 943 | 1022 | ||
| 944 | /* Work through the list of headers-out defined by LogSQLWhichHeadersOut*/ | 1023 | /* Work through the list of headers-out defined by LogSQLWhichHeadersOut*/ |
| @@ -954,9 +1033,9 @@ static int log_sql_transaction(request_rec *orig) | |||
| 954 | "('", | 1033 | "('", |
| 955 | unique_id, | 1034 | unique_id, |
| 956 | "','", | 1035 | "','", |
| 957 | global_config.driver->escape(*ptrptr, r->pool,&global_config.db), | 1036 | escape_query(*ptrptr, r->pool), |
| 958 | "','", | 1037 | "','", |
| 959 | global_config.driver->escape(theitem, r->pool,&global_config.db), | 1038 | escape_query(theitem, r->pool), |
| 960 | "')", | 1039 | "')", |
| 961 | NULL); | 1040 | NULL); |
| 962 | i++; | 1041 | i++; |
| @@ -964,9 +1043,11 @@ static int log_sql_transaction(request_rec *orig) | |||
| 964 | } | 1043 | } |
| 965 | if ( itemsets != "" ) { | 1044 | if ( itemsets != "" ) { |
| 966 | hout_query = apr_psprintf(r->pool, "insert %s into `%s` (id, item, val) values %s", | 1045 | hout_query = apr_psprintf(r->pool, "insert %s into `%s` (id, item, val) values %s", |
| 967 | /*global_config.insertdelayed?"delayed":*/"", hout_tablename, itemsets); | 1046 | global_config.insertdelayed?"delayed":"", hout_tablename, itemsets); |
| 968 | 1047 | ||
| 969 | log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: header_out string: %s", hout_query); | 1048 | #ifdef DEBUG |
| 1049 | log_error(APLOG_MARK,APLOG_DEBUG,orig->server,"mod_log_sql: header_out string: %s", hout_query); | ||
| 1050 | #endif | ||
| 970 | } | 1051 | } |
| 971 | 1052 | ||
| 972 | 1053 | ||
| @@ -983,9 +1064,9 @@ static int log_sql_transaction(request_rec *orig) | |||
| 983 | "('", | 1064 | "('", |
| 984 | unique_id, | 1065 | unique_id, |
| 985 | "','", | 1066 | "','", |
| 986 | global_config.driver->escape(*ptrptr, r->pool,&global_config.db), | 1067 | escape_query(*ptrptr, r->pool), |
| 987 | "','", | 1068 | "','", |
| 988 | global_config.driver->escape(theitem, r->pool,&global_config.db), | 1069 | escape_query(theitem, r->pool), |
| 989 | "')", | 1070 | "')", |
| 990 | NULL); | 1071 | NULL); |
| 991 | i++; | 1072 | i++; |
| @@ -993,9 +1074,11 @@ static int log_sql_transaction(request_rec *orig) | |||
| 993 | } | 1074 | } |
| 994 | if ( itemsets != "" ) { | 1075 | if ( itemsets != "" ) { |
| 995 | hin_query = apr_psprintf(r->pool, "insert %s into `%s` (id, item, val) values %s", | 1076 | hin_query = apr_psprintf(r->pool, "insert %s into `%s` (id, item, val) values %s", |
| 996 | /*global_config.insertdelayed?"delayed":*/"", hin_tablename, itemsets); | 1077 | global_config.insertdelayed?"delayed":"", hin_tablename, itemsets); |
| 997 | 1078 | ||
| 998 | log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: header_in string: %s", hin_query); | 1079 | #ifdef DEBUG |
| 1080 | log_error(APLOG_MARK,APLOG_DEBUG,orig->server,"mod_log_sql: header_in string: %s", hin_query); | ||
| 1081 | #endif | ||
| 999 | } | 1082 | } |
| 1000 | 1083 | ||
| 1001 | 1084 | ||
| @@ -1012,9 +1095,9 @@ static int log_sql_transaction(request_rec *orig) | |||
| 1012 | "('", | 1095 | "('", |
| 1013 | unique_id, | 1096 | unique_id, |
| 1014 | "','", | 1097 | "','", |
| 1015 | global_config.driver->escape(*ptrptr, r->pool,&global_config.db), | 1098 | escape_query(*ptrptr, r->pool), |
| 1016 | "','", | 1099 | "','", |
| 1017 | global_config.driver->escape(theitem, r->pool,&global_config.db), | 1100 | escape_query(theitem, r->pool), |
| 1018 | "')", | 1101 | "')", |
| 1019 | NULL); | 1102 | NULL); |
| 1020 | i++; | 1103 | i++; |
| @@ -1023,23 +1106,29 @@ static int log_sql_transaction(request_rec *orig) | |||
| 1023 | } | 1106 | } |
| 1024 | if ( itemsets != "" ) { | 1107 | if ( itemsets != "" ) { |
| 1025 | cookie_query = apr_psprintf(r->pool, "insert %s into `%s` (id, item, val) values %s", | 1108 | cookie_query = apr_psprintf(r->pool, "insert %s into `%s` (id, item, val) values %s", |
| 1026 | /*global_config.insertdelayed?"delayed":*/"", cookie_tablename, itemsets); | 1109 | global_config.insertdelayed?"delayed":"", cookie_tablename, itemsets); |
| 1027 | 1110 | ||
| 1028 | log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: cookie string: %s", cookie_query); | 1111 | #ifdef DEBUG |
| 1112 | log_error(APLOG_MARK,APLOG_DEBUG,orig->server,"mod_log_sql: cookie string: %s", cookie_query); | ||
| 1113 | #endif | ||
| 1029 | } | 1114 | } |
| 1030 | 1115 | ||
| 1031 | 1116 | ||
| 1032 | /* Set up the actual INSERT statement */ | 1117 | /* Set up the actual INSERT statement */ |
| 1033 | access_query = apr_psprintf(r->pool, "insert %s into `%s` (%s) values (%s)", | 1118 | access_query = apr_psprintf(r->pool, "insert %s into `%s` (%s) values (%s)", |
| 1034 | /*global_config.insertdelayed?"delayed":*/"", transfer_tablename, fields, values); | 1119 | global_config.insertdelayed?"delayed":"", transfer_tablename, fields, values); |
| 1035 | 1120 | ||
| 1036 | log_error(APLOG_MARK,APLOG_DEBUG,0, r->server,"mod_log_sql: access string: %s", access_query); | 1121 | #ifdef DEBUG |
| 1122 | log_error(APLOG_MARK,APLOG_DEBUG,r->server,"mod_log_sql: access string: %s", access_query); | ||
| 1123 | #endif | ||
| 1037 | 1124 | ||
| 1038 | /* If the person activated force-preserve, go ahead and push all the entries | 1125 | /* If the person activated force-preserve, go ahead and push all the entries |
| 1039 | * into the preserve file, then return. | 1126 | * into the preserve file, then return. |
| 1040 | */ | 1127 | */ |
| 1041 | if (global_config.forcepreserve) { | 1128 | if (global_config.forcepreserve) { |
| 1042 | log_error(APLOG_MARK,APLOG_DEBUG,0, orig->server,"mod_log_sql: preservation forced"); | 1129 | #ifdef DEBUG |
| 1130 | log_error(APLOG_MARK,APLOG_DEBUG,orig->server,"mod_log_sql: preservation forced"); | ||
| 1131 | #endif | ||
| 1043 | preserve_entry(orig, access_query); | 1132 | preserve_entry(orig, access_query); |
| 1044 | if ( note_query != NULL ) | 1133 | if ( note_query != NULL ) |
| 1045 | preserve_entry(orig, note_query); | 1134 | preserve_entry(orig, note_query); |
| @@ -1053,12 +1142,12 @@ static int log_sql_transaction(request_rec *orig) | |||
| 1053 | } | 1142 | } |
| 1054 | 1143 | ||
| 1055 | /* How's our mysql link integrity? */ | 1144 | /* How's our mysql link integrity? */ |
| 1056 | if (!global_config.db.connected) { | 1145 | if (global_config.server_p == NULL) { |
| 1057 | 1146 | ||
| 1058 | /* Make a try to establish the link */ | 1147 | /* Make a try to establish the link */ |
| 1059 | log_sql_opendb_link(r->server); | 1148 | open_logdb_link(r->server); |
| 1060 | 1149 | ||
| 1061 | if (!global_config.db.connected) { | 1150 | if (global_config.server_p == NULL) { |
| 1062 | /* Unable to re-establish a DB link, so assume that it's really | 1151 | /* Unable to re-establish a DB link, so assume that it's really |
| 1063 | * gone and send the entry to the preserve file instead. | 1152 | * gone and send the entry to the preserve file instead. |
| 1064 | * This short-circuits safe_sql_query() during a db outage and therefore | 1153 | * This short-circuits safe_sql_query() during a db outage and therefore |
| @@ -1077,7 +1166,7 @@ static int log_sql_transaction(request_rec *orig) | |||
| 1077 | return OK; | 1166 | return OK; |
| 1078 | } else { | 1167 | } else { |
| 1079 | /* Whew, we got the DB link back */ | 1168 | /* Whew, we got the DB link back */ |
| 1080 | log_error(APLOG_MARK,APLOG_NOTICE,0, orig->server,"mod_log_sql: child established database connection"); | 1169 | log_error(APLOG_MARK,APLOG_NOTICE,orig->server,"mod_log_sql: child established database connection"); |
| 1081 | } | 1170 | } |
| 1082 | } | 1171 | } |
| 1083 | 1172 | ||
| @@ -1086,20 +1175,20 @@ static int log_sql_transaction(request_rec *orig) | |||
| 1086 | /* ---> i.e. we have a good MySQL connection. <--- */ | 1175 | /* ---> i.e. we have a good MySQL connection. <--- */ |
| 1087 | 1176 | ||
| 1088 | /* Make the access-table insert */ | 1177 | /* Make the access-table insert */ |
| 1089 | safe_sql_insert(orig,LOGSQL_TABLE_ACCESS,transfer_tablename,access_query); | 1178 | safe_sql_query(orig, access_query); |
| 1090 | 1179 | ||
| 1091 | /* Log the optional notes, headers, etc. */ | 1180 | /* Log the optional notes, headers, etc. */ |
| 1092 | if (note_query) | 1181 | if (note_query) |
| 1093 | safe_sql_insert(orig, LOGSQL_TABLE_NOTES,notes_tablename,note_query); | 1182 | safe_sql_query(orig, note_query); |
| 1094 | 1183 | ||
| 1095 | if (hout_query) | 1184 | if (hout_query) |
| 1096 | safe_sql_insert(orig, LOGSQL_TABLE_HEADERSOUT,hout_tablename,hout_query); | 1185 | safe_sql_query(orig, hout_query); |
| 1097 | 1186 | ||
| 1098 | if (hin_query) | 1187 | if (hin_query) |
| 1099 | safe_sql_insert(orig, LOGSQL_TABLE_HEADERSIN,hin_tablename,hin_query); | 1188 | safe_sql_query(orig, hin_query); |
| 1100 | 1189 | ||
| 1101 | if (cookie_query) | 1190 | if (cookie_query) |
| 1102 | safe_sql_insert(orig, LOGSQL_TABLE_COOKIES,cookie_tablename,cookie_query); | 1191 | safe_sql_query(orig, cookie_query); |
| 1103 | 1192 | ||
| 1104 | return OK; | 1193 | return OK; |
| 1105 | } | 1194 | } |
| @@ -1110,38 +1199,6 @@ static int log_sql_transaction(request_rec *orig) | |||
| 1110 | * Structure: command, function called, NULL, where available, how many arguments, verbose description | 1199 | * Structure: command, function called, NULL, where available, how many arguments, verbose description |
| 1111 | */ | 1200 | */ |
| 1112 | static const command_rec log_sql_cmds[] = { | 1201 | static const command_rec log_sql_cmds[] = { |
| 1113 | AP_INIT_FLAG("LogSQLAnnounce", set_global_flag_slot, | ||
| 1114 | (void *)APR_OFFSETOF(global_config_t, announce), RSRC_CONF, | ||
| 1115 | "Whether to announce that mod_log_sql is loaded in the server header") | ||
| 1116 | , | ||
| 1117 | /* DB connection parameters */ | ||
| 1118 | AP_INIT_TAKE13("LogSQLLoginInfo", set_log_sql_info, NULL, RSRC_CONF, | ||
| 1119 | "The database connection URI in the form "driver://user:password@hostname:port/database"") | ||
| 1120 | , | ||
| 1121 | AP_INIT_TAKE2("LogSQLDBParam", set_dbparam, NULL, RSRC_CONF, | ||
| 1122 | "First argument is the DB parameter, second is the value to assign") | ||
| 1123 | , | ||
| 1124 | AP_INIT_FLAG("LogSQLForcePreserve", set_global_flag_slot, | ||
| 1125 | (void *)APR_OFFSETOF(global_config_t, forcepreserve), RSRC_CONF, | ||
| 1126 | "Forces logging to preserve file and bypasses database") | ||
| 1127 | , | ||
| 1128 | AP_INIT_FLAG("LogSQLDisablePreserve", set_global_flag_slot, | ||
| 1129 | (void *)APR_OFFSETOF(global_config_t, disablepreserve), RSRC_CONF, | ||
| 1130 | "Completely disables use of the preserve file") | ||
| 1131 | , | ||
| 1132 | AP_INIT_TAKE1("LogSQLPreserveFile", set_server_file_slot, | ||
| 1133 | (void *)APR_OFFSETOF(logsql_state,preserve_file), RSRC_CONF, | ||
| 1134 | "Name of the file to use for data preservation during database downtime") | ||
| 1135 | , | ||
| 1136 | AP_INIT_FLAG("LogSQLCreateTables", set_global_nmv_flag_slot, | ||
| 1137 | (void *)APR_OFFSETOF(global_config_t, createtables), RSRC_CONF, | ||
| 1138 | "Turn on module's capability to create its SQL tables on the fly") | ||
| 1139 | , | ||
| 1140 | /* Table names */ | ||
| 1141 | AP_INIT_FLAG("LogSQLMassVirtualHosting", set_global_flag_slot, | ||
| 1142 | (void *)APR_OFFSETOF(global_config_t, massvirtual), RSRC_CONF, | ||
| 1143 | "Activates option(s) useful for ISPs performing mass virutal hosting") | ||
| 1144 | , | ||
| 1145 | AP_INIT_TAKE1("LogSQLTransferLogTable", set_server_nmv_string_slot, | 1202 | AP_INIT_TAKE1("LogSQLTransferLogTable", set_server_nmv_string_slot, |
| 1146 | (void *)APR_OFFSETOF(logsql_state, transfer_table_name), RSRC_CONF, | 1203 | (void *)APR_OFFSETOF(logsql_state, transfer_table_name), RSRC_CONF, |
| 1147 | "The database table that holds the transfer log") | 1204 | "The database table that holds the transfer log") |
| @@ -1162,17 +1219,14 @@ static const command_rec log_sql_cmds[] = { | |||
| 1162 | (void *)APR_OFFSETOF(logsql_state, cookie_table_name), RSRC_CONF, | 1219 | (void *)APR_OFFSETOF(logsql_state, cookie_table_name), RSRC_CONF, |
| 1163 | "The database table that holds the cookie info") | 1220 | "The database table that holds the cookie info") |
| 1164 | , | 1221 | , |
| 1165 | /* Log format */ | ||
| 1166 | AP_INIT_TAKE1("LogSQLTransferLogFormat", set_logformat_slot, | 1222 | AP_INIT_TAKE1("LogSQLTransferLogFormat", set_logformat_slot, |
| 1167 | NULL, RSRC_CONF, | 1223 | NULL, RSRC_CONF, |
| 1168 | "Instruct the module what information to log to the database transfer log") | 1224 | "Instruct the module what information to log to the database transfer log") |
| 1169 | , | 1225 | , |
| 1170 | /* Machine ID */ | ||
| 1171 | AP_INIT_TAKE1("LogSQLMachineID", set_global_string_slot, | 1226 | AP_INIT_TAKE1("LogSQLMachineID", set_global_string_slot, |
| 1172 | (void *)APR_OFFSETOF(global_config_t, machid), RSRC_CONF, | 1227 | (void *)APR_OFFSETOF(global_config_t, machid), RSRC_CONF, |
| 1173 | "Machine ID that the module will log, useful in web clusters to differentiate machines") | 1228 | "Machine ID that the module will log, useful in web clusters to differentiate machines") |
| 1174 | , | 1229 | , |
| 1175 | /* Limits on logging */ | ||
| 1176 | AP_INIT_ITERATE("LogSQLRequestAccept", add_server_string_slot, | 1230 | AP_INIT_ITERATE("LogSQLRequestAccept", add_server_string_slot, |
| 1177 | (void *)APR_OFFSETOF(logsql_state, transfer_accept_list), RSRC_CONF, | 1231 | (void *)APR_OFFSETOF(logsql_state, transfer_accept_list), RSRC_CONF, |
| 1178 | "List of URIs to accept for logging. Accesses that don't match will not be logged") | 1232 | "List of URIs to accept for logging. Accesses that don't match will not be logged") |
| @@ -1185,11 +1239,48 @@ static const command_rec log_sql_cmds[] = { | |||
| 1185 | (void *)APR_OFFSETOF(logsql_state, remhost_ignore_list), RSRC_CONF, | 1239 | (void *)APR_OFFSETOF(logsql_state, remhost_ignore_list), RSRC_CONF, |
| 1186 | "List of remote hosts to ignore. Accesses that match will not be logged to database") | 1240 | "List of remote hosts to ignore. Accesses that match will not be logged to database") |
| 1187 | , | 1241 | , |
| 1188 | /* Special loggin table configuration */ | 1242 | AP_INIT_TAKE1("LogSQLDatabase", set_global_string_slot, |
| 1243 | (void *)APR_OFFSETOF(global_config_t, dbname), RSRC_CONF, | ||
| 1244 | "The name of the database database for logging") | ||
| 1245 | , | ||
| 1189 | AP_INIT_TAKE1("LogSQLWhichCookie", set_server_string_slot, | 1246 | AP_INIT_TAKE1("LogSQLWhichCookie", set_server_string_slot, |
| 1190 | (void *)APR_OFFSETOF(logsql_state, cookie_name), RSRC_CONF, | 1247 | (void *)APR_OFFSETOF(logsql_state, cookie_name), RSRC_CONF, |
| 1191 | "The single cookie that you want logged in the access_log when using the 'c' config directive") | 1248 | "The single cookie that you want logged in the access_log when using the 'c' config directive") |
| 1192 | , | 1249 | , |
| 1250 | AP_INIT_TAKE3("LogSQLLoginInfo", set_log_sql_info, NULL, RSRC_CONF, | ||
| 1251 | "The database host, user-id and password for logging") | ||
| 1252 | , | ||
| 1253 | AP_INIT_FLAG("LogSQLCreateTables", set_global_nmv_flag_slot, | ||
| 1254 | (void *)APR_OFFSETOF(global_config_t, createtables), RSRC_CONF, | ||
| 1255 | "Turn on module's capability to create its SQL tables on the fly") | ||
| 1256 | , | ||
| 1257 | AP_INIT_FLAG("LogSQLMassVirtualHosting", set_global_flag_slot, | ||
| 1258 | (void *)APR_OFFSETOF(global_config_t, massvirtual), RSRC_CONF, | ||
| 1259 | "Activates option(s) useful for ISPs performing mass virutal hosting") | ||
| 1260 | , | ||
| 1261 | AP_INIT_FLAG("LogSQLDelayedInserts", set_global_flag_slot, | ||
| 1262 | (void *)APR_OFFSETOF(global_config_t, insertdelayed), RSRC_CONF, | ||
| 1263 | "Whether to use delayed inserts") | ||
| 1264 | , | ||
| 1265 | AP_INIT_FLAG("LogSQLForcePreserve", set_global_flag_slot, | ||
| 1266 | (void *)APR_OFFSETOF(global_config_t, forcepreserve), RSRC_CONF, | ||
| 1267 | "Forces logging to preserve file and bypasses database") | ||
| 1268 | , | ||
| 1269 | AP_INIT_TAKE1("LogSQLPreserveFile", set_global_string_slot, | ||
| 1270 | (void *)APR_OFFSETOF(logsql_state,preserve_file), RSRC_CONF, | ||
| 1271 | "Name of the file to use for data preservation during database downtime") | ||
| 1272 | , | ||
| 1273 | AP_INIT_TAKE1("LogSQLSocketFile", set_global_string_slot, | ||
| 1274 | (void *)APR_OFFSETOF(global_config_t, socketfile), RSRC_CONF, | ||
| 1275 | "Name of the file to employ for socket connections to database") | ||
| 1276 | , | ||
| 1277 | AP_INIT_TAKE1("LogSQLTableType", set_global_string_slot, | ||
| 1278 | (void *)APR_OFFSETOF(global_config_t, tabletype), RSRC_CONF, | ||
| 1279 | "What kind of table to create (MyISAM, InnoDB,...) when creating tables") | ||
| 1280 | , | ||
| 1281 | AP_INIT_TAKE1("LogSQLTCPPort", set_log_sql_tcp_port, NULL, RSRC_CONF, | ||
| 1282 | "Port number to use for TCP connections to database, defaults to 3306 if not set") | ||
| 1283 | , | ||
| 1193 | AP_INIT_ITERATE("LogSQLWhichNotes", add_server_string_slot, | 1284 | AP_INIT_ITERATE("LogSQLWhichNotes", add_server_string_slot, |
| 1194 | (void *)APR_OFFSETOF(logsql_state, notes_list), RSRC_CONF, | 1285 | (void *)APR_OFFSETOF(logsql_state, notes_list), RSRC_CONF, |
| 1195 | "Notes that you would like to log in a separate table") | 1286 | "Notes that you would like to log in a separate table") |
| @@ -1206,26 +1297,6 @@ static const command_rec log_sql_cmds[] = { | |||
| 1206 | (void *)APR_OFFSETOF(logsql_state, cookie_list), RSRC_CONF, | 1297 | (void *)APR_OFFSETOF(logsql_state, cookie_list), RSRC_CONF, |
| 1207 | "The cookie(s) that you would like to log in a separate table") | 1298 | "The cookie(s) that you would like to log in a separate table") |
| 1208 | , | 1299 | , |
| 1209 | AP_INIT_RAW_ARGS("LogSQLDeprecated", ap_set_deprecated, NULL, RSRC_CONF, | ||
| 1210 | "<br><b>Deprecated</b><br>The following Commands are deprecated and should not be used.. <br>Read the documentation for more information<br><b>Deprecated</b>") | ||
| 1211 | , | ||
| 1212 | /* Deprecated commands */ | ||
| 1213 | AP_INIT_TAKE1("LogSQLDatabase", set_dbparam_slot, | ||
| 1214 | (void *)"database", RSRC_CONF, | ||
| 1215 | "<b>(Deprecated) Use LogSQLDBParam database dbname.</b> The name of the database database for logging") | ||
| 1216 | , | ||
| 1217 | AP_INIT_TAKE1("LogSQLTableType", set_dbparam_slot, | ||
| 1218 | (void *)"tabletype", RSRC_CONF, | ||
| 1219 | "<b>(Deprecated) Use LogSQLDBParam tabletype type.</b> What kind of table to create (MyISAM, InnoDB,...) when creating tables") | ||
| 1220 | , | ||
| 1221 | AP_INIT_TAKE1("LogSQLSocketFile", set_dbparam_slot, | ||
| 1222 | (void *)"socketfile", RSRC_CONF, | ||
| 1223 | "<b>(Deprecated) Use LogSQLDBParam socketfile socket.</b> Name of the file to employ for socket connections to database") | ||
| 1224 | , | ||
| 1225 | AP_INIT_TAKE1("LogSQLTCPPort", set_dbparam_slot, | ||
| 1226 | (void *)"port", RSRC_CONF, | ||
| 1227 | "<b>(Deprecated) Use LogSQLDBParam port port.</b> Port number to use for TCP connections to database, defaults to 3306 if not set") | ||
| 1228 | , | ||
| 1229 | {NULL} | 1300 | {NULL} |
| 1230 | }; | 1301 | }; |
| 1231 | /* The configuration array that sets up the hooks into the module. */ | 1302 | /* The configuration array that sets up the hooks into the module. */ |
| @@ -1233,6 +1304,7 @@ static const command_rec log_sql_cmds[] = { | |||
| 1233 | static void register_hooks(apr_pool_t *p) { | 1304 | static void register_hooks(apr_pool_t *p) { |
| 1234 | ap_hook_post_config(log_sql_post_config, NULL, NULL, APR_HOOK_REALLY_FIRST); | 1305 | ap_hook_post_config(log_sql_post_config, NULL, NULL, APR_HOOK_REALLY_FIRST); |
| 1235 | ap_hook_child_init(log_sql_child_init, NULL, NULL, APR_HOOK_MIDDLE); | 1306 | ap_hook_child_init(log_sql_child_init, NULL, NULL, APR_HOOK_MIDDLE); |
| 1307 | ap_hook_open_logs(log_sql_open, NULL, NULL, APR_HOOK_MIDDLE); | ||
| 1236 | ap_hook_log_transaction(log_sql_transaction, NULL, NULL, APR_HOOK_MIDDLE); | 1308 | ap_hook_log_transaction(log_sql_transaction, NULL, NULL, APR_HOOK_MIDDLE); |
| 1237 | } | 1309 | } |
| 1238 | 1310 | ||
| @@ -1246,7 +1318,7 @@ module AP_MODULE_DECLARE_DATA log_sql_module = { | |||
| 1246 | register_hooks /* register hooks */ | 1318 | register_hooks /* register hooks */ |
| 1247 | }; | 1319 | }; |
| 1248 | #elif defined(WITH_APACHE13) | 1320 | #elif defined(WITH_APACHE13) |
| 1249 | module MODULE_VAR_EXPORT log_sql_module = { | 1321 | module log_sql_module = { |
| 1250 | STANDARD_MODULE_STUFF, | 1322 | STANDARD_MODULE_STUFF, |
| 1251 | log_sql_module_init, /* module initializer */ | 1323 | log_sql_module_init, /* module initializer */ |
| 1252 | NULL, /* create per-dir config */ | 1324 | NULL, /* create per-dir config */ |
