Just noticed that there is a little bit of silliness (as usual) in the original patch. Nothing serious, but this one should make a bit more sense...
Bojan
--- mod_log_config.c.original Tue Aug 20 12:51:20 2002 +++ mod_log_config.c Tue Aug 20 13:33:50 2002 @@ -151,6 +151,8 @@ * %...m: the request method * %...H: the request protocol * %...q: the query string prepended by "?", or empty if no query string + * %...I: bytes received, including request and headers, cannot be zero + * %...O: bytes sent, including headers, cannot be zero * * The '...' can be nothing at all (e.g. "%h %u %r %s %b"), or it can * indicate conditions for inclusion of the item (which will cause it @@ -489,6 +491,63 @@ return "-"; } +/* + * Header length function to work with ap_table_do() + * + * This and log_bytes_recv_all() and log_bytes_sent_all() is reworked from + * Simone Tellini's mod_accounting: http://sourceforge.net/projects/mod-acct/ + * + */ +static int get_header_len(void *count, const char *key, const char *val) { + + /* Header name, colon, space, header value, CRLF */ + *((long *)count) += strlen(key) + strlen(val) + 4; + + return 1; +} + +static const char *log_bytes_recv_all(request_rec *r, char *a) +{ + /* Request length, CRLF and another CRLF after headers */ + long recv = strlen(r->the_request) + 4; /* Never zero */ + const char *clen = ap_table_get(r->headers_in, "Content-Length" ); + + /* Add length of headers */ + ap_table_do(get_header_len, &recv, r->headers_in, NULL); + + if (clen) /* We checked the value makes sense in http_protocol.c */ + recv += atol(clen); + + return ap_psprintf(r->pool, "%ld", recv); +} + +static const char *log_bytes_sent_all(request_rec *r, char *a) +{ + long sent; + + /* Headers that don't make it into headers tables + * "HTTP/x.x " + CRLF = 11 bytes + * "Server: " + CRLF = 10 bytes + * "Date: " + CRLF = 8 bytes + * CRLF after headers = 2 bytes --> Total = 31 bytes */ + sent = strlen(r->status_line) + strlen(ap_get_server_version()) + + strlen(ap_gm_timestr_822(r->pool, r->request_time)) + 31; + + /* Add regular and error headers */ + ap_table_do(get_header_len, &sent, r->headers_out, NULL); + ap_table_do(get_header_len, &sent, r->err_headers_out, NULL); + + /* Is the browser bug being avoided? + * If so, header "X-Pad: avoid browser bug" will be added and a CRLF + * 26 bytes in total */ + if (sent >= 255 && sent <= 257) + sent += 26; + + sent += r->bytes_sent; + + return ap_psprintf(r->pool, "%ld", sent); +} + /***************************************************************** * * Parsing the log format string @@ -576,6 +635,12 @@ 'c', log_connection_status, 0 }, { + 'I', log_bytes_recv_all, 0 + }, + { + 'O', log_bytes_sent_all, 0 + }, + { '\0' } };