Attached you'll find a more or less straightforward port of ap_escape_logitem, introduced in 1.3.25.
Two questions: - is this a minor mmn bump? (I'd say: yes, because new api) - should we make it configurable (via LogFormat?), I'm not sure ... TIA, nd *mumbling something about outdated docs, I've just discovered this feature accidentally ;-)* -- package Hacker::Perl::Another::Just;print [EMAIL PROTECTED] split/::/ =>__PACKAGE__]}~; # André Malo # http://pub.perlig.de #
diff -Nur httpd-2.1\include\httpd.h httpd-2.1.escape\include\httpd.h --- httpd-2.1\include\httpd.h Mon Feb 03 18:52:53 2003 +++ httpd-2.1.escape\include\httpd.h Wed Mar 05 01:08:12 2003 @@ -1360,6 +1360,14 @@ AP_DECLARE(char *) ap_escape_html(apr_pool_t *p, const char *s); /** + * Escape a string for logging + * @param p The pool to allocate from + * @param s The string to escape + * @return The escaped string + */ +AP_DECLARE(char *) ap_escape_logitem(apr_pool_t *p, const char *str); + +/** * Construct a full hostname * @param p The pool to allocate from * @param hostname The hostname of the server diff -Nur httpd-2.1\modules\loggers\mod_log_config.c httpd-2.1.escape\modules\loggers\mod_log_config.c --- httpd-2.1\modules\loggers\mod_log_config.c Fri Feb 14 15:25:44 2003 +++ httpd-2.1.escape\modules\loggers\mod_log_config.c Wed Mar 05 01:55:29 2003 @@ -333,8 +333,9 @@ static const char *log_remote_host(request_rec *r, char *a) { - return ap_get_remote_host(r->connection, r->per_dir_config, - REMOTE_NAME, NULL); + return ap_escape_logitem(r->pool, ap_get_remote_host(r->connection, + r->per_dir_config, + REMOTE_NAME, NULL)); } static const char *log_remote_address(request_rec *r, char *a) @@ -349,7 +350,7 @@ static const char *log_remote_logname(request_rec *r, char *a) { - return ap_get_remote_logname(r); + return ap_escape_logitem(r->pool, ap_get_remote_logname(r)); } static const char *log_remote_user(request_rec *r, char *a) @@ -362,6 +363,10 @@ else if (strlen(rvalue) == 0) { rvalue = "\"\""; } + else { + rvalue = ap_escape_logitem(r->pool, rvalue); + } + return rvalue; } @@ -372,33 +377,37 @@ * (note the truncation before the protocol string for HTTP/0.9 requests) * (note also that r->the_request contains the unmodified request) */ - return (r->parsed_uri.password) - ? apr_pstrcat(r->pool, r->method, " ", - apr_uri_unparse(r->pool, &r->parsed_uri, 0), - r->assbackwards ? NULL : " ", r->protocol, NULL) - : r->the_request; + return ap_escape_logitem(r->pool, + (r->parsed_uri.password) + ? apr_pstrcat(r->pool, r->method, " ", + apr_uri_unparse(r->pool, + &r->parsed_uri, 0), + r->assbackwards ? NULL : " ", + r->protocol, NULL) + : r->the_request); } static const char *log_request_file(request_rec *r, char *a) { - return r->filename; + return ap_escape_logitem(r->pool, r->filename); } static const char *log_request_uri(request_rec *r, char *a) { - return r->uri; + return ap_escape_logitem(r->pool, r->uri); } static const char *log_request_method(request_rec *r, char *a) { - return r->method; + return ap_escape_logitem(r->pool, r->method); } static const char *log_request_protocol(request_rec *r, char *a) { - return r->protocol; + return ap_escape_logitem(r->pool, r->protocol); } static const char *log_request_query(request_rec *r, char *a) { - return (r->args != NULL) ? apr_pstrcat(r->pool, "?", r->args, NULL) - : ""; + return (r->args) ? apr_pstrcat(r->pool, "?", + ap_escape_logitem(r->pool, r->args), NULL) + : ""; } static const char *log_status(request_rec *r, char *a) { @@ -428,7 +437,7 @@ static const char *log_header_in(request_rec *r, char *a) { - return apr_table_get(r->headers_in, a); + return ap_escape_logitem(r->pool, apr_table_get(r->headers_in, a)); } static const char *log_header_out(request_rec *r, char *a) @@ -438,18 +447,18 @@ cp = ap_field_noparam(r->pool, r->content_type); } if (cp) { - return cp; + return ap_escape_logitem(r->pool, cp); } - return apr_table_get(r->err_headers_out, a); + return ap_escape_logitem(r->pool, apr_table_get(r->err_headers_out, a)); } static const char *log_note(request_rec *r, char *a) { - return apr_table_get(r->notes, a); + return ap_escape_logitem(r->pool, apr_table_get(r->notes, a)); } static const char *log_env_var(request_rec *r, char *a) { - return apr_table_get(r->subprocess_env, a); + return ap_escape_logitem(r->pool, apr_table_get(r->subprocess_env, a)); } static const char *log_cookie(request_rec *r, char *a) @@ -467,7 +476,7 @@ if (end_cookie) { *end_cookie = '\0'; } - return cookie; + return ap_escape_logitem(r->pool, cookie); } } return NULL; @@ -585,7 +594,7 @@ */ static const char *log_virtual_host(request_rec *r, char *a) { - return r->server->server_hostname; + return ap_escape_logitem(r->pool, r->server->server_hostname); } static const char *log_server_port(request_rec *r, char *a) @@ -599,7 +608,7 @@ */ static const char *log_server_name(request_rec *r, char *a) { - return ap_get_server_name(r); + return ap_escape_logitem(r->pool, ap_get_server_name(r)); } static const char *log_child_pid(request_rec *r, char *a) diff -Nur httpd-2.1\server\gen_test_char.c httpd-2.1.escape\server\gen_test_char.c --- httpd-2.1\server\gen_test_char.c Mon Feb 03 18:53:18 2003 +++ httpd-2.1.escape\server\gen_test_char.c Wed Mar 05 01:11:22 2003 @@ -73,6 +73,7 @@ #define T_ESCAPE_PATH_SEGMENT (0x02) #define T_OS_ESCAPE_PATH (0x04) #define T_HTTP_TOKEN_STOP (0x08) +#define T_ESCAPE_LOGITEM (0x10) int main(int argc, char *argv[]) { @@ -85,13 +86,15 @@ "#define T_ESCAPE_PATH_SEGMENT (%u)\n" "#define T_OS_ESCAPE_PATH (%u)\n" "#define T_HTTP_TOKEN_STOP (%u)\n" + "#define T_ESCAPE_LOGITEM (%u)\n" "\n" "static const unsigned char test_char_table[256] = {\n" " 0,", T_ESCAPE_SHELL_CMD, T_ESCAPE_PATH_SEGMENT, T_OS_ESCAPE_PATH, - T_HTTP_TOKEN_STOP); + T_HTTP_TOKEN_STOP, + T_ESCAPE_LOGITEM); /* we explicitly dealt with NUL above * in case some strchr() do bogosity with it */ @@ -135,8 +138,16 @@ flags |= T_HTTP_TOKEN_STOP; } - printf("%u%c", flags, (c < 255) ? ',' : ' '); + /* For logging, escape all control characters, + * double quotes (because they delimit the request in the log file) + * backslashes (because we use backslash for escaping) + * and 8-bit chars with the high bit set + */ + if (!apr_isprint(c) || c == '"' || c == '\\' || apr_iscntrl(c)) { + flags |= T_ESCAPE_LOGITEM; + } + printf("%u%c", flags, (c < 255) ? ',' : ' '); } printf("\n};\n"); diff -Nur httpd-2.1\server\util.c httpd-2.1.escape\server\util.c --- httpd-2.1\server\util.c Thu Feb 13 03:42:51 2003 +++ httpd-2.1.escape\server\util.c Wed Mar 05 00:16:31 2003 @@ -1784,6 +1784,58 @@ return x; } +AP_DECLARE(char *) ap_escape_logitem(apr_pool_t *p, const char *str) +{ + char *ret; + unsigned char *d; + const unsigned char *s; + + if (!str) { + return NULL; + } + + ret = apr_palloc(p, 4 * strlen(str) + 1); /* Be safe */ + d = (unsigned char *)ret; + s = (const unsigned char *)str; + for (; *s; ++s) { + + if (TEST_CHAR(*s, T_ESCAPE_LOGITEM)) { + *d++ = '\\'; + switch(*s) { + case '\b': + *d++ = 'b'; + break; + case '\n': + *d++ = 'n'; + break; + case '\r': + *d++ = 'r'; + break; + case '\t': + *d++ = 't'; + break; + case '\v': + *d++ = 'v'; + break; + case '\\': + case '"': + *d++ = *s; + break; + default: + c2x(*s, d); + *d = 'x'; + d += 3; + } + } + else { + *d++ = *s; + } + } + *d = '\0'; + + return ret; +} + AP_DECLARE(int) ap_is_directory(apr_pool_t *p, const char *path) { apr_finfo_t finfo;