diff options
| -rw-r--r-- | CHANGELOG | 14 | ||||
| -rw-r--r-- | mod_log_sql.c | 311 |
2 files changed, 194 insertions, 131 deletions
| @@ -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 | ||
| 4 | TODO: | 4 | TODO: |
| 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 | ||
| 8 | CHANGES: | 9 | CHANGES: |
| 9 | 10 | ||
| 11 | 1.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 | |||
| 10 | 1.09: | 22 | 1.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" |
| 75 | #include "http_log.h" | 79 | #include "http_log.h" |
| 80 | #include "http_core.h" | ||
| 76 | #if MODULE_MAGIC_NUMBER >= 19980324 | 81 | #if MODULE_MAGIC_NUMBER >= 19980324 |
| 77 | #include "ap_compat.h" | 82 | #include "ap_compat.h" |
| 78 | #endif | 83 | #endif |
| 79 | #include "http_core.h" | ||
| 80 | #include <time.h> | ||
| 81 | #include <mysql/mysql.h> | ||
| 82 | 84 | ||
| 83 | module mysql_log_module; | 85 | module mysql_log_module; |
| 84 | MYSQL log_sql_server, *mysql_log = NULL; | 86 | MYSQL log_sql_server, *mysql_log = NULL; |
| @@ -95,26 +97,26 @@ typedef struct { | |||
| 95 | char *transfer_log_format; | 97 | char *transfer_log_format; |
| 96 | } log_mysql_state; | 98 | } log_mysql_state; |
| 97 | 99 | ||
| 98 | 100 | /* Defined in /usr/local/Apache/include/ap_mmn.h, 19990320 as of this writing. */ | |
| 99 | #if MODULE_MAGIC_NUMBER < 19970103 | 101 | #if MODULE_MAGIC_NUMBER < 19970103 |
| 100 | extern const char *log_remote_host(request_rec * r, char *a); | 102 | extern const char *log_remote_host(request_rec *r, char *a); |
| 101 | extern const char *log_remote_logname(request_rec * r, char *a); | 103 | extern const char *log_remote_logname(request_rec *r, char *a); |
| 102 | extern const char *log_remote_user(request_rec * r, char *a); | 104 | extern const char *log_remote_user(request_rec *r, char *a); |
| 103 | extern const char *log_request_time(request_rec * r, char *a); | 105 | extern const char *log_request_time(request_rec *r, char *a); |
| 104 | extern const char *log_request_timestamp(request_rec * r, char *a); | 106 | extern const char *log_request_timestamp(request_rec *r, char *a); |
| 105 | extern const char *log_request_duration(request_rec * r, char *a); | 107 | extern const char *log_request_duration(request_rec *r, char *a); |
| 106 | extern const char *log_request_line(request_rec * r, char *a); | 108 | extern const char *log_request_line(request_rec *r, char *a); |
| 107 | extern const char *log_request_file(request_rec * r, char *a); | 109 | extern const char *log_request_file(request_rec *r, char *a); |
| 108 | extern const char *log_request_uri(request_rec * r, char *a); | 110 | extern const char *log_request_uri(request_rec *r, char *a); |
| 109 | extern const char *log_status(request_rec * r, char *a); | 111 | extern const char *log_status(request_rec *r, char *a); |
| 110 | extern const char *log_bytes_sent(request_rec * r, char *a); | 112 | extern const char *log_bytes_sent(request_rec *r, char *a); |
| 111 | extern const char *log_header_in(request_rec * r, char *a); | 113 | extern const char *log_header_in(request_rec *r, char *a); |
| 112 | extern const char *log_header_out(request_rec * r, char *a); | 114 | extern const char *log_header_out(request_rec *r, char *a); |
| 113 | extern const char *log_note(request_rec * r, char *a); | 115 | extern const char *log_note(request_rec *r, char *a); |
| 114 | extern const char *log_env_var(request_rec * r, char *a); | 116 | extern const char *log_env_var(request_rec *r, char *a); |
| 115 | extern const char *log_virtual_host(request_rec * r, char *a); | 117 | extern const char *log_virtual_host(request_rec *r, char *a); |
| 116 | extern const char *log_server_port(request_rec * r, char *a); | 118 | extern const char *log_server_port(request_rec *r, char *a); |
| 117 | extern const char *log_child_pid(request_rec * r, char *a); | 119 | extern const char *log_child_pid(request_rec *r, char *a); |
| 118 | #else | 120 | #else |
| 119 | static char *format_integer(pool *p, int i) | 121 | static 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 | ||
| 135 | static 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 | |||
| 142 | static 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 | ||
| 140 | static const char *log_remote_logname(request_rec * r, char *a) | 147 | static 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 | ||
| 145 | static const char *log_remote_user(request_rec * r, char *a) | 152 | static 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 | ||
| 157 | static const char *log_request_line(request_rec * r, char *a) | 164 | static 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 | ||
| 162 | static const char *log_request_file(request_rec * r, char *a) | 169 | static const char *log_request_file(request_rec *r, char *a) |
| 163 | { | 170 | { |
| 164 | return r->filename; | 171 | return r->filename; |
| 165 | } | 172 | } |
| 166 | 173 | ||
| 167 | static const char *log_request_uri(request_rec * r, char *a) | 174 | static const char *log_request_uri(request_rec *r, char *a) |
| 168 | { | 175 | { |
| 169 | return r->uri; | 176 | return r->uri; |
| 170 | } | 177 | } |
| 171 | 178 | ||
| 172 | static const char *log_status(request_rec * r, char *a) | 179 | static 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 | ||
| 177 | static const char *log_bytes_sent(request_rec * r, char *a) | 184 | static 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 | ||
| 190 | static const char *log_header_in(request_rec * r, char *a) | 197 | static 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 | ||
| 195 | static const char *log_header_out(request_rec * r, char *a) | 202 | static 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 | ||
| 207 | static const char *log_request_time(request_rec * r, char *a) | 214 | static 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 | ||
| 230 | static const char *log_request_duration(request_rec * r, char *a) | 237 | static 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 | ||
| 238 | static const char *log_virtual_host(request_rec * r, char *a) | 245 | static 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 | ||
| 243 | static const char *log_server_port(request_rec * r, char *a) | 250 | static 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 | ||
| 251 | static const char *log_child_pid(request_rec * r, char *a) | 258 | static 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 | ||
| 258 | static const char *log_referer(request_rec * r, char *a) | 265 | static 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 | ||
| 272 | static const char *log_agent(request_rec * r, char *a) | 278 | static 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 | ||
| 285 | const char *log_request_timestamp(request_rec * r, char *a) | 291 | static 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 | |||
| 338 | const 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 | ||
| 293 | static const char *log_note(request_rec * r, char *a) | 346 | static 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 | ||
| 298 | static const char *log_env_var(request_rec * r, char *a) | 351 | static 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 | |||
| 304 | struct log_mysql_item_list { | 361 | struct 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 | */ |
| 339 | const char *mysql_escape_log(const char *str, pool *p) | 397 | const 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 | ||
| 402 | void *make_log_mysql_state(pool *p, server_rec * s) | 466 | void *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 | ||
| 414 | const char *set_referer_log_mysql_table(cmd_parms * parms, void *dummy, char *arg) | 478 | const 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 | ||
| 424 | const char *set_agent_log_mysql_table(cmd_parms * parms, void *dummy, char *arg) | 488 | const 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 | ||
| 434 | const char *set_transfer_log_mysql_table(cmd_parms * parms, void *dummy, char *arg) | 498 | const 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 | ||
| 444 | const char *set_transfer_log_format(cmd_parms * parms, void *dummy, char *arg) | 508 | const 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 | ||
| 454 | const char *set_log_mysql_db(cmd_parms * parms, void *dummy, char *arg) | 518 | const 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 | ||
| 460 | const char *set_log_mysql_info(cmd_parms * parms, void *dummy, char *host, char *user, char *pwd) | 524 | const 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 | ||
| 475 | const char *add_referer_mysql_ignore(cmd_parms * parms, void *dummy, char *arg) | 539 | const 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 | ||
| 486 | const char *add_transfer_mysql_ignore(cmd_parms * parms, void *dummy, char *arg) | 550 | const 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 | ||
| 497 | const char *add_remhost_mysql_ignore(cmd_parms * parms, void *dummy, char *arg) | 561 | const 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 | ||
| 540 | void log_mysql_child(void *cmd) | 604 | int 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 | |||
| 561 | int 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 | */ |
| 625 | int log_mysql_transaction(request_rec * orig) | 669 | int 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; |
