=== modified file 'configure.in' --- configure.in 2010-11-27 06:44:33 +0000 +++ configure.in 2010-11-28 11:19:02 +0000 @@ -932,28 +932,6 @@ dnl ]) -AC_ARG_ENABLE(useragent-log, - AS_HELP_STRING([--enable-useragent-log], - [Enable logging of User-Agent header]), [ -SQUID_YESNO([$enableval], - [unrecognized argument to --enable-useragent-log: $enableval]) - enable_useragent_log=$enableval -]) -SQUID_DEFINE_BOOL(USE_USERAGENT_LOG,${enable_useragent_log:=no}, - [If you want to log User-Agent request header values, define this.]) -AC_MSG_NOTICE([User-Agent logging enabled: $enable_useragent_log]) - -AC_ARG_ENABLE(referer-log, - AS_HELP_STRING([--enable-referer-log],[Enable logging of Referer header]), [ -SQUID_YESNO([$enableval], - [unrecognized argument to --enable-referer-log: $enableval]) -]) -SQUID_DEFINE_BOOL(USE_REFERER_LOG,${enable_referer_log:=no}, - [If you want to log Referer request header values, define this. - By default, they are written to referer.log in the Squid logdir. - This feature is deprecated in favour of custom log formats]) -AC_MSG_NOTICE([Referer logging enabled: $enable_referer_log]) - AC_ARG_ENABLE(wccp, AS_HELP_STRING([--disable-wccp],[Disable Web Cache Coordination Protocol]), [ SQUID_YESNO([$enableval],[unrecognized argument to --disable-wccp: $enableval]) === modified file 'doc/debug-sections.txt' --- doc/debug-sections.txt 2010-10-29 00:12:28 +0000 +++ doc/debug-sections.txt 2010-11-21 04:53:18 +0000 @@ -1,14 +1,10 @@ -section -- CGI Cache Manager section -- External DISKD process implementation. -section -- Refcount allocator section -- Unlink Daemon -section -- WWW Client section 00 Announcement Server section 00 Client Database section 00 DNS Resolver Daemon section 00 Debug Routines -section 00 Hash Tables section 00 UFS Store Dump Tool section 01 Main Loop section 01 Startup and Main Loop @@ -70,8 +66,6 @@ section 39 Cache Array Routing Protocol section 39 Peer source hash based selection section 39 Peer user hash based selection -section 40 Referer Logging -section 40 User-Agent Logging section 41 Event Processing section 42 ICMP Pinger program section 43 AIOPS @@ -79,6 +73,14 @@ section 44 Peer Selection Algorithm section 45 Callback Data Registry section 46 Access Log +section 46 Access Log - Apache combined format +section 46 Access Log - Apache common format +section 46 Access Log - Squid Custom format +section 46 Access Log - Squid ICAP Logging +section 46 Access Log - Squid format +section 46 Access Log - Squid referer format +section 46 Access Log - Squid useragent format +section 46 Access Log Format Tokens section 47 Store COSS Directory Routines section 47 Store Directory Routines section 48 Persistent Connections @@ -88,7 +90,6 @@ section 51 Filedescriptor Functions section 52 URN Parsing section 53 AS Number handling -section 53 Radix Tree data structure implementation section 54 Interprocess Communication section 54 Windows Interprocess Communication section 55 HTTP Header @@ -99,7 +100,6 @@ section 60 Packer: A uniform interface to store-like modules section 61 Redirector section 62 Generic Histogram -section 63 Low Level Memory Pool Management section 64 HTTP Range Header section 65 HTTP Cache Control Header section 66 HTTP Header Tools @@ -129,7 +129,6 @@ section 83 SSL accelerator support section 84 Helper process maintenance section 85 Client-side Request Routines -section 86 ESI Expressions section 86 ESI processing section 87 Client-side Stream routines. section 88 Client-side Reply Routines === modified file 'doc/release-notes/release-3.2.sgml' --- doc/release-notes/release-3.2.sgml 2010-11-22 11:19:17 +0000 +++ doc/release-notes/release-3.2.sgml 2010-11-26 06:14:12 +0000 @@ -287,6 +287,8 @@ logging a single cache.log at relatively high debug levels on a high-traffic system. Or one which is required to store a long period of access.log and needs to conserve disk space. +

The referer_log and useragent_log directives have been converted to built-in log formats. + These logs are now created using an access_log line with the format "referrer" or "useragent". Client Bandwidth Limits

In mobile environments, Squid may need to limit Squid-to-client bandwidth @@ -448,6 +450,8 @@ New installs, or installs with no logs configured explicitly will use this module by default.

New tcp module to send each log line as text data to a TCP receiver.

New udp module to send each log line as text data to a UDP receiver. +

New format referrer to log with the format prevously used by referer_log directive. +

New format useragent to log with the format prevously used by useragent_log directive. acl random

New type random. Pseudo-randomly match requests based on a configured probability. @@ -532,6 +536,12 @@ Removed tags

+ emulate_httpd_log +

Replaced by common format option on an access_log directive. + + forward_log +

Obsolete. + ftp_list_width

Obsolete. @@ -541,9 +551,14 @@ log_fqdn

Obsolete. Replaced by automatic detection of the %>A logformat tag. + referer_log +

Replaced by the referrer format option on an access_log directive. + url_rewrite_concurrency

Replaced by url_rewrite_children ... concurrency=N option. + useragent_log +

Replaced by the useragent format option on an access_log directive. @@ -644,6 +659,12 @@ --enable-auth-ntlm-helpers

replaced by --enable-auth-ntlm. + --enable-referer-log +

Obsolete. + + --enable-useragent-log +

Obsolete. + === modified file 'lib/rfc1123.c' --- lib/rfc1123.c 2010-11-01 05:44:28 +0000 +++ lib/rfc1123.c 2010-11-20 23:19:50 +0000 @@ -246,48 +246,6 @@ return buf; } -const char * -mkhttpdlogtime(const time_t * t) -{ - static char buf[128]; - - struct tm *gmt = gmtime(t); - -#if !USE_GMT - int gmt_min, gmt_hour, gmt_yday, day_offset; - size_t len; - struct tm *lt; - int min_offset; - - /* localtime & gmtime may use the same static data */ - gmt_min = gmt->tm_min; - gmt_hour = gmt->tm_hour; - gmt_yday = gmt->tm_yday; - - lt = localtime(t); - - day_offset = lt->tm_yday - gmt_yday; - /* wrap round on end of year */ - if (day_offset > 1) - day_offset = -1; - else if (day_offset < -1) - day_offset = 1; - - min_offset = day_offset * 1440 + (lt->tm_hour - gmt_hour) * 60 - + (lt->tm_min - gmt_min); - - len = strftime(buf, 127 - 5, "%d/%b/%Y:%H:%M:%S ", lt); - snprintf(buf + len, 128 - len, "%+03d%02d", - (min_offset / 60) % 24, - min_offset % 60); -#else /* USE_GMT */ - buf[0] = '\0'; - strftime(buf, 127, "%d/%b/%Y:%H:%M:%S -000", gmt); -#endif /* USE_GMT */ - - return buf; -} - #if 0 int main() === modified file 'src/Makefile.am' --- src/Makefile.am 2010-11-27 06:44:33 +0000 +++ src/Makefile.am 2010-11-28 11:19:02 +0000 @@ -419,7 +419,6 @@ PingData.h \ protos.h \ redirect.cc \ - referer.cc \ refresh.cc \ RemovalPolicy.cc \ RemovalPolicy.h \ @@ -488,7 +487,6 @@ URLScheme.cc \ URLScheme.h \ urn.cc \ - useragent.cc \ wccp.cc \ wccp2.cc \ whois.cc \ @@ -1234,7 +1232,6 @@ peer_sourcehash.cc \ peer_userhash.cc \ redirect.cc \ - referer.cc \ refresh.cc \ RemovalPolicy.cc \ Server.cc \ @@ -1272,7 +1269,6 @@ url.cc \ URLScheme.cc \ urn.cc \ - useragent.cc \ wccp2.cc \ whois.cc \ FadingCounter.cc \ @@ -1439,7 +1435,6 @@ peer_sourcehash.cc \ peer_userhash.cc \ redirect.cc \ - referer.cc \ refresh.cc \ Server.cc \ $(SNMP_SOURCE) \ @@ -1476,7 +1471,6 @@ url.cc \ URLScheme.cc \ urn.cc \ - useragent.cc \ wccp2.cc \ whois.cc \ FadingCounter.cc \ @@ -1602,7 +1596,6 @@ peer_sourcehash.cc \ peer_userhash.cc \ redirect.cc \ - referer.cc \ refresh.cc \ Server.cc \ $(SNMP_SOURCE) \ @@ -1639,7 +1632,6 @@ url.cc \ URLScheme.cc \ urn.cc \ - useragent.cc \ wccp2.cc \ whois.cc \ FadingCounter.cc \ @@ -1755,7 +1747,6 @@ peer_userhash.cc \ pconn.cc \ redirect.cc \ - referer.cc \ refresh.cc \ RemovalPolicy.cc \ Server.cc \ @@ -1795,7 +1786,6 @@ url.cc \ URLScheme.cc \ urn.cc \ - useragent.cc \ wccp2.cc \ whois.cc \ FadingCounter.cc \ @@ -1922,7 +1912,6 @@ peer_sourcehash.cc \ peer_userhash.cc \ redirect.cc \ - referer.cc \ refresh.cc \ RemovalPolicy.cc \ Server.cc \ @@ -1960,7 +1949,6 @@ url.cc \ URLScheme.cc \ urn.cc \ - useragent.cc \ wccp2.cc \ whois.cc \ FadingCounter.cc \ @@ -2340,7 +2328,6 @@ peer_sourcehash.cc \ peer_userhash.cc \ redirect.cc \ - referer.cc \ refresh.cc \ Server.cc \ $(SNMP_SOURCE) \ @@ -2375,7 +2362,6 @@ tunnel.cc \ SwapDir.cc \ urn.cc \ - useragent.cc \ wccp2.cc \ whois.cc \ FadingCounter.cc \ === modified file 'src/SquidTime.h' --- src/SquidTime.h 2010-11-21 04:40:05 +0000 +++ src/SquidTime.h 2010-11-21 04:51:17 +0000 @@ -58,4 +58,25 @@ virtual void tick(); }; +namespace Time +{ + +/** Display time as a formatted human-readable string. + * Time syntax is + * "YYYY/MM/DD hh:mm:ss" + * + * Output is only valid until next call to this function. + */ +const char *FormatStrf(time_t t); + +/** Display time as a formatted human-readable string. + * Time string syntax used is that of Apache httpd. + * "DD/MMM/YYYY:hh:mm:ss zzzz" + * + * Output is only valid until next call to this function. + */ +const char *FormatHttpd(time_t t); + +} // namespace Time + #endif /* SQUID_TIME_H */ === modified file 'src/StatHist.cc' --- src/StatHist.cc 2009-01-21 03:47:47 +0000 +++ src/StatHist.cc 2010-11-21 04:51:18 +0000 @@ -58,9 +58,12 @@ * HP-UX and GCC (2.8?) give strange errors when these simple * functions are static. */ +namespace Math +{ static hbase_f Log; static hbase_f Exp; static hbase_f Null; +}; #endif /* low level init, higher level functions has less params */ @@ -278,7 +281,7 @@ static #endif double -Log(double x) +Math::Log(double x) { assert((x + 1.0) >= 0.0); return log(x + 1.0); @@ -288,7 +291,7 @@ static #endif double -Exp(double x) +Math::Exp(double x) { return exp(x) - 1.0; } @@ -296,7 +299,7 @@ void statHistLogInit(StatHist * H, int capacity, double min, double max) { - statHistInit(H, capacity, Log, Exp, min, max); + statHistInit(H, capacity, Math::Log, Math::Exp, min, max); } /* linear histogram for enums */ @@ -305,7 +308,7 @@ static #endif double -Null(double x) +Math::Null(double x) { return x; } @@ -313,7 +316,7 @@ void statHistEnumInit(StatHist * H, int last_enum) { - statHistInit(H, last_enum + 3, Null, Null, (double) -1, (double) (last_enum + 1 + 1)); + statHistInit(H, last_enum + 3, Math::Null, Math::Null, (double) -1, (double) (last_enum + 1 + 1)); } void @@ -327,7 +330,7 @@ void statHistIntInit(StatHist * H, int n) { - statHistInit(H, n, Null, Null, (double) 0, (double) n - 1); + statHistInit(H, n, Math::Null, Math::Null, (double) 0, (double) n - 1); } void === modified file 'src/adaptation/icap/icap_log.cc' --- src/adaptation/icap/icap_log.cc 2009-11-22 20:37:27 +0000 +++ src/adaptation/icap/icap_log.cc 2010-11-21 04:51:44 +0000 @@ -2,6 +2,7 @@ #include "icap_log.h" #include "AccessLogEntry.h" #include "log/File.h" +#include "log/Formats.h" int IcapLogfileStatus = LOG_DISABLE; @@ -11,11 +12,11 @@ customlog *log; for (log = Config.Log.icaplogs; log; log = log->next) { - if (log->type == CLF_NONE) + if (log->type == Log::Format::CLF_NONE) continue; - if (log->type == CLF_AUTO) - log->type = CLF_ICAP_SQUID; + if (log->type == Log::Format::CLF_AUTO) + log->type = Log::Format::CLF_ICAP_SQUID; log->logfile = logfileOpen(log->filename, MAX_URL << 1, 1); === modified file 'src/cache_cf.cc' --- src/cache_cf.cc 2010-11-27 06:44:33 +0000 +++ src/cache_cf.cc 2010-11-28 11:19:02 +0000 @@ -132,13 +132,9 @@ static const char *const list_sep = ", \t\n\r"; -static void parse_logformat(logformat ** logformat_definitions); static void parse_access_log(customlog ** customlog_definitions); static int check_null_access_log(customlog *customlog_definitions); - -static void dump_logformat(StoreEntry * entry, const char *name, logformat * definitions); static void dump_access_log(StoreEntry * entry, const char *name, customlog * definitions); -static void free_logformat(logformat ** definitions); static void free_access_log(customlog ** definitions); static void update_maxobjsize(void); @@ -3974,36 +3970,6 @@ } #include "AccessLogEntry.h" -/* TODO: split out parsing somehow ...*/ -static void -parse_logformat(logformat ** logformat_definitions) -{ - logformat *nlf; - char *name, *def; - - if ((name = strtok(NULL, w_space)) == NULL) - self_destruct(); - - if ((def = strtok(NULL, "\r\n")) == NULL) { - self_destruct(); - return; - } - - debugs(3, 2, "Logformat for '" << name << "' is '" << def << "'"); - - nlf = (logformat *)xcalloc(1, sizeof(logformat)); - - nlf->name = xstrdup(name); - - if (!accessLogParseLogFormat(&nlf->format, def)) { - self_destruct(); - return; - } - - nlf->next = *logformat_definitions; - - *logformat_definitions = nlf; -} static void parse_access_log(customlog ** logs) @@ -4020,19 +3986,19 @@ } if (strcmp(filename, "none") == 0) { - cl->type = CLF_NONE; + cl->type = Log::Format::CLF_NONE; goto done; } if ((logdef_name = strtok(NULL, w_space)) == NULL) - logdef_name = "auto"; + logdef_name = "squid"; debugs(3, 9, "Log definition name '" << logdef_name << "' file '" << filename << "'"); cl->filename = xstrdup(filename); /* look for the definition pointer corresponding to this name */ - lf = Config.Log.logformats; + lf = Log::TheConfig.logformats; while (lf != NULL) { debugs(3, 9, "Comparing against '" << lf->name << "'"); @@ -4044,18 +4010,25 @@ } if (lf != NULL) { - cl->type = CLF_CUSTOM; + cl->type = Log::Format::CLF_CUSTOM; cl->logFormat = lf; } else if (strcmp(logdef_name, "auto") == 0) { - cl->type = CLF_AUTO; + debugs(0,0, "WARNING: Log format 'auto' no longer exists. Using 'squid' instead."); + cl->type = Log::Format::CLF_SQUID; } else if (strcmp(logdef_name, "squid") == 0) { - cl->type = CLF_SQUID; + cl->type = Log::Format::CLF_SQUID; } else if (strcmp(logdef_name, "common") == 0) { - cl->type = CLF_COMMON; + cl->type = Log::Format::CLF_COMMON; + } else if (strcmp(logdef_name, "combined") == 0) { + cl->type = Log::Format::CLF_COMBINED; #if ICAP_CLIENT } else if (strcmp(logdef_name, "icap_squid") == 0) { - cl->type = CLF_ICAP_SQUID; + cl->type = Log::Format::CLF_ICAP_SQUID; #endif + } else if (strcmp(logdef_name, "useragent") == 0) { + cl->type = Log::Format::CLF_USERAGENT; + } else if (strcmp(logdef_name, "referrer") == 0) { + cl->type = Log::Format::CLF_REFERER; } else { debugs(3, 0, "Log format '" << logdef_name << "' is not defined"); self_destruct(); @@ -4078,12 +4051,6 @@ } static void -dump_logformat(StoreEntry * entry, const char *name, logformat * definitions) -{ - accessLogDumpLogFormat(entry, name, definitions); -} - -static void dump_access_log(StoreEntry * entry, const char *name, customlog * logs) { customlog *log; @@ -4093,36 +4060,40 @@ switch (log->type) { - case CLF_CUSTOM: + case Log::Format::CLF_CUSTOM: storeAppendPrintf(entry, "%s %s", log->filename, log->logFormat->name); break; - case CLF_NONE: + case Log::Format::CLF_NONE: storeAppendPrintf(entry, "none"); break; - case CLF_SQUID: - storeAppendPrintf(entry, "%s squid", log->filename); - break; - - case CLF_COMMON: - storeAppendPrintf(entry, "%s squid", log->filename); - break; + case Log::Format::CLF_SQUID: + storeAppendPrintf(entry, "%s squid", log->filename); + break; + + case Log::Format::CLF_COMBINED: + storeAppendPrintf(entry, "%s combined", log->filename); + break; + + case Log::Format::CLF_COMMON: + storeAppendPrintf(entry, "%s common", log->filename); + break; + #if ICAP_CLIENT - case CLF_ICAP_SQUID: + case Log::Format::CLF_ICAP_SQUID: storeAppendPrintf(entry, "%s icap_squid", log->filename); break; #endif - case CLF_AUTO: - - if (log->aclList) - storeAppendPrintf(entry, "%s auto", log->filename); - else - storeAppendPrintf(entry, "%s", log->filename); - - break; - - case CLF_UNKNOWN: + case Log::Format::CLF_USERAGENT: + storeAppendPrintf(entry, "%s useragent", log->filename); + break; + + case Log::Format::CLF_REFERER: + storeAppendPrintf(entry, "%s referrer", log->filename); + break; + + case Log::Format::CLF_UNKNOWN: break; } @@ -4134,18 +4105,6 @@ } static void -free_logformat(logformat ** definitions) -{ - while (*definitions) { - logformat *format = *definitions; - *definitions = format->next; - safe_free(format->name); - accessLogFreeLogFormat(&format->format); - xfree(format); - } -} - -static void free_access_log(customlog ** definitions) { while (*definitions) { @@ -4153,7 +4112,7 @@ *definitions = log->next; log->logFormat = NULL; - log->type = CLF_UNKNOWN; + log->type = Log::Format::CLF_UNKNOWN; if (log->aclList) aclDestroyAclList(&log->aclList); === modified file 'src/cf.data.pre' --- src/cf.data.pre 2010-11-27 23:15:46 +0000 +++ src/cf.data.pre 2010-11-28 11:19:02 +0000 @@ -2812,7 +2812,7 @@ NAME: logformat TYPE: logformat -LOC: Config.Log.logformats +LOC: Log::TheConfig DEFAULT: none DOC_START Usage: @@ -2957,10 +2957,18 @@ The default formats available (which do not need re-defining) are: -logformat squid %ts.%03tu %6tr %>a %Ss/%03>Hs %a %Ss/%03>Hs %h] [%a %ui %un [%tl] "%rm %ru HTTP/%rv" %>Hs %a %ui %un [%tl] "%rm %ru HTTP/%rv" %>Hs %h" "%{User-Agent}>h" %Ss:%Sh +logformat squid %ts.%03tu %6tr %>a %Ss/%03>Hs %a %ui %un [%tl] "%rm %ru HTTP/%rv" %>Hs %a %ui %un [%tl] "%rm %ru HTTP/%rv" %>Hs %h" "%{User-Agent}>h" %Ss:%Sh +logformat referrer %ts.%03tu %>a %{Referer}>h %ru +logformat useragent %>a [%tl] "%{User-Agent}>h" + + When the log_mime_hdrs directive is set to ON. The squid, common and combined + formats have a safely encoded copy of the mime headers appended to each line + within a pair of brackets. + + The common and combined formats are not quite true to the Apache definition. + The logs from Squid contain an extra status and hierarchy code appended. DOC_END NAME: access_log cache_access_log @@ -3221,16 +3229,9 @@ DOC_END NAME: emulate_httpd_log -COMMENT: on|off -TYPE: onoff -DEFAULT: off -LOC: Config.onoff.common_log +TYPE: obsolete DOC_START - The Cache can emulate the log file format which many 'httpd' - programs use. To disable/enable this emulation, set - emulate_httpd_log to 'off' or 'on'. The default - is to use the native log format since it includes useful - information Squid-specific log analyzers use. + Replace this with an access_log directive using the format 'common' or 'combined'. DOC_END NAME: log_ip_on_direct @@ -3268,27 +3269,15 @@ DOC_END NAME: useragent_log -TYPE: string -LOC: Config.Log.useragent -DEFAULT: none -IFDEF: USE_USERAGENT_LOG +TYPE: obsolete DOC_START - Squid will write the User-Agent field from HTTP requests - to the filename specified here. By default useragent_log - is disabled. + Replace this with an access_log directive using the format 'useragent'. DOC_END NAME: referer_log referrer_log -TYPE: string -LOC: Config.Log.referer -DEFAULT: none -IFDEF: USE_REFERER_LOG +TYPE: obsolete DOC_START - Squid will write the Referer field from HTTP requests to the - filename specified here. By default referer_log is disabled. - Note that "referer" is actually a misspelling of "referrer" - however the misspelt version has been accepted into the HTTP RFCs - and we accept both. + Replace this with an access_log directive using the format 'referrer'. DOC_END NAME: pid_filename @@ -3317,14 +3306,9 @@ DOC_END NAME: forward_log -IFDEF: WIP_FWD_LOG -TYPE: string -DEFAULT: none -LOC: Config.Log.forward +TYPE: obsolete DOC_START - Logs the server-side requests. - - This is currently work in progress. + Use a regular access.log with ACL limiting it to MISS events. DOC_END NAME: strip_query_terms === modified file 'src/cf_gen_defines' --- src/cf_gen_defines 2010-11-27 06:44:33 +0000 +++ src/cf_gen_defines 2010-11-28 11:19:02 +0000 @@ -23,11 +23,9 @@ define["USE_ICMP"]="--enable-icmp" define["USE_IDENT"]="--enable-ident-lookups" define["USE_LOADABLE_MODULES"]="--enable-loadable-modules" - define["USE_REFERER_LOG"]="--enable-referer-log" define["USE_SQUID_ESI"]="--enable-esi" define["USE_SSL"]="--enable-ssl" define["USE_UNLINKD"]="--enable-unlinkd" - define["USE_USERAGENT_LOG"]="--enable-useragent-log" define["USE_WCCP"]="--enable-wccp" define["USE_WCCPv2"]="--enable-wccpv2" define["USE_QOS_TOS"]="--enable-zph-qos" === modified file 'src/client_side_request.cc' --- src/client_side_request.cc 2010-11-27 01:46:22 +0000 +++ src/client_side_request.cc 2010-11-28 11:19:02 +0000 @@ -951,21 +951,6 @@ s.clean(); } - /** - \todo --enable-useragent-log and --enable-referer-log. We should - probably drop those two as the custom log formats accomplish pretty much the same thing.. - */ -#if USE_USERAGENT_LOG - if ((str = req_hdr->getStr(HDR_USER_AGENT))) - logUserAgent(fqdnFromAddr(http->getConn()->log_addr), str); - -#endif -#if USE_REFERER_LOG - - if ((str = req_hdr->getStr(HDR_REFERER))) - logReferer(fqdnFromAddr(http->getConn()->log_addr), str, http->log_uri); - -#endif #if USE_FORW_VIA_DB if (req_hdr->has(HDR_X_FORWARDED_FOR)) { === modified file 'src/enums.h' --- src/enums.h 2010-10-04 15:32:20 +0000 +++ src/enums.h 2010-11-21 04:52:05 +0000 @@ -342,20 +342,7 @@ _WIN_OS_WINLON, _WIN_OS_WIN7 }; - -#endif - -typedef enum { - CLF_UNKNOWN, - CLF_AUTO, - CLF_CUSTOM, - CLF_SQUID, - CLF_COMMON, -#if ICAP_CLIENT - CLF_ICAP_SQUID, -#endif - CLF_NONE -} customlog_type; +#endif enum { DISABLE_PMTU_OFF, === modified file 'src/errorpage.cc' --- src/errorpage.cc 2010-11-27 01:46:22 +0000 +++ src/errorpage.cc 2010-11-28 11:19:02 +0000 @@ -804,7 +804,7 @@ break; case 't': - mb.Printf("%s", mkhttpdlogtime(&squid_curtime)); + mb.Printf("%s", Time::FormatHttpd(squid_curtime)); break; case 'T': === modified file 'src/forward.cc' --- src/forward.cc 2010-10-28 18:52:59 +0000 +++ src/forward.cc 2010-11-21 04:52:13 +0000 @@ -67,11 +67,6 @@ #define MAX_FWD_STATS_IDX 9 static int FwdReplyCodes[MAX_FWD_STATS_IDX + 1][HTTP_INVALID_HEADER + 1]; -#if WIP_FWD_LOG -static void fwdLog(FwdState * fwdState); -static Logfile *logfile = NULL; -#endif - static PconnPool *fwdPconnPool = new PconnPool("server-side"); CBDATA_CLASS_INIT(FwdState); @@ -136,10 +131,6 @@ entry->mem_obj->checkUrlChecksum(); #endif -#if WIP_FWD_LOG - - log(); -#endif if (entry->store_status == STORE_PENDING) { if (entry->isEmpty()) { @@ -1263,18 +1254,6 @@ FwdState::initModule() { memDataInit(MEM_FWD_SERVER, "FwdServer", sizeof(FwdServer), 0); - -#if WIP_FWD_LOG - - if (logfile) - (void) 0; - else if (NULL == Config.Log.forward) - (void) 0; - else - logfile = logfileOpen(Config.Log.forward, 0, 1); - -#endif - RegisterWithCacheManager(); } @@ -1469,47 +1448,3 @@ return aclMapNfmark(Ip::Qos::TheConfig.nfmarkToServer, &ch); } - - -/**** WIP_FWD_LOG *************************************************************/ - -#if WIP_FWD_LOG -void -fwdUninit(void) -{ - if (NULL == logfile) - return; - - logfileClose(logfile); - - logfile = NULL; -} - -void -fwdLogRotate(void) -{ - if (logfile) - logfileRotate(logfile); -} - -static void -FwdState::log() -{ - if (NULL == logfile) - return; - - logfilePrintf(logfile, "%9d.%03d %03d %s %s\n", - (int) current_time.tv_sec, - (int) current_time.tv_usec / 1000, - last_status, - RequestMethodStr(request->method), - request->canonical); -} - -void -FwdState::status(http_status s) -{ - last_status = s; -} - -#endif === modified file 'src/forward.h' --- src/forward.h 2010-10-06 03:50:45 +0000 +++ src/forward.h 2010-11-21 04:52:14 +0000 @@ -81,13 +81,6 @@ ErrorState *makeConnectingError(const err_type type) const; static void RegisterWithCacheManager(void); -#if WIP_FWD_LOG - - void uninit /**DOCS_NOSEMI*/ - static void logRotate /**DOCS_NOSEMI*/ - void status() /**DOCS_NOSEMI*/ -#endif - public: StoreEntry *entry; HttpRequest *request; @@ -102,10 +95,6 @@ time_t start_t; int n_tries; int origin_tries; -#if WIP_FWD_LOG - - http_status last_status; -#endif struct { unsigned int dont_retry:1; === modified file 'src/helper.cc' --- src/helper.cc 2010-11-27 01:46:22 +0000 +++ src/helper.cc 2010-11-28 11:19:02 +0000 @@ -35,6 +35,7 @@ #include "squid.h" #include "comm/Write.h" #include "helper.h" +#include "log/Gadgets.h" #include "SquidMath.h" #include "SquidTime.h" #include "Store.h" @@ -441,7 +442,7 @@ srv->flags.shutdown ? 'S' : ' ', tt < 0.0 ? 0.0 : tt, (int) srv->roffset, - srv->requests[0] ? log_quote(srv->requests[0]->buf) : "(none)"); + srv->requests[0] ? Log::QuoteMimeBlob(srv->requests[0]->buf) : "(none)"); } storeAppendPrintf(sentry, "\nFlags key:\n\n"); @@ -495,7 +496,7 @@ srv->request ? (srv->request->placeholder ? 'P' : ' ') : ' ', tt < 0.0 ? 0.0 : tt, (int) srv->roffset, - srv->request ? log_quote(srv->request->buf) : "(none)"); + srv->request ? Log::QuoteMimeBlob(srv->request->buf) : "(none)"); } storeAppendPrintf(sentry, "\nFlags key:\n\n"); === modified file 'src/http.cc' --- src/http.cc 2010-11-27 06:44:33 +0000 +++ src/http.cc 2010-11-28 11:19:02 +0000 @@ -906,10 +906,6 @@ entry->mem_obj->vary_headers = xstrdup(vary); } -#if WIP_FWD_LOG - fwdStatus(fwd, s); - -#endif /* * If its not a reply that we will re-forward, then * allow the client to get it. === modified file 'src/log/Config.cc' --- src/log/Config.cc 2009-11-22 20:37:27 +0000 +++ src/log/Config.cc 2010-11-21 04:52:42 +0000 @@ -1,4 +1,33 @@ #include "config.h" #include "log/Config.h" +#include "log/Tokens.h" +#include "protos.h" Log::LogConfig Log::TheConfig; + +void +Log::LogConfig::parseFormats() +{ + char *name, *def; + + if ((name = strtok(NULL, w_space)) == NULL) + self_destruct(); + + if ((def = strtok(NULL, "\r\n")) == NULL) { + self_destruct(); + return; + } + + debugs(3, 2, "Logformat for '" << name << "' is '" << def << "'"); + + logformat *nlf = new logformat(name); + + if (!accessLogParseLogFormat(&nlf->format, def)) { + self_destruct(); + return; + } + + // add to global config list + nlf->next = logformats; + logformats = nlf; +} === modified file 'src/log/Config.h' --- src/log/Config.h 2010-11-27 01:58:38 +0000 +++ src/log/Config.h 2010-11-28 11:19:02 +0000 @@ -1,17 +1,35 @@ #ifndef SQUID_SRC_LOG_CONFIG_H #define SQUID_SRC_LOG_CONFIG_H +#include "log/Tokens.h" + +class StoreEntry; + namespace Log { class LogConfig { public: + void parseFormats(); + void dumpFormats(StoreEntry *e, const char *name) { + accessLogDumpLogFormat(e, name, logformats); + } + + /// File path to logging daemon executable char *logfile_daemon; + + /// Linked list of custom log formats + logformat *logformats; }; extern LogConfig TheConfig; } // namespace Log +// Legacy parsing wrappers +#define parse_logformat(X) (X)->parseFormats() +#define free_logformat(X) do{ delete (*X).logformats; (*X).logformats=NULL; }while(false) +#define dump_logformat(E,N,D) (D).dumpFormats((E),(N)) + #endif === added file 'src/log/FormatHttpdCombined.cc' --- src/log/FormatHttpdCombined.cc 1970-01-01 00:00:00 +0000 +++ src/log/FormatHttpdCombined.cc 2010-11-21 04:52:42 +0000 @@ -0,0 +1,87 @@ +/* + * $Id$ + * + * DEBUG: section 46 Access Log - Apache combined format + * AUTHOR: Amos Jeffries + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "config.h" +#include "AccessLogEntry.h" +#include "HttpRequest.h" +#include "log/File.h" +#include "log/Formats.h" +#include "log/Gadgets.h" +#include "SquidTime.h" + +void +Log::Format::HttpdCombined(AccessLogEntry * al, Logfile * logfile) +{ + char clientip[MAX_IPSTRLEN]; + + const char *user_ident = FormatName(al->cache.rfc931); + + const char *user_auth = FormatName(al->cache.authuser); + + const char *referer = al->request->header.getStr(HDR_REFERER); + if (!referer || *referer == '\0') + referer = "-"; + + const char *agent = al->request->header.getStr(HDR_USER_AGENT); + if (!agent || *agent == '\0') + agent = "-"; + + logfilePrintf(logfile, "%s %s %s [%s] \"%s %s HTTP/%d.%d\" %d %"PRId64" \"%s\" \"%s\" %s%s:%s%s", + al->cache.caddr.NtoA(clientip,MAX_IPSTRLEN), + user_ident ? user_ident : dash_str, + user_auth ? user_auth : dash_str, + Time::FormatHttpd(squid_curtime), + al->_private.method_str, + al->url, + al->http.version.major, al->http.version.minor, + al->http.code, + al->cache.replySize, + referer, + agent, + log_tags[al->cache.code], + al->http.statusSfx(), + hier_code_str[al->hier.code], + (Config.onoff.log_mime_hdrs?"":"\n")); + + safe_free(user_ident); + safe_free(user_auth); + + if (Config.onoff.log_mime_hdrs) { + char *ereq = QuoteMimeBlob(al->headers.request); + char *erep = QuoteMimeBlob(al->headers.reply); + logfilePrintf(logfile, " [%s] [%s]\n", ereq, erep); + safe_free(ereq); + safe_free(erep); + } +} === added file 'src/log/FormatHttpdCommon.cc' --- src/log/FormatHttpdCommon.cc 1970-01-01 00:00:00 +0000 +++ src/log/FormatHttpdCommon.cc 2010-11-21 04:52:42 +0000 @@ -0,0 +1,74 @@ +/* + * $Id$ + * + * DEBUG: section 46 Access Log - Apache common format + * AUTHOR: Duane Wessels + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "config.h" +#include "AccessLogEntry.h" +#include "log/File.h" +#include "log/Formats.h" +#include "log/Gadgets.h" +#include "SquidTime.h" + +void +Log::Format::HttpdCommon(AccessLogEntry * al, Logfile * logfile) +{ + char clientip[MAX_IPSTRLEN]; + const char *user_auth = FormatName(al->cache.authuser); + const char *user_ident = FormatName(al->cache.rfc931); + + logfilePrintf(logfile, "%s %s %s [%s] \"%s %s HTTP/%d.%d\" %d %"PRId64" %s%s:%s%s", + al->cache.caddr.NtoA(clientip,MAX_IPSTRLEN), + user_ident ? user_ident : dash_str, + user_auth ? user_auth : dash_str, + Time::FormatHttpd(squid_curtime), + al->_private.method_str, + al->url, + al->http.version.major, al->http.version.minor, + al->http.code, + al->cache.replySize, + log_tags[al->cache.code], + al->http.statusSfx(), + hier_code_str[al->hier.code], + (Config.onoff.log_mime_hdrs?"":"\n")); + + safe_free(user_auth); + safe_free(user_ident); + + if (Config.onoff.log_mime_hdrs) { + char *ereq = QuoteMimeBlob(al->headers.request); + char *erep = QuoteMimeBlob(al->headers.reply); + logfilePrintf(logfile, " [%s] [%s]\n", ereq, erep); + safe_free(ereq); + safe_free(erep); + } +} === added file 'src/log/FormatSquidCustom.cc' --- src/log/FormatSquidCustom.cc 1970-01-01 00:00:00 +0000 +++ src/log/FormatSquidCustom.cc 2010-11-21 08:40:05 +0000 @@ -0,0 +1,817 @@ +/* + * $Id$ + * + * DEBUG: section 46 Access Log - Squid Custom format + * AUTHOR: Duane Wessels + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "config.h" +#include "AccessLogEntry.h" +#include "log/File.h" +#include "log/Formats.h" +#include "log/Gadgets.h" +#include "log/Tokens.h" +#include "SquidTime.h" + +#include "MemBuf.h" +#include "HttpRequest.h" +#include "rfc1738.h" +#include "err_detail_type.h" +#include "errorpage.h" + +static void +log_quoted_string(const char *str, char *out) +{ + char *p = out; + + while (*str) { + int l = strcspn(str, "\"\\\r\n\t"); + memcpy(p, str, l); + str += l; + p += l; + + switch (*str) { + + case '\0': + break; + + case '\r': + *p++ = '\\'; + *p++ = 'r'; + str++; + break; + + case '\n': + *p++ = '\\'; + *p++ = 'n'; + str++; + break; + + case '\t': + *p++ = '\\'; + *p++ = 't'; + str++; + break; + + default: + *p++ = '\\'; + *p++ = *str; + str++; + break; + } + } + + *p++ = '\0'; +} + +void +Log::Format::SquidCustom(AccessLogEntry * al, customlog * log) +{ + logformat *lf; + Logfile *logfile; + logformat_token *fmt; + static MemBuf mb; + char tmp[1024]; + String sb; + + mb.reset(); + + lf = log->logFormat; + logfile = log->logfile; + + for (fmt = lf->format; fmt != NULL; fmt = fmt->next) { /* for each token */ + const char *out = NULL; + int quote = 0; + long int outint = 0; + int doint = 0; + int dofree = 0; + int64_t outoff = 0; + int dooff = 0; + + switch (fmt->type) { + + case LFT_NONE: + out = ""; + break; + + case LFT_STRING: + out = fmt->data.string; + break; + + case LFT_CLIENT_IP_ADDRESS: + if (al->cache.caddr.IsNoAddr()) // e.g., ICAP OPTIONS lack client + out = "-"; + else + out = al->cache.caddr.NtoA(tmp,1024); + break; + + case LFT_CLIENT_FQDN: + if (al->cache.caddr.IsAnyAddr()) // e.g., ICAP OPTIONS lack client + out = "-"; + else + out = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS); + if (!out) { + out = al->cache.caddr.NtoA(tmp,1024); + } + + break; + + case LFT_CLIENT_PORT: + if (al->request) { + outint = al->request->client_addr.GetPort(); + doint = 1; + } + break; + +#if USE_SQUID_EUI + case LFT_CLIENT_EUI: + if (al->request) { + if (al->cache.caddr.IsIPv4()) + al->request->client_eui48.encode(tmp, 1024); + else + al->request->client_eui64.encode(tmp, 1024); + out = tmp; + } + break; +#endif + + /* case LFT_SERVER_IP_ADDRESS: */ + + case LFT_SERVER_IP_OR_PEER_NAME: + out = al->hier.host; + + break; + + /* case LFT_SERVER_PORT: */ + + case LFT_LOCAL_IP: + if (al->request) { + out = al->request->my_addr.NtoA(tmp,1024); + } + + break; + + case LFT_LOCAL_PORT: + if (al->request) { + outint = al->request->my_addr.GetPort(); + doint = 1; + } + + break; + + case LFT_PEER_LOCAL_PORT: + if (al->hier.peer_local_port) { + outint = al->hier.peer_local_port; + doint = 1; + } + + break; + + case LFT_TIME_SECONDS_SINCE_EPOCH: + // some platforms store time in 32-bit, some 64-bit... + outoff = static_cast(current_time.tv_sec); + dooff = 1; + break; + + case LFT_TIME_SUBSECOND: + outint = current_time.tv_usec / fmt->divisor; + doint = 1; + break; + + + case LFT_TIME_LOCALTIME: + + case LFT_TIME_GMT: { + const char *spec; + + struct tm *t; + spec = fmt->data.timespec; + + if (fmt->type == LFT_TIME_LOCALTIME) { + if (!spec) + spec = "%d/%b/%Y:%H:%M:%S %z"; + t = localtime(&squid_curtime); + } else { + if (!spec) + spec = "%d/%b/%Y:%H:%M:%S"; + + t = gmtime(&squid_curtime); + } + + strftime(tmp, sizeof(tmp), spec, t); + + out = tmp; + } + + break; + + case LFT_TIME_TO_HANDLE_REQUEST: + outint = al->cache.msec; + doint = 1; + break; + + case LFT_PEER_RESPONSE_TIME: + if (al->hier.peer_response_time < 0) { + out = "-"; + } else { + outoff = al->hier.peer_response_time; + dooff = 1; + } + break; + + case LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME: + if (al->hier.total_response_time < 0) { + out = "-"; + } else { + outoff = al->hier.total_response_time; + dooff = 1; + } + break; + + case LFT_DNS_WAIT_TIME: + if (al->request && al->request->dnsWait >= 0) { + outint = al->request->dnsWait; + doint = 1; + } + break; + + case LFT_REQUEST_HEADER: + + if (al->request) + sb = al->request->header.getByName(fmt->data.header.header); + + out = sb.termedBuf(); + + quote = 1; + + break; + + case LFT_ADAPTED_REQUEST_HEADER: + + if (al->request) + sb = al->adapted_request->header.getByName(fmt->data.header.header); + + out = sb.termedBuf(); + + quote = 1; + + break; + + case LFT_REPLY_HEADER: + if (al->reply) + sb = al->reply->header.getByName(fmt->data.header.header); + + out = sb.termedBuf(); + + quote = 1; + + break; + +#if USE_ADAPTATION + case LTF_ADAPTATION_SUM_XACT_TIMES: + if (al->request) { + Adaptation::History::Pointer ah = al->request->adaptHistory(); + if (ah != NULL) + ah->sumLogString(fmt->data.string, sb); + out = sb.termedBuf(); + } + break; + + case LTF_ADAPTATION_ALL_XACT_TIMES: + if (al->request) { + Adaptation::History::Pointer ah = al->request->adaptHistory(); + if (ah != NULL) + ah->allLogString(fmt->data.string, sb); + out = sb.termedBuf(); + } + break; +#endif + +#if ICAP_CLIENT + case LFT_ICAP_LAST_MATCHED_HEADER: + if (al->request) { + Adaptation::Icap::History::Pointer ih = al->request->icapHistory(); + if (ih != NULL) + sb = ih->mergeOfIcapHeaders.getByName(fmt->data.header.header); + } + + out = sb.termedBuf(); + + quote = 1; + + break; + + case LFT_ICAP_LAST_MATCHED_HEADER_ELEM: + if (al->request) { + Adaptation::Icap::History::Pointer ih = al->request->icapHistory(); + if (ih != NULL) + sb = ih->mergeOfIcapHeaders.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator); + } + + out = sb.termedBuf(); + + quote = 1; + + break; + + case LFT_ICAP_LAST_MATCHED_ALL_HEADERS: + out = al->headers.icap; + + quote = 1; + + break; + + case LFT_ICAP_ADDR: + if (!out) + out = al->icap.hostAddr.NtoA(tmp,1024); + break; + + case LFT_ICAP_SERV_NAME: + out = al->icap.serviceName.termedBuf(); + break; + + case LFT_ICAP_REQUEST_URI: + out = al->icap.reqUri.termedBuf(); + break; + + case LFT_ICAP_REQUEST_METHOD: + out = Adaptation::Icap::ICAP::methodStr(al->icap.reqMethod); + break; + + case LFT_ICAP_BYTES_SENT: + outoff = al->icap.bytesSent; + dooff = 1; + break; + + case LFT_ICAP_BYTES_READ: + outoff = al->icap.bytesRead; + dooff = 1; + break; + + case LFT_ICAP_BODY_BYTES_READ: + if (al->icap.bodyBytesRead >= 0) { + outoff = al->icap.bodyBytesRead; + dooff = 1; + } + // else if icap.bodyBytesRead < 0, we do not have any http data, + // so just print a "-" (204 responses etc) + break; + + case LFT_ICAP_REQ_HEADER: + if (NULL != al->icap.request) { + sb = al->icap.request->header.getByName(fmt->data.header.header); + out = sb.termedBuf(); + quote = 1; + } + break; + + case LFT_ICAP_REQ_HEADER_ELEM: + if (al->request) + sb = al->icap.request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator); + + out = sb.termedBuf(); + + quote = 1; + + break; + + case LFT_ICAP_REQ_ALL_HEADERS: + if (al->icap.request) { + HttpHeaderPos pos = HttpHeaderInitPos; + while (const HttpHeaderEntry *e = al->icap.request->header.getEntry(&pos)) { + sb.append(e->name); + sb.append(": "); + sb.append(e->value); + sb.append("\r\n"); + } + out = sb.termedBuf(); + quote = 1; + } + break; + + case LFT_ICAP_REP_HEADER: + if (NULL != al->icap.reply) { + sb = al->icap.reply->header.getByName(fmt->data.header.header); + out = sb.termedBuf(); + quote = 1; + } + break; + + case LFT_ICAP_REP_HEADER_ELEM: + if (NULL != al->icap.reply) + sb = al->icap.reply->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator); + + out = sb.termedBuf(); + + quote = 1; + + break; + + case LFT_ICAP_REP_ALL_HEADERS: + if (al->icap.reply) { + HttpHeaderPos pos = HttpHeaderInitPos; + while (const HttpHeaderEntry *e = al->icap.reply->header.getEntry(&pos)) { + sb.append(e->name); + sb.append(": "); + sb.append(e->value); + sb.append("\r\n"); + } + out = sb.termedBuf(); + quote = 1; + } + break; + + case LFT_ICAP_TR_RESPONSE_TIME: + outint = al->icap.trTime; + doint = 1; + break; + + case LFT_ICAP_IO_TIME: + outint = al->icap.ioTime; + doint = 1; + break; + + case LFT_ICAP_STATUS_CODE: + outint = al->icap.resStatus; + doint = 1; + break; + + case LFT_ICAP_OUTCOME: + out = al->icap.outcome; + break; + + case LFT_ICAP_TOTAL_TIME: + outint = al->icap.processingTime; + doint = 1; + break; +#endif + case LFT_REQUEST_HEADER_ELEM: + if (al->request) + sb = al->request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator); + + out = sb.termedBuf(); + + quote = 1; + + break; + + case LFT_ADAPTED_REQUEST_HEADER_ELEM: + if (al->adapted_request) + sb = al->adapted_request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator); + + out = sb.termedBuf(); + + quote = 1; + + break; + + case LFT_REPLY_HEADER_ELEM: + if (al->reply) + sb = al->reply->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator); + + out = sb.termedBuf(); + + quote = 1; + + break; + + case LFT_REQUEST_ALL_HEADERS: + out = al->headers.request; + + quote = 1; + + break; + + case LFT_ADAPTED_REQUEST_ALL_HEADERS: + out = al->headers.adapted_request; + + quote = 1; + + break; + + case LFT_REPLY_ALL_HEADERS: + out = al->headers.reply; + + quote = 1; + + break; + + case LFT_USER_NAME: + out = Log::FormatName(al->cache.authuser); + + if (!out) + out = Log::FormatName(al->cache.extuser); + +#if USE_SSL + + if (!out) + out = Log::FormatName(al->cache.ssluser); + +#endif + + if (!out) + out = Log::FormatName(al->cache.rfc931); + + dofree = 1; + + break; + + case LFT_USER_LOGIN: + out = Log::FormatName(al->cache.authuser); + + dofree = 1; + + break; + + case LFT_USER_IDENT: + out = Log::FormatName(al->cache.rfc931); + + dofree = 1; + + break; + + case LFT_USER_EXTERNAL: + out = Log::FormatName(al->cache.extuser); + + dofree = 1; + + break; + + /* case LFT_USER_REALM: */ + /* case LFT_USER_SCHEME: */ + + // the fmt->type can not be LFT_HTTP_SENT_STATUS_CODE_OLD_30 + // but compiler complains if ommited + case LFT_HTTP_SENT_STATUS_CODE_OLD_30: + case LFT_HTTP_SENT_STATUS_CODE: + outint = al->http.code; + + doint = 1; + + break; + + case LFT_HTTP_RECEIVED_STATUS_CODE: + if (al->hier.peer_reply_status == HTTP_STATUS_NONE) { + out = "-"; + } else { + outint = al->hier.peer_reply_status; + doint = 1; + } + break; + /* case LFT_HTTP_STATUS: + * out = statusline->text; + * quote = 1; + * break; + */ + case LFT_HTTP_BODY_BYTES_READ: + if (al->hier.bodyBytesRead >= 0) { + outoff = al->hier.bodyBytesRead; + dooff = 1; + } + // else if hier.bodyBytesRead < 0 we did not have any data exchange with + // a peer server so just print a "-" (eg requests served from cache, + // or internal error messages). + break; + + case LFT_SQUID_STATUS: + if (al->http.timedout || al->http.aborted) { + snprintf(tmp, sizeof(tmp), "%s%s", log_tags[al->cache.code], + al->http.statusSfx()); + out = tmp; + } else { + out = log_tags[al->cache.code]; + } + + break; + + case LFT_SQUID_ERROR: + if (al->request && al->request->errType != ERR_NONE) + out = errorPageName(al->request->errType); + break; + + case LFT_SQUID_ERROR_DETAIL: + if (al->request && al->request->errDetail != ERR_DETAIL_NONE) { + if (al->request->errDetail > ERR_DETAIL_START && + al->request->errDetail < ERR_DETAIL_MAX) + out = errorDetailName(al->request->errDetail); + else { + if (al->request->errDetail >= ERR_DETAIL_EXCEPTION_START) + snprintf(tmp, sizeof(tmp), "%s=0x%X", + errorDetailName(al->request->errDetail), (uint32_t) al->request->errDetail); + else + snprintf(tmp, sizeof(tmp), "%s=%d", + errorDetailName(al->request->errDetail), al->request->errDetail); + out = tmp; + } + } + break; + + case LFT_SQUID_HIERARCHY: + if (al->hier.ping.timedout) + mb.append("TIMEOUT_", 8); + + out = hier_code_str[al->hier.code]; + + break; + + case LFT_MIME_TYPE: + out = al->http.content_type; + + break; + + case LFT_REQUEST_METHOD: + out = al->_private.method_str; + + break; + + case LFT_REQUEST_URI: + out = al->url; + + break; + + case LFT_REQUEST_URLPATH: + if (al->request) { + out = al->request->urlpath.termedBuf(); + quote = 1; + } + break; + + case LFT_REQUEST_VERSION: + snprintf(tmp, sizeof(tmp), "%d.%d", (int) al->http.version.major, (int) al->http.version.minor); + out = tmp; + break; + + case LFT_REQUEST_SIZE_TOTAL: + outoff = al->cache.requestSize; + dooff = 1; + break; + + /*case LFT_REQUEST_SIZE_LINE: */ + case LFT_REQUEST_SIZE_HEADERS: + outoff = al->cache.requestHeadersSize; + dooff =1; + break; + /*case LFT_REQUEST_SIZE_BODY: */ + /*case LFT_REQUEST_SIZE_BODY_NO_TE: */ + + case LFT_REPLY_SIZE_TOTAL: + outoff = al->cache.replySize; + dooff = 1; + break; + + case LFT_REPLY_HIGHOFFSET: + outoff = al->cache.highOffset; + + dooff = 1; + + break; + + case LFT_REPLY_OBJECTSIZE: + outoff = al->cache.objectSize; + + dooff = 1; + + break; + + /*case LFT_REPLY_SIZE_LINE: */ + case LFT_REPLY_SIZE_HEADERS: + outint = al->cache.replyHeadersSize; + doint = 1; + break; + /*case LFT_REPLY_SIZE_BODY: */ + /*case LFT_REPLY_SIZE_BODY_NO_TE: */ + + case LFT_TAG: + if (al->request) + out = al->request->tag.termedBuf(); + + quote = 1; + + break; + + case LFT_IO_SIZE_TOTAL: + outint = al->cache.requestSize + al->cache.replySize; + doint = 1; + break; + + case LFT_EXT_LOG: + if (al->request) + out = al->request->extacl_log.termedBuf(); + + quote = 1; + + break; + + case LFT_SEQUENCE_NUMBER: + outoff = logfile->sequence_number; + dooff = 1; + break; + + case LFT_PERCENT: + out = "%"; + + break; + } + + if (dooff) { + snprintf(tmp, sizeof(tmp), "%0*" PRId64, fmt->zero ? (int) fmt->width : 0, outoff); + out = tmp; + + } else if (doint) { + snprintf(tmp, sizeof(tmp), "%0*ld", fmt->zero ? (int) fmt->width : 0, outint); + out = tmp; + } + + if (out && *out) { + if (quote || fmt->quote != LOG_QUOTE_NONE) { + char *newout = NULL; + int newfree = 0; + + switch (fmt->quote) { + + case LOG_QUOTE_NONE: + newout = rfc1738_escape_unescaped(out); + break; + + case LOG_QUOTE_QUOTES: + size_t out_len = static_cast(strlen(out)) * 2 + 1; + if (out_len >= sizeof(tmp)) { + newout = (char *)xmalloc(out_len); + newfree = 1; + } else + newout = tmp; + log_quoted_string(out, newout); + break; + + case LOG_QUOTE_MIMEBLOB: + newout = Log::QuoteMimeBlob(out); + newfree = 1; + break; + + case LOG_QUOTE_URL: + newout = rfc1738_escape(out); + break; + + case LOG_QUOTE_RAW: + break; + } + + if (newout) { + if (dofree) + safe_free(out); + + out = newout; + + dofree = newfree; + } + } + + if (fmt->width) { + if (fmt->left) + mb.Printf("%-*s", (int) fmt->width, out); + else + mb.Printf("%*s", (int) fmt->width, out); + } else + mb.append(out, strlen(out)); + } else { + mb.append("-", 1); + } + + if (fmt->space) + mb.append(" ", 1); + + sb.clean(); + + if (dofree) + safe_free(out); + } + + logfilePrintf(logfile, "%s\n", mb.buf); +} === added file 'src/log/FormatSquidIcap.cc' --- src/log/FormatSquidIcap.cc 1970-01-01 00:00:00 +0000 +++ src/log/FormatSquidIcap.cc 2010-11-27 11:06:38 +0000 @@ -0,0 +1,91 @@ +/* + * $Id$ + * + * DEBUG: section 46 Access Log - Squid ICAP Logging + * AUTHOR: Alex Rousskov + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "config.h" + +#if ICAP_CLIENT + +#include "AccessLogEntry.h" +#include "HttpRequest.h" +#include "log/File.h" +#include "log/Formats.h" +#include "log/Gadgets.h" +#include "SquidTime.h" + +void +Log::Format::SquidIcap(AccessLogEntry * al, Logfile * logfile) +{ + const char *client = NULL; + const char *user = NULL; + char tmp[MAX_IPSTRLEN], clientbuf[MAX_IPSTRLEN]; + + if (al->cache.caddr.IsAnyAddr()) { // ICAP OPTIONS xactions lack client + client = "-"; + } else { + if (Config.onoff.log_fqdn) + client = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS); + if (!client) + client = al->cache.caddr.NtoA(clientbuf, MAX_IPSTRLEN); + } + + user = Log::FormatName(al->cache.authuser); + + if (!user) + user = Log::FormatName(al->cache.extuser); + +#if USE_SSL + if (!user) + user = Log::FormatName(al->cache.ssluser); +#endif + + if (!user) + user = Log::FormatName(al->cache.rfc931); + + if (user && !*user) + safe_free(user); + + logfilePrintf(logfile, "%9ld.%03d %6d %s -/%03d %"PRId64" %s %s %s -/%s -\n", + (long int) current_time.tv_sec, + (int) current_time.tv_usec / 1000, + al->icap.trTime, + client, + al->icap.resStatus, + al->icap.bytesRead, + Adaptation::Icap::ICAP::methodStr(al->icap.reqMethod), + al->icap.reqUri.termedBuf(), + user ? user : "-", + al->icap.hostAddr.NtoA(tmp, MAX_IPSTRLEN)); + safe_free(user); +} +#endif === added file 'src/log/FormatSquidNative.cc' --- src/log/FormatSquidNative.cc 1970-01-01 00:00:00 +0000 +++ src/log/FormatSquidNative.cc 2010-11-21 04:52:43 +0000 @@ -0,0 +1,91 @@ +/* + * $Id$ + * + * DEBUG: section 46 Access Log - Squid format + * AUTHOR: Duane Wessels + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "config.h" +#include "AccessLogEntry.h" +#include "log/File.h" +#include "log/Formats.h" +#include "log/Gadgets.h" +#include "SquidTime.h" + +void +Log::Format::SquidNative(AccessLogEntry * al, Logfile * logfile) +{ + const char *user = NULL; + char clientip[MAX_IPSTRLEN]; + + user = FormatName(al->cache.authuser); + + if (!user) + user = FormatName(al->cache.extuser); + +#if USE_SSL + if (!user) + user = FormatName(al->cache.ssluser); +#endif + + if (!user) + user = FormatName(al->cache.rfc931); + + if (user && !*user) + safe_free(user); + + logfilePrintf(logfile, "%9ld.%03d %6d %s %s%s/%03d %"PRId64" %s %s %s %s%s/%s %s%s", + (long int) current_time.tv_sec, + (int) current_time.tv_usec / 1000, + al->cache.msec, + al->cache.caddr.NtoA(clientip, MAX_IPSTRLEN), + log_tags[al->cache.code], + al->http.statusSfx(), + al->http.code, + al->cache.replySize, + al->_private.method_str, + al->url, + user ? user : dash_str, + al->hier.ping.timedout ? "TIMEOUT_" : "", + hier_code_str[al->hier.code], + al->hier.host, + al->http.content_type, + (Config.onoff.log_mime_hdrs?"":"\n")); + + safe_free(user); + + if (Config.onoff.log_mime_hdrs) { + char *ereq = QuoteMimeBlob(al->headers.request); + char *erep = QuoteMimeBlob(al->headers.reply); + logfilePrintf(logfile, " [%s] [%s]\n", ereq, erep); + safe_free(ereq); + safe_free(erep); + } +} === renamed file 'src/referer.cc' => 'src/log/FormatSquidReferer.cc' --- src/referer.cc 2009-11-22 20:37:27 +0000 +++ src/log/FormatSquidReferer.cc 2010-11-21 04:52:43 +0000 @@ -1,9 +1,9 @@ /* * $Id$ * - * DEBUG: section 40 Referer Logging + * DEBUG: section 46 Access Log - Squid referer format * AUTHOR: Joe Ramey (useragent) - * Jens-S. Vöckler (mod 4 referer) + * Jens-S. V?ckler (mod 4 referer) * * SQUID Web Proxy Cache http://www.squid-cache.org/ * ---------------------------------------------------------- @@ -33,71 +33,26 @@ * */ -#include "squid.h" +#include "config.h" +#include "AccessLogEntry.h" +#include "HttpRequest.h" #include "log/File.h" +#include "log/Formats.h" #include "SquidTime.h" -#if USE_REFERER_LOG -static Logfile *refererlog = NULL; -#endif - -void -refererOpenLog(void) -{ -#if USE_REFERER_LOG - assert(NULL == refererlog); - - if (!Config.Log.referer || (0 == strcmp(Config.Log.referer, "none"))) { - debugs(40, 1, "Referer logging is disabled."); - return; - } - - refererlog = logfileOpen(Config.Log.referer, 0, 1); -#endif -} - -void -refererRotateLog(void) -{ -#if USE_REFERER_LOG - - if (NULL == refererlog) - return; - - logfileRotate(refererlog); - -#endif -} - -void -logReferer(const char *client, const char *referer, const char *uri) -{ -#if USE_REFERER_LOG - - if (NULL == refererlog) - return; - - logfilePrintf(refererlog, "%9d.%03d %s %s %s\n", - (int) current_time.tv_sec, +void +Log::Format::SquidReferer(AccessLogEntry *al, Logfile *logfile) +{ + const char *referer = al->request->header.getStr(HDR_REFERER); + if (!referer || *referer == '\0') + referer = "-"; + + char clientip[MAX_IPSTRLEN]; + + logfilePrintf(logfile, "%9ld.%03d %s %s %s\n", + (long int) current_time.tv_sec, (int) current_time.tv_usec / 1000, - client, + al->cache.caddr.NtoA(clientip, MAX_IPSTRLEN), referer, - uri ? uri : "-"); - -#endif -} - -void -refererCloseLog(void) -{ -#if USE_REFERER_LOG - - if (NULL == refererlog) - return; - - logfileClose(refererlog); - - refererlog = NULL; - -#endif + al->url ? al->url : "-"); } === renamed file 'src/useragent.cc' => 'src/log/FormatSquidUseragent.cc' --- src/useragent.cc 2009-11-22 20:37:27 +0000 +++ src/log/FormatSquidUseragent.cc 2010-11-21 04:52:43 +0000 @@ -1,8 +1,9 @@ /* * $Id$ * - * DEBUG: section 40 User-Agent Logging + * DEBUG: section 46 Access Log - Squid useragent format * AUTHOR: Joe Ramey + * AUTHOR: Amos Jeffries * * SQUID Web Proxy Cache http://www.squid-cache.org/ * ---------------------------------------------------------- @@ -32,77 +33,24 @@ * */ -#include "squid.h" +#include "config.h" +#include "AccessLogEntry.h" +#include "HttpRequest.h" #include "log/File.h" +#include "log/Formats.h" #include "SquidTime.h" -#if USE_USERAGENT_LOG -static Logfile *useragentlog = NULL; -#endif - -void -useragentOpenLog(void) -{ -#if USE_USERAGENT_LOG - assert(NULL == useragentlog); - - if (!Config.Log.useragent || (0 == strcmp(Config.Log.useragent, "none"))) { - debugs(40, 1, "User-Agent logging is disabled."); - return; - } - - useragentlog = logfileOpen(Config.Log.useragent, 0, 1); -#endif -} - -void -useragentRotateLog(void) -{ -#if USE_USERAGENT_LOG - - if (NULL == useragentlog) - return; - - logfileRotate(useragentlog); - -#endif -} - -void -logUserAgent(const char *client, const char *agent) -{ -#if USE_USERAGENT_LOG - static time_t last_time = 0; - static char time_str[128]; - const char *s; - - if (NULL == useragentlog) - return; - - if (squid_curtime != last_time) { - s = mkhttpdlogtime(&squid_curtime); - strcpy(time_str, s); - last_time = squid_curtime; - } - - logfilePrintf(useragentlog, "%s [%s] \"%s\"\n", - client, - time_str, +void +Log::Format::SquidUserAgent(AccessLogEntry * al, Logfile * logfile) +{ + char clientip[MAX_IPSTRLEN]; + + const char *agent = al->request->header.getStr(HDR_USER_AGENT); + if (!agent || *agent == '\0') + agent = "-"; + + logfilePrintf(logfile, "%s [%s] \"%s\"\n", + al->cache.caddr.NtoA(clientip,MAX_IPSTRLEN), + Time::FormatHttpd(squid_curtime), agent); -#endif -} - -void -useragentLogClose(void) -{ -#if USE_USERAGENT_LOG - - if (NULL == useragentlog) - return; - - logfileClose(useragentlog); - - useragentlog = NULL; - -#endif } === added file 'src/log/Formats.h' --- src/log/Formats.h 1970-01-01 00:00:00 +0000 +++ src/log/Formats.h 2010-11-21 04:52:44 +0000 @@ -0,0 +1,51 @@ +#ifndef _SQUID_LOG_FORMATS_H +#define _SQUID_LOG_FORMATS_H + +class AccessLogEntry; +class Logfile; + +namespace Log +{ + +namespace Format +{ + +typedef enum { + CLF_UNKNOWN, + CLF_COMBINED, + CLF_COMMON, + CLF_CUSTOM, +#if ICAP_CLIENT + CLF_ICAP_SQUID, +#endif + CLF_REFERER, + CLF_SQUID, + CLF_USERAGENT, + CLF_NONE +} log_type; + +/// Native Squid Format Display +void SquidNative(AccessLogEntry * al, Logfile * logfile); + +/// Display log details in Squid ICAP format. +void SquidIcap(AccessLogEntry * al, Logfile * logfile); + +/// Display log details in useragent format. +void SquidUserAgent(AccessLogEntry * al, Logfile * logfile); + +/// Display log details in Squid old refererlog format. +void SquidReferer(AccessLogEntry * al, Logfile * logfile); + +/// Log with a local custom format +void SquidCustom(AccessLogEntry * al, customlog * log); + +/// Log with Apache httpd common format +void HttpdCommon(AccessLogEntry * al, Logfile * logfile); + +/// Log with Apache httpd combined format +void HttpdCombined(AccessLogEntry * al, Logfile * logfile); + +}; // namespace Format +}; // namespace Log + +#endif /* _SQUID_LOG_FORMATS_H */ === added file 'src/log/Gadgets.cc' --- src/log/Gadgets.cc 1970-01-01 00:00:00 +0000 +++ src/log/Gadgets.cc 2010-11-21 04:52:44 +0000 @@ -0,0 +1,156 @@ +#include "config.h" +#include "log/Gadgets.h" + +static const char c2x[] = + "000102030405060708090a0b0c0d0e0f" + "101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f" + "303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f" + "505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f" + "707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f" + "909192939495969798999a9b9c9d9e9f" + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; + +#if DEAD_USING_QUOTEMIMEBLOB +/** copy of Log::QuoteMimeBlob. Bugs there will be found here. + * This omits [] characters but is otherwise identical to Log::QuoteMimeBlob when OLD_LOG_MIME = 1 + */ +static char * +username_quote(const char *header) +{ + int c; + int i; + char *buf; + char *buf_cursor; + + if (header == NULL) { + buf = static_cast(xcalloc(1, 1)); + *buf = '\0'; + return buf; + } + + buf = static_cast(xcalloc(1, (strlen(header) * 3) + 1)); + buf_cursor = buf; + /* + * We escape: space \x00-\x1F and space (0x40) and \x7F-\xFF + * to prevent garbage in the logs. CR and LF are also there just in case. + */ + + while ((c = *(const unsigned char *) header++) != '\0') { + if (c == '\r') { + *buf_cursor++ = '\\'; + *buf_cursor++ = 'r'; + } else if (c == '\n') { + *buf_cursor++ = '\\'; + *buf_cursor++ = 'n'; + } else if (c <= 0x1F + || c >= 0x7F + || c == '%' + || c == ' ') { + *buf_cursor++ = '%'; + i = c * 2; + *buf_cursor++ = c2x[i]; + *buf_cursor++ = c2x[i + 1]; + } else { + *buf_cursor++ = (char) c; + } + } + + *buf_cursor = '\0'; + return buf; +} +#endif // DEAD + +char * +Log::FormatName(const char *name) +{ + if (NULL == name) + return NULL; + + if (name[0] == '\0') + return NULL; + + return QuoteMimeBlob(name); +// return username_quote(name); +} + +char * +Log::QuoteMimeBlob(const char *header) +{ + int c; + int i; + char *buf; + char *buf_cursor; + + if (header == NULL) { + buf = static_cast(xcalloc(1, 1)); + *buf = '\0'; + return buf; + } + + buf = static_cast(xcalloc(1, (strlen(header) * 3) + 1)); + buf_cursor = buf; + /** + * Whe OLD_LOG_MIME is defined we escape: \x00-\x1F"#%;<>?{}|\\\\^~`\[\]\x7F-\xFF + * which is the default escape list for the CPAN Perl5 URI module + * modulo the inclusion of space (x40) to make the raw logs a bit + * more readable. + */ + + while ((c = *(const unsigned char *) header++) != '\0') { +#if !OLD_LOG_MIME + if (c == '\r') { + *buf_cursor++ = '\\'; + *buf_cursor++ = 'r'; + } else if (c == '\n') { + *buf_cursor++ = '\\'; + *buf_cursor++ = 'n'; + } else +#endif + if (c <= 0x1F + || c >= 0x7F + || c == '%' +#if OLD_LOG_MIME + || c == '"' + || c == '#' + || c == ';' + || c == '<' + || c == '>' + || c == '?' + || c == '{' + || c == '}' + || c == '|' + || c == '\\' + || c == '^' + || c == '~' + || c == '`' +#endif + || c == '[' + || c == ']') { + *buf_cursor++ = '%'; + i = c * 2; + *buf_cursor++ = c2x[i]; + *buf_cursor++ = c2x[i + 1]; +#if !OLD_LOG_MIME + + } else if (c == '\\') { + *buf_cursor++ = '\\'; + *buf_cursor++ = '\\'; +#endif + + } else { + *buf_cursor++ = (char) c; + } + } + + *buf_cursor = '\0'; + return buf; +} === added file 'src/log/Gadgets.h' --- src/log/Gadgets.h 1970-01-01 00:00:00 +0000 +++ src/log/Gadgets.h 2010-11-21 04:52:44 +0000 @@ -0,0 +1,19 @@ +#ifndef _SQUID_LOG_GADGETS_H +#define _SQUID_LOG_GADGETS_H + +namespace Log +{ + +/// Safely URL-encode a username. +/// Accepts NULL or empty strings. +char * FormatName(const char *name); + +/** URL-style encoding on a MIME headers blob. + * May accept NULL or empty strings. + * \return A dynamically allocated string. recipient is responsible for free()'ing + */ +char *QuoteMimeBlob(const char *header); + +}; // namespace Log + +#endif /* _SQUID_LOG_GADGETS_H */ === modified file 'src/log/Makefile.am' --- src/log/Makefile.am 2010-04-19 10:03:17 +0000 +++ src/log/Makefile.am 2010-11-21 04:52:44 +0000 @@ -9,6 +9,16 @@ Config.h \ File.cc \ File.h \ + FormatHttpdCombined.cc \ + FormatHttpdCommon.cc \ + Formats.h \ + FormatSquidCustom.cc \ + FormatSquidIcap.cc \ + FormatSquidNative.cc \ + FormatSquidReferer.cc \ + FormatSquidUseragent.cc \ + Gadgets.cc \ + Gadgets.h \ ModDaemon.cc \ ModDaemon.h \ ModStdio.cc \ @@ -18,4 +28,7 @@ ModTcp.cc \ ModTcp.h \ ModUdp.cc \ - ModUdp.h + ModUdp.h \ + Tokens.cc \ + Tokens.h + === added file 'src/log/Tokens.cc' --- src/log/Tokens.cc 1970-01-01 00:00:00 +0000 +++ src/log/Tokens.cc 2010-11-21 05:34:20 +0000 @@ -0,0 +1,690 @@ +/* + * $Id$ + * + * DEBUG: section 46 Access Log Format Tokens + * AUTHOR: Duane Wessels + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "config.h" +#include "log/Tokens.h" +#include "Store.h" + +const char *log_tags[] = { + "NONE", + "TCP_HIT", + "TCP_MISS", + "TCP_REFRESH_UNMODIFIED", + "TCP_REFRESH_FAIL", // same tag logged for LOG_TCP_REFRESH_FAIL_OLD and + "TCP_REFRESH_FAIL", // LOG_TCP_REFRESH_FAIL_ERR for backward-compatibility + "TCP_REFRESH_MODIFIED", + "TCP_CLIENT_REFRESH_MISS", + "TCP_IMS_HIT", + "TCP_SWAPFAIL_MISS", + "TCP_NEGATIVE_HIT", + "TCP_MEM_HIT", + "TCP_DENIED", + "TCP_DENIED_REPLY", + "TCP_OFFLINE_HIT", +#if LOG_TCP_REDIRECTS + "TCP_REDIRECT", +#endif + "UDP_HIT", + "UDP_MISS", + "UDP_DENIED", + "UDP_INVALID", + "UDP_MISS_NOFETCH", + "ICP_QUERY", + "LOG_TYPE_MAX" +}; + +#if USE_ADAPTATION +bool alLogformatHasAdaptToken = false; +#endif + +#if ICAP_CLIENT +bool alLogformatHasIcapToken = false; +#endif + +struct logformat_token_table_entry logformat_token_table[] = { + + {">a", LFT_CLIENT_IP_ADDRESS}, + {">p", LFT_CLIENT_PORT}, + {">A", LFT_CLIENT_FQDN}, +#if USE_SQUID_EUI + {">eui", LFT_CLIENT_EUI}, +#endif + + /*{ "ha", LFT_ADAPTED_REQUEST_HEADER}, + {">ha", LFT_ADAPTED_REQUEST_ALL_HEADERS}, + {">h", LFT_REQUEST_HEADER}, + {">h", LFT_REQUEST_ALL_HEADERS}, + {"Hs", LFT_HTTP_SENT_STATUS_CODE}, + {"v", LFT_REQUEST_VERSION}, + {"rv", LFT_REQUEST_VERSION}, + + { ">st", LFT_REQUEST_SIZE_TOTAL }, + /*{ ">sl", LFT_REQUEST_SIZE_LINE }, * / / * the request line "GET ... " */ + { ">sh", LFT_REQUEST_SIZE_HEADERS }, + /*{ ">sb", LFT_REQUEST_SIZE_BODY }, */ + /*{ ">sB", LFT_REQUEST_SIZE_BODY_NO_TE }, */ + + {"st", LFT_ICAP_BYTES_SENT}, + {"icap::h", LFT_ICAP_REQ_HEADER}, + {"icap:: 0) { + char *cp; + /* it's a string for sure, until \0 or the next % */ + cp = (char *)xmalloc(l + 1); + xstrncpy(cp, cur, l + 1); + lt->type = LFT_STRING; + lt->data.string = cp; + + while (l > 0) { + switch (*cur) { + + case '"': + + if (*quote == LOG_QUOTE_NONE) + *quote = LOG_QUOTE_QUOTES; + else if (*quote == LOG_QUOTE_QUOTES) + *quote = LOG_QUOTE_NONE; + + break; + + case '[': + if (*quote == LOG_QUOTE_NONE) + *quote = LOG_QUOTE_MIMEBLOB; + + break; + + case ']': + if (*quote == LOG_QUOTE_MIMEBLOB) + *quote = LOG_QUOTE_NONE; + + break; + } + + cur++; + l--; + } + + goto done; + } + + if (!*cur) + goto done; + + cur++; + + switch (*cur) { + + case '"': + lt->quote = LOG_QUOTE_QUOTES; + cur++; + break; + + case '\'': + lt->quote = LOG_QUOTE_RAW; + cur++; + break; + + case '[': + lt->quote = LOG_QUOTE_MIMEBLOB; + cur++; + break; + + case '#': + lt->quote = LOG_QUOTE_URL; + cur++; + break; + + default: + lt->quote = *quote; + break; + } + + if (*cur == '-') { + lt->left = 1; + cur++; + } + + if (*cur == '0') { + lt->zero = 1; + cur++; + } + + if (xisdigit(*cur)) + lt->width = strtol(cur, &cur, 10); + + if (*cur == '.') + lt->precision = strtol(cur + 1, &cur, 10); + + if (*cur == '{') { + char *cp; + cur++; + l = strcspn(cur, "}"); + cp = (char *)xmalloc(l + 1); + xstrncpy(cp, cur, l + 1); + lt->data.string = cp; + cur += l; + + if (*cur == '}') + cur++; + } + + // For upward compatibility, assume "http::" prefix as default prefix + // for all log access formating codes, except those starting + // from "icap::", "adapt::" and "%" + if (strncmp(cur,"http::", 6) == 0 && + strncmp(cur+6, "icap::", 6) != 0 && + strncmp(cur+6, "adapt::", 12) != 0 && *(cur+6) != '%' ) { + cur += 6; + } + + lt->type = LFT_NONE; + + for (lte = logformat_token_table; lte->config != NULL; lte++) { + if (strncmp(lte->config, cur, strlen(lte->config)) == 0) { + lt->type = lte->token_type; + cur += strlen(lte->config); + break; + } + } + + if (lt->type == LFT_NONE) { + fatalf("Can't parse configuration token: '%s'\n", + def); + } + + if (*cur == ' ') { + lt->space = 1; + cur++; + } + +done: + + switch (lt->type) { + +#if ICAP_CLIENT + case LFT_ICAP_LAST_MATCHED_HEADER: + + case LFT_ICAP_REQ_HEADER: + + case LFT_ICAP_REP_HEADER: +#endif + + case LFT_ADAPTED_REQUEST_HEADER: + + case LFT_REQUEST_HEADER: + + case LFT_REPLY_HEADER: + + if (lt->data.string) { + char *header = lt->data.string; + char *cp = strchr(header, ':'); + + if (cp) { + *cp++ = '\0'; + + if (*cp == ',' || *cp == ';' || *cp == ':') + lt->data.header.separator = *cp++; + else + lt->data.header.separator = ','; + + lt->data.header.element = cp; + + switch (lt->type) { + case LFT_REQUEST_HEADER: + lt->type = LFT_REQUEST_HEADER_ELEM; + break; + + case LFT_ADAPTED_REQUEST_HEADER: + lt->type = LFT_ADAPTED_REQUEST_HEADER_ELEM; + break; + + case LFT_REPLY_HEADER: + lt->type = LFT_REPLY_HEADER_ELEM; + break; +#if ICAP_CLIENT + case LFT_ICAP_LAST_MATCHED_HEADER: + lt->type = LFT_ICAP_LAST_MATCHED_HEADER_ELEM; + break; + case LFT_ICAP_REQ_HEADER: + lt->type = LFT_ICAP_REQ_HEADER_ELEM; + break; + case LFT_ICAP_REP_HEADER: + lt->type = LFT_ICAP_REP_HEADER_ELEM; + break; +#endif + default: + break; + } + } + + lt->data.header.header = header; + } else { + switch (lt->type) { + case LFT_REQUEST_HEADER: + lt->type = LFT_REQUEST_ALL_HEADERS; + break; + + case LFT_ADAPTED_REQUEST_HEADER: + lt->type = LFT_ADAPTED_REQUEST_ALL_HEADERS; + break; + + case LFT_REPLY_HEADER: + lt->type = LFT_REPLY_ALL_HEADERS; + break; +#if ICAP_CLIENT + case LFT_ICAP_LAST_MATCHED_HEADER: + lt->type = LFT_ICAP_LAST_MATCHED_ALL_HEADERS; + break; + case LFT_ICAP_REQ_HEADER: + lt->type = LFT_ICAP_REQ_ALL_HEADERS; + break; + case LFT_ICAP_REP_HEADER: + lt->type = LFT_ICAP_REP_ALL_HEADERS; + break; +#endif + default: + break; + } + Config.onoff.log_mime_hdrs = 1; + } + + break; + + case LFT_CLIENT_FQDN: + Config.onoff.log_fqdn = 1; + break; + + case LFT_TIME_SUBSECOND: + lt->divisor = 1000; + + if (lt->precision) { + int i; + lt->divisor = 1000000; + + for (i = lt->precision; i > 1; i--) + lt->divisor /= 10; + + if (!lt->divisor) + lt->divisor = 0; + } + + break; + + case LFT_HTTP_SENT_STATUS_CODE_OLD_30: + debugs(46, 0, "WARNING: the \"Hs\" formating code is deprecated use the \">Hs\" instead"); + lt->type = LFT_HTTP_SENT_STATUS_CODE; + break; + default: + break; + } + + return (cur - def); +} + +int +accessLogParseLogFormat(logformat_token ** fmt, char *def) +{ + char *cur, *eos; + logformat_token *new_lt, *last_lt; + enum log_quote quote = LOG_QUOTE_NONE; + + debugs(46, 2, "accessLogParseLogFormat: got definition '" << def << "'"); + + /* very inefficent parser, but who cares, this needs to be simple */ + /* First off, let's tokenize, we'll optimize in a second pass. + * A token can either be a %-prefixed sequence (usually a dynamic + * token but it can be an escaped sequence), or a string. */ + cur = def; + eos = def + strlen(def); + *fmt = new_lt = last_lt = (logformat_token *)xmalloc(sizeof(logformat_token)); + cur += accessLogGetNewLogFormatToken(new_lt, cur, "e); + + while (cur < eos) { + new_lt = (logformat_token *)xmalloc(sizeof(logformat_token)); + last_lt->next = new_lt; + last_lt = new_lt; + cur += accessLogGetNewLogFormatToken(new_lt, cur, "e); + } + + return 1; +} + +void +accessLogDumpLogFormat(StoreEntry * entry, const char *name, logformat * definitions) +{ + logformat_token *t; + logformat *format; + + struct logformat_token_table_entry *te; + debugs(46, 4, "accessLogDumpLogFormat called"); + + for (format = definitions; format; format = format->next) { + debugs(46, 3, "Dumping logformat definition for " << format->name); + storeAppendPrintf(entry, "logformat %s ", format->name); + + for (t = format->format; t; t = t->next) { + if (t->type == LFT_STRING) + storeAppendPrintf(entry, "%s", t->data.string); + else { + char argbuf[256]; + char *arg = NULL; + logformat_bcode_t type = t->type; + + switch (type) { + /* special cases */ + + case LFT_STRING: + break; +#if ICAP_CLIENT + case LFT_ICAP_LAST_MATCHED_HEADER_ELEM: + case LFT_ICAP_REQ_HEADER_ELEM: + case LFT_ICAP_REP_HEADER_ELEM: +#endif + case LFT_REQUEST_HEADER_ELEM: + case LFT_ADAPTED_REQUEST_HEADER_ELEM: + case LFT_REPLY_HEADER_ELEM: + + if (t->data.header.separator != ',') + snprintf(argbuf, sizeof(argbuf), "%s:%c%s", t->data.header.header, t->data.header.separator, t->data.header.element); + else + snprintf(argbuf, sizeof(argbuf), "%s:%s", t->data.header.header, t->data.header.element); + + arg = argbuf; + + switch (type) { + case LFT_REQUEST_HEADER_ELEM: + type = LFT_REQUEST_HEADER_ELEM; + break; + case LFT_ADAPTED_REQUEST_HEADER_ELEM: + type = LFT_ADAPTED_REQUEST_HEADER_ELEM; + break; + case LFT_REPLY_HEADER_ELEM: + type = LFT_REPLY_HEADER_ELEM; + break; +#if ICAP_CLIENT + case LFT_ICAP_LAST_MATCHED_HEADER_ELEM: + type = LFT_ICAP_LAST_MATCHED_HEADER; + break; + case LFT_ICAP_REQ_HEADER_ELEM: + type = LFT_ICAP_REQ_HEADER; + break; + case LFT_ICAP_REP_HEADER_ELEM: + type = LFT_ICAP_REP_HEADER; + break; +#endif + default: + break; + } + + break; + + case LFT_REQUEST_ALL_HEADERS: + case LFT_ADAPTED_REQUEST_ALL_HEADERS: + case LFT_REPLY_ALL_HEADERS: + +#if ICAP_CLIENT + case LFT_ICAP_LAST_MATCHED_ALL_HEADERS: + case LFT_ICAP_REQ_ALL_HEADERS: + case LFT_ICAP_REP_ALL_HEADERS: +#endif + + switch (type) { + case LFT_REQUEST_ALL_HEADERS: + type = LFT_REQUEST_HEADER; + break; + case LFT_ADAPTED_REQUEST_ALL_HEADERS: + type = LFT_ADAPTED_REQUEST_HEADER; + break; + case LFT_REPLY_ALL_HEADERS: + type = LFT_REPLY_HEADER; + break; +#if ICAP_CLIENT + case LFT_ICAP_LAST_MATCHED_ALL_HEADERS: + type = LFT_ICAP_LAST_MATCHED_HEADER; + break; + case LFT_ICAP_REQ_ALL_HEADERS: + type = LFT_ICAP_REQ_HEADER; + break; + case LFT_ICAP_REP_ALL_HEADERS: + type = LFT_ICAP_REP_HEADER; + break; +#endif + default: + break; + } + + break; + + default: + if (t->data.string) + arg = t->data.string; + + break; + } + + entry->append("%", 1); + + switch (t->quote) { + + case LOG_QUOTE_QUOTES: + entry->append("\"", 1); + break; + + case LOG_QUOTE_MIMEBLOB: + entry->append("[", 1); + break; + + case LOG_QUOTE_URL: + entry->append("#", 1); + break; + + case LOG_QUOTE_RAW: + entry->append("'", 1); + break; + + case LOG_QUOTE_NONE: + break; + } + + if (t->left) + entry->append("-", 1); + + if (t->zero) + entry->append("0", 1); + + if (t->width) + storeAppendPrintf(entry, "%d", (int) t->width); + + if (t->precision) + storeAppendPrintf(entry, ".%d", (int) t->precision); + + if (arg) + storeAppendPrintf(entry, "{%s}", arg); + + for (te = logformat_token_table; te->config != NULL; te++) { + if (te->token_type == type) { + storeAppendPrintf(entry, "%s", te->config); + break; + } + } + + if (t->space) + entry->append(" ", 1); + + assert(te->config != NULL); + } + } + + entry->append("\n", 1); + } + +} + +void +accessLogFreeLogFormat(logformat_token ** tokens) +{ + while (*tokens) { + logformat_token *token = *tokens; + *tokens = token->next; + safe_free(token->data.string); + xfree(token); + } +} + +logformat::logformat(const char *n) : + format(NULL), + next(NULL) +{ + name = xstrdup(n); +} + +logformat::~logformat() +{ + // erase the list without consuming stack space + while (next) { + // unlink the next entry for deletion + logformat *temp = next; + next = temp->next; + temp->next = NULL; + delete temp; + } + + // remove locals + xfree(name); + accessLogFreeLogFormat(&format); +} === added file 'src/log/Tokens.h' --- src/log/Tokens.h 1970-01-01 00:00:00 +0000 +++ src/log/Tokens.h 2010-11-21 04:52:47 +0000 @@ -0,0 +1,246 @@ +/* + * $Id$ + * + * DEBUG: section 46 Access Log + * AUTHOR: Duane Wessels + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ +#ifndef _SQUID_LOG_TOKENS_H +#define _SQUID_LOG_TOKENS_H + +class StoreEntry; + +#define LOG_BUF_SZ (MAX_URL<<2) + +/* + * Bytecodes for the configureable logformat stuff + */ +typedef enum { + LFT_NONE, /* dummy */ + LFT_STRING, + + LFT_CLIENT_IP_ADDRESS, + LFT_CLIENT_FQDN, + LFT_CLIENT_PORT, +#if USE_SQUID_EUI + LFT_CLIENT_EUI, +#endif + + /*LFT_SERVER_IP_ADDRESS, */ + LFT_SERVER_IP_OR_PEER_NAME, + /*LFT_SERVER_PORT, */ + + LFT_LOCAL_IP, + LFT_LOCAL_PORT, + /*LFT_LOCAL_NAME, */ + LFT_PEER_LOCAL_PORT, + + LFT_TIME_SECONDS_SINCE_EPOCH, + LFT_TIME_SUBSECOND, + LFT_TIME_LOCALTIME, + LFT_TIME_GMT, + LFT_TIME_TO_HANDLE_REQUEST, + + LFT_PEER_RESPONSE_TIME, + LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME, + LFT_DNS_WAIT_TIME, + + LFT_REQUEST_HEADER, + LFT_REQUEST_HEADER_ELEM, + LFT_REQUEST_ALL_HEADERS, + + LFT_ADAPTED_REQUEST_HEADER, + LFT_ADAPTED_REQUEST_HEADER_ELEM, + LFT_ADAPTED_REQUEST_ALL_HEADERS, + + LFT_REPLY_HEADER, + LFT_REPLY_HEADER_ELEM, + LFT_REPLY_ALL_HEADERS, + + LFT_USER_NAME, + LFT_USER_LOGIN, + LFT_USER_IDENT, + /*LFT_USER_REALM, */ + /*LFT_USER_SCHEME, */ + LFT_USER_EXTERNAL, + + LFT_HTTP_SENT_STATUS_CODE_OLD_30, + LFT_HTTP_SENT_STATUS_CODE, + LFT_HTTP_RECEIVED_STATUS_CODE, + /*LFT_HTTP_STATUS, */ + LFT_HTTP_BODY_BYTES_READ, + + LFT_SQUID_STATUS, + LFT_SQUID_ERROR, + LFT_SQUID_ERROR_DETAIL, + LFT_SQUID_HIERARCHY, + + LFT_MIME_TYPE, + + LFT_REQUEST_METHOD, + LFT_REQUEST_URI, + LFT_REQUEST_URLPATH, + /*LFT_REQUEST_QUERY, * // * this is not needed. see strip_query_terms */ + LFT_REQUEST_VERSION, + + LFT_REQUEST_SIZE_TOTAL, + /*LFT_REQUEST_SIZE_LINE, */ + LFT_REQUEST_SIZE_HEADERS, + /*LFT_REQUEST_SIZE_BODY, */ + /*LFT_REQUEST_SIZE_BODY_NO_TE, */ + + LFT_REPLY_SIZE_TOTAL, + LFT_REPLY_HIGHOFFSET, + LFT_REPLY_OBJECTSIZE, + /*LFT_REPLY_SIZE_LINE, */ + LFT_REPLY_SIZE_HEADERS, + /*LFT_REPLY_SIZE_BODY, */ + /*LFT_REPLY_SIZE_BODY_NO_TE, */ + + LFT_TAG, + LFT_IO_SIZE_TOTAL, + LFT_EXT_LOG, + + LFT_SEQUENCE_NUMBER, + +#if USE_ADAPTATION + LTF_ADAPTATION_SUM_XACT_TIMES, + LTF_ADAPTATION_ALL_XACT_TIMES, +#endif + +#if ICAP_CLIENT + + LFT_ICAP_TOTAL_TIME, + LFT_ICAP_LAST_MATCHED_HEADER, + LFT_ICAP_LAST_MATCHED_HEADER_ELEM, + LFT_ICAP_LAST_MATCHED_ALL_HEADERS, + + LFT_ICAP_ADDR, + LFT_ICAP_SERV_NAME, + LFT_ICAP_REQUEST_URI, + LFT_ICAP_REQUEST_METHOD, + LFT_ICAP_BYTES_SENT, + LFT_ICAP_BYTES_READ, + LFT_ICAP_BODY_BYTES_READ, + + LFT_ICAP_REQ_HEADER, + LFT_ICAP_REQ_HEADER_ELEM, + LFT_ICAP_REQ_ALL_HEADERS, + + LFT_ICAP_REP_HEADER, + LFT_ICAP_REP_HEADER_ELEM, + LFT_ICAP_REP_ALL_HEADERS, + + LFT_ICAP_TR_RESPONSE_TIME, + LFT_ICAP_IO_TIME, + LFT_ICAP_OUTCOME, + LFT_ICAP_STATUS_CODE, +#endif + + LFT_PERCENT /* special string cases for escaped chars */ +} logformat_bcode_t; + +enum log_quote { + LOG_QUOTE_NONE = 0, + LOG_QUOTE_QUOTES, + LOG_QUOTE_MIMEBLOB, + LOG_QUOTE_URL, + LOG_QUOTE_RAW +}; + +/* FIXME: public class so we can pre-define its type. */ +class logformat_token +{ +public: + logformat_bcode_t type; + union { + char *string; + + struct { + char *header; + char *element; + char separator; + } header; + char *timespec; + } data; + unsigned char width; + unsigned char precision; + enum log_quote quote; + unsigned int left:1; + unsigned int space:1; + unsigned int zero:1; + int divisor; + logformat_token *next; /* todo: move from linked list to array */ +}; + +struct logformat_token_table_entry { + const char *config; + logformat_bcode_t token_type; + int options; +}; + +class logformat +{ +public: + logformat(const char *name); + ~logformat(); + + char *name; + logformat_token *format; + logformat *next; +}; + +extern const char *log_tags[]; +extern struct logformat_token_table_entry logformat_token_table[]; + +#if USE_ADAPTATION +extern bool alLogformatHasAdaptToken; +#endif + +#if ICAP_CLIENT +extern bool alLogformatHasIcapToken; +#endif + +/* parses a single token. Returns the token length in characters, + * and fills in the lt item with the token information. + * def is for sure null-terminated + */ +int accessLogGetNewLogFormatToken(logformat_token * lt, char *def, enum log_quote *quote); + +/* very inefficent parser, but who cares, this needs to be simple */ +/* First off, let's tokenize, we'll optimize in a second pass. + * A token can either be a %-prefixed sequence (usually a dynamic + * token but it can be an escaped sequence), or a string. */ +int accessLogParseLogFormat(logformat_token ** fmt, char *def); + +void accessLogDumpLogFormat(StoreEntry * entry, const char *name, logformat * definitions); + +void accessLogFreeLogFormat(logformat_token ** tokens); + +#endif /* _SQUID_LOG_TOKENS_H */ === modified file 'src/log/access_log.cc' --- src/log/access_log.cc 2010-10-29 00:12:28 +0000 +++ src/log/access_log.cc 2010-11-21 08:38:59 +0000 @@ -51,14 +51,14 @@ #include "HttpReply.h" #include "HttpRequest.h" #include "log/File.h" +#include "log/Formats.h" +#include "log/Gadgets.h" +#include "log/Tokens.h" #include "MemBuf.h" #include "mgr/Registration.h" #include "rfc1738.h" #include "SquidTime.h" -static void accessLogSquid(AccessLogEntry * al, Logfile * logfile); -static void accessLogCommon(AccessLogEntry * al, Logfile * logfile); -static void accessLogCustom(AccessLogEntry * al, customlog * log); #if HEADERS_LOG static Logfile *headerslog = NULL; #endif @@ -70,34 +70,6 @@ static void mcast_encode(unsigned int *, size_t, const unsigned int *); #endif -const char *log_tags[] = { - "NONE", - "TCP_HIT", - "TCP_MISS", - "TCP_REFRESH_UNMODIFIED", - "TCP_REFRESH_FAIL", // same tag logged for LOG_TCP_REFRESH_FAIL_OLD and - "TCP_REFRESH_FAIL", // LOG_TCP_REFRESH_FAIL_ERR for backward-compatibility - "TCP_REFRESH_MODIFIED", - "TCP_CLIENT_REFRESH_MISS", - "TCP_IMS_HIT", - "TCP_SWAPFAIL_MISS", - "TCP_NEGATIVE_HIT", - "TCP_MEM_HIT", - "TCP_DENIED", - "TCP_DENIED_REPLY", - "TCP_OFFLINE_HIT", -#if LOG_TCP_REDIRECTS - "TCP_REDIRECT", -#endif - "UDP_HIT", - "UDP_MISS", - "UDP_DENIED", - "UDP_INVALID", - "UDP_MISS_NOFETCH", - "ICP_QUERY", - "LOG_TYPE_MAX" -}; - #if USE_FORW_VIA_DB typedef struct { @@ -118,1872 +90,6 @@ int LogfileStatus = LOG_DISABLE; -#if USE_ADAPTATION -bool alLogformatHasAdaptToken = false; -#endif - -#if ICAP_CLIENT -bool alLogformatHasIcapToken = false; -#endif - -#define LOG_BUF_SZ (MAX_URL<<2) - -static const char c2x[] = - "000102030405060708090a0b0c0d0e0f" - "101112131415161718191a1b1c1d1e1f" - "202122232425262728292a2b2c2d2e2f" - "303132333435363738393a3b3c3d3e3f" - "404142434445464748494a4b4c4d4e4f" - "505152535455565758595a5b5c5d5e5f" - "606162636465666768696a6b6c6d6e6f" - "707172737475767778797a7b7c7d7e7f" - "808182838485868788898a8b8c8d8e8f" - "909192939495969798999a9b9c9d9e9f" - "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" - "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" - "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" - "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" - "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" - "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; - -/* log_quote -- URL-style encoding on MIME headers. */ - -char * -log_quote(const char *header) -{ - int c; - int i; - char *buf; - char *buf_cursor; - - if (header == NULL) { - buf = static_cast(xcalloc(1, 1)); - *buf = '\0'; - return buf; - } - - buf = static_cast(xcalloc(1, (strlen(header) * 3) + 1)); - buf_cursor = buf; - /* - * We escape: \x00-\x1F"#%;<>?{}|\\\\^~`\[\]\x7F-\xFF - * which is the default escape list for the CPAN Perl5 URI module - * modulo the inclusion of space (x40) to make the raw logs a bit - * more readable. - */ - - while ((c = *(const unsigned char *) header++) != '\0') { -#if !OLD_LOG_MIME - - if (c == '\r') { - *buf_cursor++ = '\\'; - *buf_cursor++ = 'r'; - } else if (c == '\n') { - *buf_cursor++ = '\\'; - *buf_cursor++ = 'n'; - } else -#endif - if (c <= 0x1F - || c >= 0x7F - || c == '%' -#if OLD_LOG_MIME - || c == '"' - || c == '#' - || c == ';' - || c == '<' - || c == '>' - || c == '?' - || c == '{' - || c == '}' - || c == '|' - || c == '\\' - || c == '^' - || c == '~' - || c == '`' -#endif - || c == '[' - || c == ']') { - *buf_cursor++ = '%'; - i = c * 2; - *buf_cursor++ = c2x[i]; - *buf_cursor++ = c2x[i + 1]; -#if !OLD_LOG_MIME - - } else if (c == '\\') { - *buf_cursor++ = '\\'; - *buf_cursor++ = '\\'; -#endif - - } else { - *buf_cursor++ = (char) c; - } - } - - *buf_cursor = '\0'; - return buf; -} - -static char * -username_quote(const char *header) -/* copy of log_quote. Bugs there will be found here */ -{ - int c; - int i; - char *buf; - char *buf_cursor; - - if (header == NULL) { - buf = static_cast(xcalloc(1, 1)); - *buf = '\0'; - return buf; - } - - buf = static_cast(xcalloc(1, (strlen(header) * 3) + 1)); - buf_cursor = buf; - /* - * We escape: space \x00-\x1F and space (0x40) and \x7F-\xFF - * to prevent garbage in the logs. CR and LF are also there just in case. - */ - - while ((c = *(const unsigned char *) header++) != '\0') { - if (c == '\r') { - *buf_cursor++ = '\\'; - *buf_cursor++ = 'r'; - } else if (c == '\n') { - *buf_cursor++ = '\\'; - *buf_cursor++ = 'n'; - } else if (c <= 0x1F - || c >= 0x7F - || c == '%' - || c == ' ') { - *buf_cursor++ = '%'; - i = c * 2; - *buf_cursor++ = c2x[i]; - *buf_cursor++ = c2x[i + 1]; - } else { - *buf_cursor++ = (char) c; - } - } - - *buf_cursor = '\0'; - return buf; -} - -static char * -accessLogFormatName(const char *name) -{ - if (NULL == name) - return NULL; - - if (name[0] == '\0') - return NULL; - - return username_quote(name); -} - -static char * -log_quoted_string(const char *str) -{ - char *out = (char *)xmalloc(strlen(str) * 2 + 1); - char *p = out; - - while (*str) { - int l = strcspn(str, "\"\\\r\n\t"); - memcpy(p, str, l); - str += l; - p += l; - - switch (*str) { - - case '\0': - break; - - case '\r': - *p++ = '\\'; - *p++ = 'r'; - str++; - break; - - case '\n': - *p++ = '\\'; - *p++ = 'n'; - str++; - break; - - case '\t': - *p++ = '\\'; - *p++ = 't'; - str++; - break; - - default: - *p++ = '\\'; - *p++ = *str; - str++; - break; - } - } - - *p++ = '\0'; - return out; -} - -/* - * Bytecodes for the configureable logformat stuff - */ -typedef enum { - LFT_NONE, /* dummy */ - LFT_STRING, - - LFT_CLIENT_IP_ADDRESS, - LFT_CLIENT_FQDN, - LFT_CLIENT_PORT, -#if USE_SQUID_EUI - LFT_CLIENT_EUI, -#endif - - /*LFT_SERVER_IP_ADDRESS, */ - LFT_SERVER_IP_OR_PEER_NAME, - /*LFT_SERVER_PORT, */ - - LFT_LOCAL_IP, - LFT_LOCAL_PORT, - /*LFT_LOCAL_NAME, */ - LFT_PEER_LOCAL_PORT, - - LFT_TIME_SECONDS_SINCE_EPOCH, - LFT_TIME_SUBSECOND, - LFT_TIME_LOCALTIME, - LFT_TIME_GMT, - LFT_TIME_TO_HANDLE_REQUEST, - - LFT_PEER_RESPONSE_TIME, - LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME, - LFT_DNS_WAIT_TIME, - - LFT_REQUEST_HEADER, - LFT_REQUEST_HEADER_ELEM, - LFT_REQUEST_ALL_HEADERS, - - LFT_ADAPTED_REQUEST_HEADER, - LFT_ADAPTED_REQUEST_HEADER_ELEM, - LFT_ADAPTED_REQUEST_ALL_HEADERS, - - LFT_REPLY_HEADER, - LFT_REPLY_HEADER_ELEM, - LFT_REPLY_ALL_HEADERS, - - LFT_USER_NAME, - LFT_USER_LOGIN, - LFT_USER_IDENT, - /*LFT_USER_REALM, */ - /*LFT_USER_SCHEME, */ - LFT_USER_EXTERNAL, - - LFT_HTTP_SENT_STATUS_CODE_OLD_30, - LFT_HTTP_SENT_STATUS_CODE, - LFT_HTTP_RECEIVED_STATUS_CODE, - /*LFT_HTTP_STATUS, */ - LFT_HTTP_BODY_BYTES_READ, - - LFT_SQUID_STATUS, - LFT_SQUID_ERROR, - LFT_SQUID_ERROR_DETAIL, - LFT_SQUID_HIERARCHY, - - LFT_MIME_TYPE, - - LFT_REQUEST_METHOD, - LFT_REQUEST_URI, - LFT_REQUEST_URLPATH, - /*LFT_REQUEST_QUERY, * // * this is not needed. see strip_query_terms */ - LFT_REQUEST_VERSION, - - LFT_REQUEST_SIZE_TOTAL, - /*LFT_REQUEST_SIZE_LINE, */ - LFT_REQUEST_SIZE_HEADERS, - /*LFT_REQUEST_SIZE_BODY, */ - /*LFT_REQUEST_SIZE_BODY_NO_TE, */ - - LFT_REPLY_SIZE_TOTAL, - LFT_REPLY_HIGHOFFSET, - LFT_REPLY_OBJECTSIZE, - /*LFT_REPLY_SIZE_LINE, */ - LFT_REPLY_SIZE_HEADERS, - /*LFT_REPLY_SIZE_BODY, */ - /*LFT_REPLY_SIZE_BODY_NO_TE, */ - - LFT_TAG, - LFT_IO_SIZE_TOTAL, - LFT_EXT_LOG, - - LFT_SEQUENCE_NUMBER, - -#if USE_ADAPTATION - LTF_ADAPTATION_SUM_XACT_TIMES, - LTF_ADAPTATION_ALL_XACT_TIMES, -#endif - -#if ICAP_CLIENT - - LFT_ICAP_TOTAL_TIME, - LFT_ICAP_LAST_MATCHED_HEADER, - LFT_ICAP_LAST_MATCHED_HEADER_ELEM, - LFT_ICAP_LAST_MATCHED_ALL_HEADERS, - - LFT_ICAP_ADDR, - LFT_ICAP_SERV_NAME, - LFT_ICAP_REQUEST_URI, - LFT_ICAP_REQUEST_METHOD, - LFT_ICAP_BYTES_SENT, - LFT_ICAP_BYTES_READ, - LFT_ICAP_BODY_BYTES_READ, - - LFT_ICAP_REQ_HEADER, - LFT_ICAP_REQ_HEADER_ELEM, - LFT_ICAP_REQ_ALL_HEADERS, - - LFT_ICAP_REP_HEADER, - LFT_ICAP_REP_HEADER_ELEM, - LFT_ICAP_REP_ALL_HEADERS, - - LFT_ICAP_TR_RESPONSE_TIME, - LFT_ICAP_IO_TIME, - LFT_ICAP_OUTCOME, - LFT_ICAP_STATUS_CODE, -#endif - - LFT_PERCENT /* special string cases for escaped chars */ -} logformat_bcode_t; - -enum log_quote { - LOG_QUOTE_NONE = 0, - LOG_QUOTE_QUOTES, - LOG_QUOTE_BRAKETS, - LOG_QUOTE_URL, - LOG_QUOTE_RAW -}; - -/* FIXME: public class so we can pre-define its type. */ -class logformat_token -{ -public: - logformat_bcode_t type; - union { - char *string; - - struct { - char *header; - char *element; - char separator; - } header; - char *timespec; - } data; - unsigned char width; - unsigned char precision; - enum log_quote quote; - unsigned int left:1; - unsigned int space:1; - unsigned int zero:1; - int divisor; - logformat_token *next; /* todo: move from linked list to array */ -}; - -struct logformat_token_table_entry { - const char *config; - logformat_bcode_t token_type; - int options; -}; - -struct logformat_token_table_entry logformat_token_table[] = { - - {">a", LFT_CLIENT_IP_ADDRESS}, - {">p", LFT_CLIENT_PORT}, - {">A", LFT_CLIENT_FQDN}, -#if USE_SQUID_EUI - {">eui", LFT_CLIENT_EUI}, -#endif - - /*{ "ha", LFT_ADAPTED_REQUEST_HEADER}, - {">ha", LFT_ADAPTED_REQUEST_ALL_HEADERS}, - {">h", LFT_REQUEST_HEADER}, - {">h", LFT_REQUEST_ALL_HEADERS}, - {"Hs", LFT_HTTP_SENT_STATUS_CODE}, - {"v", LFT_REQUEST_VERSION}, - {"rv", LFT_REQUEST_VERSION}, - - { ">st", LFT_REQUEST_SIZE_TOTAL }, - /*{ ">sl", LFT_REQUEST_SIZE_LINE }, * / / * the request line "GET ... " */ - { ">sh", LFT_REQUEST_SIZE_HEADERS }, - /*{ ">sb", LFT_REQUEST_SIZE_BODY }, */ - /*{ ">sB", LFT_REQUEST_SIZE_BODY_NO_TE }, */ - - {"st", LFT_ICAP_BYTES_SENT}, - {"icap::h", LFT_ICAP_REQ_HEADER}, - {"icap::logFormat; - logfile = log->logfile; - - for (fmt = lf->format; fmt != NULL; fmt = fmt->next) { /* for each token */ - const char *out = NULL; - int quote = 0; - long int outint = 0; - int doint = 0; - int dofree = 0; - int64_t outoff = 0; - int dooff = 0; - - switch (fmt->type) { - - case LFT_NONE: - out = ""; - break; - - case LFT_STRING: - out = fmt->data.string; - break; - - case LFT_CLIENT_IP_ADDRESS: - if (al->cache.caddr.IsNoAddr()) // e.g., ICAP OPTIONS lack client - out = "-"; - else - out = al->cache.caddr.NtoA(tmp,1024); - break; - - case LFT_CLIENT_FQDN: - if (al->cache.caddr.IsAnyAddr()) // e.g., ICAP OPTIONS lack client - out = "-"; - else - out = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS); - if (!out) { - out = al->cache.caddr.NtoA(tmp,1024); - } - - break; - - case LFT_CLIENT_PORT: - if (al->request) { - outint = al->request->client_addr.GetPort(); - doint = 1; - } - break; - -#if USE_SQUID_EUI - case LFT_CLIENT_EUI: - if (al->request) { - if (al->cache.caddr.IsIPv4()) - al->request->client_eui48.encode(tmp, 1024); - else - al->request->client_eui64.encode(tmp, 1024); - out = tmp; - } - break; -#endif - - /* case LFT_SERVER_IP_ADDRESS: */ - - case LFT_SERVER_IP_OR_PEER_NAME: - out = al->hier.host; - - break; - - /* case LFT_SERVER_PORT: */ - - case LFT_LOCAL_IP: - if (al->request) { - out = al->request->my_addr.NtoA(tmp,1024); - } - - break; - - case LFT_LOCAL_PORT: - if (al->request) { - outint = al->request->my_addr.GetPort(); - doint = 1; - } - - break; - - case LFT_PEER_LOCAL_PORT: - if (al->hier.peer_local_port) { - outint = al->hier.peer_local_port; - doint = 1; - } - - break; - - case LFT_TIME_SECONDS_SINCE_EPOCH: - // some platforms store time in 32-bit, some 64-bit... - outoff = static_cast(current_time.tv_sec); - dooff = 1; - break; - - case LFT_TIME_SUBSECOND: - outint = current_time.tv_usec / fmt->divisor; - doint = 1; - break; - - - case LFT_TIME_LOCALTIME: - - case LFT_TIME_GMT: { - const char *spec; - - struct tm *t; - spec = fmt->data.timespec; - - if (fmt->type == LFT_TIME_LOCALTIME) { - if (!spec) - spec = "%d/%b/%Y:%H:%M:%S %z"; - t = localtime(&squid_curtime); - } else { - if (!spec) - spec = "%d/%b/%Y:%H:%M:%S"; - - t = gmtime(&squid_curtime); - } - - strftime(tmp, sizeof(tmp), spec, t); - - out = tmp; - } - - break; - - case LFT_TIME_TO_HANDLE_REQUEST: - outint = al->cache.msec; - doint = 1; - break; - - case LFT_PEER_RESPONSE_TIME: - if (al->hier.peer_response_time < 0) { - out = "-"; - } else { - outoff = al->hier.peer_response_time; - dooff = 1; - } - break; - - case LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME: - if (al->hier.total_response_time < 0) { - out = "-"; - } else { - outoff = al->hier.total_response_time; - dooff = 1; - } - break; - - case LFT_DNS_WAIT_TIME: - if (al->request && al->request->dnsWait >= 0) { - outint = al->request->dnsWait; - doint = 1; - } - break; - - case LFT_REQUEST_HEADER: - - if (al->request) - sb = al->request->header.getByName(fmt->data.header.header); - - out = sb.termedBuf(); - - quote = 1; - - break; - - case LFT_ADAPTED_REQUEST_HEADER: - - if (al->request) - sb = al->adapted_request->header.getByName(fmt->data.header.header); - - out = sb.termedBuf(); - - quote = 1; - - break; - - case LFT_REPLY_HEADER: - if (al->reply) - sb = al->reply->header.getByName(fmt->data.header.header); - - out = sb.termedBuf(); - - quote = 1; - - break; - -#if USE_ADAPTATION - case LTF_ADAPTATION_SUM_XACT_TIMES: - if (al->request) { - Adaptation::History::Pointer ah = al->request->adaptHistory(); - if (ah != NULL) - ah->sumLogString(fmt->data.string, sb); - out = sb.termedBuf(); - } - break; - - case LTF_ADAPTATION_ALL_XACT_TIMES: - if (al->request) { - Adaptation::History::Pointer ah = al->request->adaptHistory(); - if (ah != NULL) - ah->allLogString(fmt->data.string, sb); - out = sb.termedBuf(); - } - break; -#endif - -#if ICAP_CLIENT - case LFT_ICAP_LAST_MATCHED_HEADER: - if (al->request) { - Adaptation::Icap::History::Pointer ih = al->request->icapHistory(); - if (ih != NULL) - sb = ih->mergeOfIcapHeaders.getByName(fmt->data.header.header); - } - - out = sb.termedBuf(); - - quote = 1; - - break; - - case LFT_ICAP_LAST_MATCHED_HEADER_ELEM: - if (al->request) { - Adaptation::Icap::History::Pointer ih = al->request->icapHistory(); - if (ih != NULL) - sb = ih->mergeOfIcapHeaders.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator); - } - - out = sb.termedBuf(); - - quote = 1; - - break; - - case LFT_ICAP_LAST_MATCHED_ALL_HEADERS: - out = al->headers.icap; - - quote = 1; - - break; - - case LFT_ICAP_ADDR: - if (!out) - out = al->icap.hostAddr.NtoA(tmp,1024); - break; - - case LFT_ICAP_SERV_NAME: - out = al->icap.serviceName.termedBuf(); - break; - - case LFT_ICAP_REQUEST_URI: - out = al->icap.reqUri.termedBuf(); - break; - - case LFT_ICAP_REQUEST_METHOD: - out = Adaptation::Icap::ICAP::methodStr(al->icap.reqMethod); - break; - - case LFT_ICAP_BYTES_SENT: - outoff = al->icap.bytesSent; - dooff = 1; - break; - - case LFT_ICAP_BYTES_READ: - outoff = al->icap.bytesRead; - dooff = 1; - break; - - case LFT_ICAP_BODY_BYTES_READ: - if (al->icap.bodyBytesRead >= 0) { - outoff = al->icap.bodyBytesRead; - dooff = 1; - } - // else if icap.bodyBytesRead < 0, we do not have any http data, - // so just print a "-" (204 responses etc) - break; - - case LFT_ICAP_REQ_HEADER: - if (NULL != al->icap.request) { - sb = al->icap.request->header.getByName(fmt->data.header.header); - out = sb.termedBuf(); - quote = 1; - } - break; - - case LFT_ICAP_REQ_HEADER_ELEM: - if (al->request) - sb = al->icap.request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator); - - out = sb.termedBuf(); - - quote = 1; - - break; - - case LFT_ICAP_REQ_ALL_HEADERS: - if (al->icap.request) { - HttpHeaderPos pos = HttpHeaderInitPos; - while (const HttpHeaderEntry *e = al->icap.request->header.getEntry(&pos)) { - sb.append(e->name); - sb.append(": "); - sb.append(e->value); - sb.append("\r\n"); - } - out = sb.termedBuf(); - quote = 1; - } - break; - - case LFT_ICAP_REP_HEADER: - if (NULL != al->icap.reply) { - sb = al->icap.reply->header.getByName(fmt->data.header.header); - out = sb.termedBuf(); - quote = 1; - } - break; - - case LFT_ICAP_REP_HEADER_ELEM: - if (NULL != al->icap.reply) - sb = al->icap.reply->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator); - - out = sb.termedBuf(); - - quote = 1; - - break; - - case LFT_ICAP_REP_ALL_HEADERS: - if (al->icap.reply) { - HttpHeaderPos pos = HttpHeaderInitPos; - while (const HttpHeaderEntry *e = al->icap.reply->header.getEntry(&pos)) { - sb.append(e->name); - sb.append(": "); - sb.append(e->value); - sb.append("\r\n"); - } - out = sb.termedBuf(); - quote = 1; - } - break; - - case LFT_ICAP_TR_RESPONSE_TIME: - outint = al->icap.trTime; - doint = 1; - break; - - case LFT_ICAP_IO_TIME: - outint = al->icap.ioTime; - doint = 1; - break; - - case LFT_ICAP_STATUS_CODE: - outint = al->icap.resStatus; - doint = 1; - break; - - case LFT_ICAP_OUTCOME: - out = al->icap.outcome; - break; - - case LFT_ICAP_TOTAL_TIME: - outint = al->icap.processingTime; - doint = 1; - break; -#endif - case LFT_REQUEST_HEADER_ELEM: - if (al->request) - sb = al->request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator); - - out = sb.termedBuf(); - - quote = 1; - - break; - - case LFT_ADAPTED_REQUEST_HEADER_ELEM: - if (al->adapted_request) - sb = al->adapted_request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator); - - out = sb.termedBuf(); - - quote = 1; - - break; - - case LFT_REPLY_HEADER_ELEM: - if (al->reply) - sb = al->reply->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator); - - out = sb.termedBuf(); - - quote = 1; - - break; - - case LFT_REQUEST_ALL_HEADERS: - out = al->headers.request; - - quote = 1; - - break; - - case LFT_ADAPTED_REQUEST_ALL_HEADERS: - out = al->headers.adapted_request; - - quote = 1; - - break; - - case LFT_REPLY_ALL_HEADERS: - out = al->headers.reply; - - quote = 1; - - break; - - case LFT_USER_NAME: - out = accessLogFormatName(al->cache.authuser); - - if (!out) - out = accessLogFormatName(al->cache.extuser); - -#if USE_SSL - - if (!out) - out = accessLogFormatName(al->cache.ssluser); - -#endif - - if (!out) - out = accessLogFormatName(al->cache.rfc931); - - dofree = 1; - - break; - - case LFT_USER_LOGIN: - out = accessLogFormatName(al->cache.authuser); - - dofree = 1; - - break; - - case LFT_USER_IDENT: - out = accessLogFormatName(al->cache.rfc931); - - dofree = 1; - - break; - - case LFT_USER_EXTERNAL: - out = accessLogFormatName(al->cache.extuser); - - dofree = 1; - - break; - - /* case LFT_USER_REALM: */ - /* case LFT_USER_SCHEME: */ - - // the fmt->type can not be LFT_HTTP_SENT_STATUS_CODE_OLD_30 - // but compiler complains if ommited - case LFT_HTTP_SENT_STATUS_CODE_OLD_30: - case LFT_HTTP_SENT_STATUS_CODE: - outint = al->http.code; - - doint = 1; - - break; - - case LFT_HTTP_RECEIVED_STATUS_CODE: - if (al->hier.peer_reply_status == HTTP_STATUS_NONE) { - out = "-"; - } else { - outint = al->hier.peer_reply_status; - doint = 1; - } - break; - /* case LFT_HTTP_STATUS: - * out = statusline->text; - * quote = 1; - * break; - */ - case LFT_HTTP_BODY_BYTES_READ: - if (al->hier.bodyBytesRead >= 0) { - outoff = al->hier.bodyBytesRead; - dooff = 1; - } - // else if hier.bodyBytesRead < 0 we did not have any data exchange with - // a peer server so just print a "-" (eg requests served from cache, - // or internal error messages). - break; - - case LFT_SQUID_STATUS: - if (al->http.timedout || al->http.aborted) { - snprintf(tmp, sizeof(tmp), "%s%s", log_tags[al->cache.code], - al->http.statusSfx()); - out = tmp; - } else { - out = log_tags[al->cache.code]; - } - - break; - - case LFT_SQUID_ERROR: - if (al->request && al->request->errType != ERR_NONE) - out = errorPageName(al->request->errType); - break; - - case LFT_SQUID_ERROR_DETAIL: - if (al->request && al->request->errDetail != ERR_DETAIL_NONE) { - if (al->request->errDetail > ERR_DETAIL_START && - al->request->errDetail < ERR_DETAIL_MAX) - out = errorDetailName(al->request->errDetail); - else { - if (al->request->errDetail >= ERR_DETAIL_EXCEPTION_START) - snprintf(tmp, sizeof(tmp), "%s=0x%X", - errorDetailName(al->request->errDetail), (uint32_t) al->request->errDetail); - else - snprintf(tmp, sizeof(tmp), "%s=%d", - errorDetailName(al->request->errDetail), al->request->errDetail); - out = tmp; - } - } - break; - - case LFT_SQUID_HIERARCHY: - if (al->hier.ping.timedout) - mb.append("TIMEOUT_", 8); - - out = hier_code_str[al->hier.code]; - - break; - - case LFT_MIME_TYPE: - out = al->http.content_type; - - break; - - case LFT_REQUEST_METHOD: - out = al->_private.method_str; - - break; - - case LFT_REQUEST_URI: - out = al->url; - - break; - - case LFT_REQUEST_URLPATH: - if (al->request) { - out = al->request->urlpath.termedBuf(); - quote = 1; - } - break; - - case LFT_REQUEST_VERSION: - snprintf(tmp, sizeof(tmp), "%d.%d", (int) al->http.version.major, (int) al->http.version.minor); - out = tmp; - break; - - case LFT_REQUEST_SIZE_TOTAL: - outoff = al->cache.requestSize; - dooff = 1; - break; - - /*case LFT_REQUEST_SIZE_LINE: */ - case LFT_REQUEST_SIZE_HEADERS: - outoff = al->cache.requestHeadersSize; - dooff =1; - break; - /*case LFT_REQUEST_SIZE_BODY: */ - /*case LFT_REQUEST_SIZE_BODY_NO_TE: */ - - case LFT_REPLY_SIZE_TOTAL: - outoff = al->cache.replySize; - dooff = 1; - break; - - case LFT_REPLY_HIGHOFFSET: - outoff = al->cache.highOffset; - - dooff = 1; - - break; - - case LFT_REPLY_OBJECTSIZE: - outoff = al->cache.objectSize; - - dooff = 1; - - break; - - /*case LFT_REPLY_SIZE_LINE: */ - case LFT_REPLY_SIZE_HEADERS: - outint = al->cache.replyHeadersSize; - doint = 1; - break; - /*case LFT_REPLY_SIZE_BODY: */ - /*case LFT_REPLY_SIZE_BODY_NO_TE: */ - - case LFT_TAG: - if (al->request) - out = al->request->tag.termedBuf(); - - quote = 1; - - break; - - case LFT_IO_SIZE_TOTAL: - outint = al->cache.requestSize + al->cache.replySize; - doint = 1; - break; - - case LFT_EXT_LOG: - if (al->request) - out = al->request->extacl_log.termedBuf(); - - quote = 1; - - break; - - case LFT_SEQUENCE_NUMBER: - outoff = logfile->sequence_number; - dooff = 1; - break; - - case LFT_PERCENT: - out = "%"; - - break; - } - - if (dooff) { - snprintf(tmp, sizeof(tmp), "%0*" PRId64, fmt->zero ? (int) fmt->width : 0, outoff); - out = tmp; - - } else if (doint) { - snprintf(tmp, sizeof(tmp), "%0*ld", fmt->zero ? (int) fmt->width : 0, outint); - out = tmp; - } - - if (out && *out) { - if (quote || fmt->quote != LOG_QUOTE_NONE) { - char *newout = NULL; - int newfree = 0; - - switch (fmt->quote) { - - case LOG_QUOTE_NONE: - newout = rfc1738_escape_unescaped(out); - break; - - case LOG_QUOTE_QUOTES: - newout = log_quoted_string(out); - newfree = 1; - break; - - case LOG_QUOTE_BRAKETS: - newout = log_quote(out); - newfree = 1; - break; - - case LOG_QUOTE_URL: - newout = rfc1738_escape(out); - break; - - case LOG_QUOTE_RAW: - break; - } - - if (newout) { - if (dofree) - safe_free(out); - - out = newout; - - dofree = newfree; - } - } - - if (fmt->width) { - if (fmt->left) - mb.Printf("%-*s", (int) fmt->width, out); - else - mb.Printf("%*s", (int) fmt->width, out); - } else - mb.append(out, strlen(out)); - } else { - mb.append("-", 1); - } - - if (fmt->space) - mb.append(" ", 1); - - sb.clean(); - - if (dofree) - safe_free(out); - } - - logfilePrintf(logfile, "%s\n", mb.buf); -} - -/* parses a single token. Returns the token length in characters, - * and fills in the lt item with the token information. - * def is for sure null-terminated - */ -static int -accessLogGetNewLogFormatToken(logformat_token * lt, char *def, enum log_quote *quote) -{ - char *cur = def; - - struct logformat_token_table_entry *lte; - int l; - - memset(lt, 0, sizeof(*lt)); - l = strcspn(cur, "%"); - - if (l > 0) { - char *cp; - /* it's a string for sure, until \0 or the next % */ - cp = (char *)xmalloc(l + 1); - xstrncpy(cp, cur, l + 1); - lt->type = LFT_STRING; - lt->data.string = cp; - - while (l > 0) { - switch (*cur) { - - case '"': - - if (*quote == LOG_QUOTE_NONE) - *quote = LOG_QUOTE_QUOTES; - else if (*quote == LOG_QUOTE_QUOTES) - *quote = LOG_QUOTE_NONE; - - break; - - case '[': - if (*quote == LOG_QUOTE_NONE) - *quote = LOG_QUOTE_BRAKETS; - - break; - - case ']': - if (*quote == LOG_QUOTE_BRAKETS) - *quote = LOG_QUOTE_NONE; - - break; - } - - cur++; - l--; - } - - goto done; - } - - if (!*cur) - goto done; - - cur++; - - switch (*cur) { - - case '"': - lt->quote = LOG_QUOTE_QUOTES; - cur++; - break; - - case '\'': - lt->quote = LOG_QUOTE_RAW; - cur++; - break; - - case '[': - lt->quote = LOG_QUOTE_BRAKETS; - cur++; - break; - - case '#': - lt->quote = LOG_QUOTE_URL; - cur++; - break; - - default: - lt->quote = *quote; - break; - } - - if (*cur == '-') { - lt->left = 1; - cur++; - } - - if (*cur == '0') { - lt->zero = 1; - cur++; - } - - if (xisdigit(*cur)) - lt->width = strtol(cur, &cur, 10); - - if (*cur == '.') - lt->precision = strtol(cur + 1, &cur, 10); - - if (*cur == '{') { - char *cp; - cur++; - l = strcspn(cur, "}"); - cp = (char *)xmalloc(l + 1); - xstrncpy(cp, cur, l + 1); - lt->data.string = cp; - cur += l; - - if (*cur == '}') - cur++; - } - - // For upward compatibility, assume "http::" prefix as default prefix - // for all log access formating codes, except those starting - // from "icap::", "adapt::" and "%" - if (strncmp(cur,"http::", 6) == 0 && - strncmp(cur+6, "icap::", 6) != 0 && - strncmp(cur+6, "adapt::", 12) != 0 && *(cur+6) != '%' ) { - cur += 6; - } - - lt->type = LFT_NONE; - - for (lte = logformat_token_table; lte->config != NULL; lte++) { - if (strncmp(lte->config, cur, strlen(lte->config)) == 0) { - lt->type = lte->token_type; - cur += strlen(lte->config); - break; - } - } - - if (lt->type == LFT_NONE) { - fatalf("Can't parse configuration token: '%s'\n", - def); - } - - if (*cur == ' ') { - lt->space = 1; - cur++; - } - -done: - - switch (lt->type) { - -#if ICAP_CLIENT - case LFT_ICAP_LAST_MATCHED_HEADER: - - case LFT_ICAP_REQ_HEADER: - - case LFT_ICAP_REP_HEADER: -#endif - - case LFT_ADAPTED_REQUEST_HEADER: - - case LFT_REQUEST_HEADER: - - case LFT_REPLY_HEADER: - - if (lt->data.string) { - char *header = lt->data.string; - char *cp = strchr(header, ':'); - - if (cp) { - *cp++ = '\0'; - - if (*cp == ',' || *cp == ';' || *cp == ':') - lt->data.header.separator = *cp++; - else - lt->data.header.separator = ','; - - lt->data.header.element = cp; - - switch (lt->type) { - case LFT_REQUEST_HEADER: - lt->type = LFT_REQUEST_HEADER_ELEM; - break; - - case LFT_ADAPTED_REQUEST_HEADER: - lt->type = LFT_ADAPTED_REQUEST_HEADER_ELEM; - break; - - case LFT_REPLY_HEADER: - lt->type = LFT_REPLY_HEADER_ELEM; - break; -#if ICAP_CLIENT - case LFT_ICAP_LAST_MATCHED_HEADER: - lt->type = LFT_ICAP_LAST_MATCHED_HEADER_ELEM; - break; - case LFT_ICAP_REQ_HEADER: - lt->type = LFT_ICAP_REQ_HEADER_ELEM; - break; - case LFT_ICAP_REP_HEADER: - lt->type = LFT_ICAP_REP_HEADER_ELEM; - break; -#endif - default: - break; - } - } - - lt->data.header.header = header; - } else { - switch (lt->type) { - case LFT_REQUEST_HEADER: - lt->type = LFT_REQUEST_ALL_HEADERS; - break; - - case LFT_ADAPTED_REQUEST_HEADER: - lt->type = LFT_ADAPTED_REQUEST_ALL_HEADERS; - break; - - case LFT_REPLY_HEADER: - lt->type = LFT_REPLY_ALL_HEADERS; - break; -#if ICAP_CLIENT - case LFT_ICAP_LAST_MATCHED_HEADER: - lt->type = LFT_ICAP_LAST_MATCHED_ALL_HEADERS; - break; - case LFT_ICAP_REQ_HEADER: - lt->type = LFT_ICAP_REQ_ALL_HEADERS; - break; - case LFT_ICAP_REP_HEADER: - lt->type = LFT_ICAP_REP_ALL_HEADERS; - break; -#endif - default: - break; - } - Config.onoff.log_mime_hdrs = 1; - } - - break; - - case LFT_CLIENT_FQDN: - Config.onoff.log_fqdn = 1; - break; - - case LFT_TIME_SUBSECOND: - lt->divisor = 1000; - - if (lt->precision) { - int i; - lt->divisor = 1000000; - - for (i = lt->precision; i > 1; i--) - lt->divisor /= 10; - - if (!lt->divisor) - lt->divisor = 0; - } - - break; - - case LFT_HTTP_SENT_STATUS_CODE_OLD_30: - debugs(46, 0, "WARNING: the \"Hs\" formating code is deprecated use the \">Hs\" instead"); - lt->type = LFT_HTTP_SENT_STATUS_CODE; - break; - default: - break; - } - - return (cur - def); -} - -int -accessLogParseLogFormat(logformat_token ** fmt, char *def) -{ - char *cur, *eos; - logformat_token *new_lt, *last_lt; - enum log_quote quote = LOG_QUOTE_NONE; - - debugs(46, 2, "accessLogParseLogFormat: got definition '" << def << "'"); - - /* very inefficent parser, but who cares, this needs to be simple */ - /* First off, let's tokenize, we'll optimize in a second pass. - * A token can either be a %-prefixed sequence (usually a dynamic - * token but it can be an escaped sequence), or a string. */ - cur = def; - eos = def + strlen(def); - *fmt = new_lt = last_lt = (logformat_token *)xmalloc(sizeof(logformat_token)); - cur += accessLogGetNewLogFormatToken(new_lt, cur, "e); - - while (cur < eos) { - new_lt = (logformat_token *)xmalloc(sizeof(logformat_token)); - last_lt->next = new_lt; - last_lt = new_lt; - cur += accessLogGetNewLogFormatToken(new_lt, cur, "e); - } - - return 1; -} - -void -accessLogDumpLogFormat(StoreEntry * entry, const char *name, logformat * definitions) -{ - logformat_token *t; - logformat *format; - - struct logformat_token_table_entry *te; - debugs(46, 4, "accessLogDumpLogFormat called"); - - for (format = definitions; format; format = format->next) { - debugs(46, 3, "Dumping logformat definition for " << format->name); - storeAppendPrintf(entry, "logformat %s ", format->name); - - for (t = format->format; t; t = t->next) { - if (t->type == LFT_STRING) - storeAppendPrintf(entry, "%s", t->data.string); - else { - char argbuf[256]; - char *arg = NULL; - logformat_bcode_t type = t->type; - - switch (type) { - /* special cases */ - - case LFT_STRING: - break; -#if ICAP_CLIENT - case LFT_ICAP_LAST_MATCHED_HEADER_ELEM: - case LFT_ICAP_REQ_HEADER_ELEM: - case LFT_ICAP_REP_HEADER_ELEM: -#endif - case LFT_REQUEST_HEADER_ELEM: - case LFT_ADAPTED_REQUEST_HEADER_ELEM: - case LFT_REPLY_HEADER_ELEM: - - if (t->data.header.separator != ',') - snprintf(argbuf, sizeof(argbuf), "%s:%c%s", t->data.header.header, t->data.header.separator, t->data.header.element); - else - snprintf(argbuf, sizeof(argbuf), "%s:%s", t->data.header.header, t->data.header.element); - - arg = argbuf; - - switch (type) { - case LFT_REQUEST_HEADER_ELEM: - type = LFT_REQUEST_HEADER_ELEM; - break; - case LFT_ADAPTED_REQUEST_HEADER_ELEM: - type = LFT_ADAPTED_REQUEST_HEADER_ELEM; - break; - case LFT_REPLY_HEADER_ELEM: - type = LFT_REPLY_HEADER_ELEM; - break; -#if ICAP_CLIENT - case LFT_ICAP_LAST_MATCHED_HEADER_ELEM: - type = LFT_ICAP_LAST_MATCHED_HEADER; - break; - case LFT_ICAP_REQ_HEADER_ELEM: - type = LFT_ICAP_REQ_HEADER; - break; - case LFT_ICAP_REP_HEADER_ELEM: - type = LFT_ICAP_REP_HEADER; - break; -#endif - default: - break; - } - - break; - - case LFT_REQUEST_ALL_HEADERS: - case LFT_ADAPTED_REQUEST_ALL_HEADERS: - case LFT_REPLY_ALL_HEADERS: - -#if ICAP_CLIENT - case LFT_ICAP_LAST_MATCHED_ALL_HEADERS: - case LFT_ICAP_REQ_ALL_HEADERS: - case LFT_ICAP_REP_ALL_HEADERS: -#endif - - switch (type) { - case LFT_REQUEST_ALL_HEADERS: - type = LFT_REQUEST_HEADER; - break; - case LFT_ADAPTED_REQUEST_ALL_HEADERS: - type = LFT_ADAPTED_REQUEST_HEADER; - break; - case LFT_REPLY_ALL_HEADERS: - type = LFT_REPLY_HEADER; - break; -#if ICAP_CLIENT - case LFT_ICAP_LAST_MATCHED_ALL_HEADERS: - type = LFT_ICAP_LAST_MATCHED_HEADER; - break; - case LFT_ICAP_REQ_ALL_HEADERS: - type = LFT_ICAP_REQ_HEADER; - break; - case LFT_ICAP_REP_ALL_HEADERS: - type = LFT_ICAP_REP_HEADER; - break; -#endif - default: - break; - } - - break; - - default: - if (t->data.string) - arg = t->data.string; - - break; - } - - entry->append("%", 1); - - switch (t->quote) { - - case LOG_QUOTE_QUOTES: - entry->append("\"", 1); - break; - - case LOG_QUOTE_BRAKETS: - entry->append("[", 1); - break; - - case LOG_QUOTE_URL: - entry->append("#", 1); - break; - - case LOG_QUOTE_RAW: - entry->append("'", 1); - break; - - case LOG_QUOTE_NONE: - break; - } - - if (t->left) - entry->append("-", 1); - - if (t->zero) - entry->append("0", 1); - - if (t->width) - storeAppendPrintf(entry, "%d", (int) t->width); - - if (t->precision) - storeAppendPrintf(entry, ".%d", (int) t->precision); - - if (arg) - storeAppendPrintf(entry, "{%s}", arg); - - for (te = logformat_token_table; te->config != NULL; te++) { - if (te->token_type == type) { - storeAppendPrintf(entry, "%s", te->config); - break; - } - } - - if (t->space) - entry->append(" ", 1); - - assert(te->config != NULL); - } - } - - entry->append("\n", 1); - } - -} - -void -accessLogFreeLogFormat(logformat_token ** tokens) -{ - while (*tokens) { - logformat_token *token = *tokens; - *tokens = token->next; - safe_free(token->data.string); - xfree(token); - } -} - -static void -accessLogSquid(AccessLogEntry * al, Logfile * logfile) -{ - const char *client = NULL; - const char *user = NULL; - char buf[MAX_IPSTRLEN]; - - if (Config.onoff.log_fqdn) { - client = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS); - } - - if (client == NULL) { - client = al->cache.caddr.NtoA(buf,MAX_IPSTRLEN); - } - - user = accessLogFormatName(al->cache.authuser); - - if (!user) - user = accessLogFormatName(al->cache.extuser); - -#if USE_SSL - - if (!user) - user = accessLogFormatName(al->cache.ssluser); - -#endif - - if (!user) - user = accessLogFormatName(al->cache.rfc931); - - if (user && !*user) - safe_free(user); - - if (!Config.onoff.log_mime_hdrs) { - logfilePrintf(logfile, "%9ld.%03d %6d %s %s%s/%03d %"PRId64" %s %s %s %s%s/%s %s\n", - (long int) current_time.tv_sec, - (int) current_time.tv_usec / 1000, - al->cache.msec, - client, - log_tags[al->cache.code], - al->http.statusSfx(), - al->http.code, - al->cache.replySize, - al->_private.method_str, - al->url, - user ? user : dash_str, - al->hier.ping.timedout ? "TIMEOUT_" : "", - hier_code_str[al->hier.code], - al->hier.host, - al->http.content_type); - } else { - char *ereq = log_quote(al->headers.request); - char *erep = log_quote(al->headers.reply); - logfilePrintf(logfile, "%9ld.%03d %6d %s %s%s/%03d %"PRId64" %s %s %s %s%s/%s %s [%s] [%s]\n", - (long int) current_time.tv_sec, - (int) current_time.tv_usec / 1000, - al->cache.msec, - client, - log_tags[al->cache.code], - al->http.statusSfx(), - al->http.code, - al->cache.replySize, - al->_private.method_str, - al->url, - user ? user : dash_str, - al->hier.ping.timedout ? "TIMEOUT_" : "", - hier_code_str[al->hier.code], - al->hier.host, - al->http.content_type, - ereq, - erep); - safe_free(ereq); - safe_free(erep); - } - safe_free(user); -} - -static void -accessLogCommon(AccessLogEntry * al, Logfile * logfile) -{ - const char *client = NULL; - char *user1 = NULL, *user2 = NULL; - char buf[MAX_IPSTRLEN]; - - if (Config.onoff.log_fqdn) { - client = fqdncache_gethostbyaddr(al->cache.caddr, 0); - } - - if (client == NULL) { - client = al->cache.caddr.NtoA(buf,MAX_IPSTRLEN); - } - - user1 = accessLogFormatName(al->cache.authuser); - - user2 = accessLogFormatName(al->cache.rfc931); - - logfilePrintf(logfile, "%s %s %s [%s] \"%s %s HTTP/%d.%d\" %d %"PRId64" %s%s:%s%s", - client, - user2 ? user2 : dash_str, - user1 ? user1 : dash_str, - mkhttpdlogtime(&squid_curtime), - al->_private.method_str, - al->url, - al->http.version.major, al->http.version.minor, - al->http.code, - al->cache.replySize, - log_tags[al->cache.code], - al->http.statusSfx(), - hier_code_str[al->hier.code], - (Config.onoff.log_mime_hdrs?"":"\n")); - - safe_free(user1); - - safe_free(user2); - - if (Config.onoff.log_mime_hdrs) { - char *ereq = log_quote(al->headers.request); - char *erep = log_quote(al->headers.reply); - logfilePrintf(logfile, " [%s] [%s]\n", ereq, erep); - safe_free(ereq); - safe_free(erep); - } -} - -#if ICAP_CLIENT -static void -accessLogICAPSquid(AccessLogEntry * al, Logfile * logfile) -{ - const char *client = NULL; - const char *user = NULL; - char tmp[MAX_IPSTRLEN], clientbuf[MAX_IPSTRLEN]; - - if (al->cache.caddr.IsAnyAddr()) { // ICAP OPTIONS xactions lack client - client = "-"; - } else { - if (Config.onoff.log_fqdn) - client = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS); - if (!client) - client = al->cache.caddr.NtoA(clientbuf, MAX_IPSTRLEN); - } - - user = accessLogFormatName(al->cache.authuser); - - if (!user) - user = accessLogFormatName(al->cache.extuser); - -#if USE_SSL - - if (!user) - user = accessLogFormatName(al->cache.ssluser); - -#endif - - if (!user) - user = accessLogFormatName(al->cache.rfc931); - - if (user && !*user) - safe_free(user); - - logfilePrintf(logfile, "%9ld.%03d %6d %s -/%03d %"PRId64" %s %s %s -/%s -\n", - (long int) current_time.tv_sec, - (int) current_time.tv_usec / 1000, - - al->icap.trTime, - client, - - al->icap.resStatus, - al->icap.bytesRead, - Adaptation::Icap::ICAP::methodStr(al->icap.reqMethod), - al->icap.reqUri.termedBuf(), - user ? user : dash_str, - al->icap.hostAddr.NtoA(tmp, MAX_IPSTRLEN)); - safe_free(user); -} -#endif - void accessLogLogTo(customlog* log, AccessLogEntry * al, ACLChecklist * checklist) { @@ -2013,32 +119,37 @@ switch (log->type) { - case CLF_AUTO: - if (Config.onoff.common_log) - accessLogCommon(al, log->logfile); - else - accessLogSquid(al, log->logfile); - break; - - case CLF_SQUID: - accessLogSquid(al, log->logfile); - break; - - case CLF_COMMON: - accessLogCommon(al, log->logfile); - break; - - case CLF_CUSTOM: - accessLogCustom(al, log); + case Log::Format::CLF_SQUID: + Log::Format::SquidNative(al, log->logfile); + break; + + case Log::Format::CLF_COMBINED: + Log::Format::HttpdCombined(al, log->logfile); + break; + + case Log::Format::CLF_COMMON: + Log::Format::HttpdCommon(al, log->logfile); + break; + + case Log::Format::CLF_REFERER: + Log::Format::SquidReferer(al, log->logfile); + break; + + case Log::Format::CLF_USERAGENT: + Log::Format::SquidUserAgent(al, log->logfile); + break; + + case Log::Format::CLF_CUSTOM: + Log::Format::SquidCustom(al, log); break; #if ICAP_CLIENT - case CLF_ICAP_SQUID: - accessLogICAPSquid(al, log->logfile); + case Log::Format::CLF_ICAP_SQUID: + Log::Format::SquidIcap(al, log->logfile); break; #endif - case CLF_NONE: + case Log::Format::CLF_NONE: return; // abort! default: @@ -2185,8 +296,6 @@ accessLogRegisterWithCacheManager(); - assert(sizeof(log_tags) == (LOG_TYPE_MAX + 1) * sizeof(char *)); - #if USE_ADAPTATION alLogformatHasAdaptToken = false; #endif @@ -2195,7 +304,7 @@ #endif for (log = Config.Log.accesslogs; log; log = log->next) { - if (log->type == CLF_NONE) + if (log->type == Log::Format::CLF_NONE) continue; log->logfile = logfileOpen(log->filename, MAX_URL << 2, 1); @@ -2261,24 +370,6 @@ #endif } -const char * -accessLogTime(time_t t) -{ - - struct tm *tm; - static char buf[128]; - static time_t last_t = 0; - - if (t != last_t) { - tm = localtime(&t); - strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm); - last_t = t; - } - - return buf; -} - - #if USE_FORW_VIA_DB static void === modified file 'src/main.cc' --- src/main.cc 2010-11-27 06:44:33 +0000 +++ src/main.cc 2010-11-28 11:19:02 +0000 @@ -756,8 +756,6 @@ #if ICAP_CLIENT icapLogClose(); #endif - useragentLogClose(); - refererCloseLog(); eventAdd("mainReconfigureFinish", &mainReconfigureFinish, NULL, 0, 1, false); @@ -823,8 +821,6 @@ icapLogOpen(); #endif storeLogOpen(); - useragentOpenLog(); - refererOpenLog(); #if USE_DNSSERVERS dnsInit(); @@ -893,15 +889,9 @@ storeDirWriteCleanLogs(1); storeLogRotate(); /* store.log */ accessLogRotate(); /* access.log */ - useragentRotateLog(); /* useragent.log */ - refererRotateLog(); /* referer.log */ #if ICAP_CLIENT icapLogRotate(); /*icap.log*/ #endif -#if WIP_FWD_LOG - fwdLogRotate(); -#endif - icmpEngine.Open(); #if USE_DNSSERVERS dnsInit(); @@ -1040,10 +1030,6 @@ externalAclInit(); - useragentOpenLog(); - - refererOpenLog(); - httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */ httpReplyInitModule(); /* must go before accepting replies */ @@ -1875,13 +1861,6 @@ Store::Root().sync(); /* Flush log writes */ storeLogClose(); accessLogClose(); - useragentLogClose(); - refererCloseLog(); -#if WIP_FWD_LOG - - fwdUninit(); -#endif - Store::Root().sync(); /* Flush log close */ StoreFileSystem::FreeAllFs(); DiskIOModule::FreeAllModules(); === modified file 'src/neighbors.cc' --- src/neighbors.cc 2010-11-27 06:44:33 +0000 +++ src/neighbors.cc 2010-11-28 11:19:02 +0000 @@ -1755,7 +1755,7 @@ if (e->stats.last_connect_failure) { storeAppendPrintf(sentry, "Last failed connect() at: %s\n", - mkhttpdlogtime(&(e->stats.last_connect_failure))); + Time::FormatHttpd(e->stats.last_connect_failure)); } if (e->peer_domain != NULL) { === modified file 'src/protos.h' --- src/protos.h 2010-11-27 06:44:33 +0000 +++ src/protos.h 2010-11-28 11:19:02 +0000 @@ -57,7 +57,6 @@ #if HEADERS_LOG SQUIDCEXTERN void headersLog(int cs, int pq, const HttpRequestMethod& m, void *data); #endif -SQUIDCEXTERN char *log_quote(const char *header); SQUIDCEXTERN int logTypeIsATcpHit(log_type); /* @@ -632,14 +631,6 @@ SQUIDCEXTERN char *urlHostname(const char *url); SQUIDCEXTERN void urlExtMethodConfigure(void); -SQUIDCEXTERN void useragentOpenLog(void); -SQUIDCEXTERN void useragentRotateLog(void); -SQUIDCEXTERN void logUserAgent(const char *, const char *); -SQUIDCEXTERN void useragentLogClose(void); -SQUIDCEXTERN void refererOpenLog(void); -SQUIDCEXTERN void refererRotateLog(void); -SQUIDCEXTERN void logReferer(const char *, const char *, const char *); -SQUIDCEXTERN void refererCloseLog(void); SQUIDCEXTERN peer_t parseNeighborType(const char *s); /* tools.c */ === modified file 'src/send-announce.cc' --- src/send-announce.cc 2010-04-17 02:29:04 +0000 +++ src/send-announce.cc 2010-11-21 04:52:58 +0000 @@ -92,7 +92,7 @@ snprintf(tbuf, 256, "generated %d [%s]\n", (int) squid_curtime, - mkhttpdlogtime(&squid_curtime)); + Time::FormatHttpd(squid_curtime)); strcat(sndbuf, tbuf); l = strlen(sndbuf); === modified file 'src/structs.h' --- src/structs.h 2010-11-27 06:44:33 +0000 +++ src/structs.h 2010-11-28 11:19:02 +0000 @@ -256,27 +256,10 @@ struct { char *store; char *swap; -#if USE_USERAGENT_LOG - - char *useragent; -#endif -#if USE_REFERER_LOG - - char *referer; -#endif -#if WIP_FWD_LOG - - char *forward; -#endif - - logformat *logformats; - customlog *accesslogs; - #if ICAP_CLIENT customlog *icaplogs; #endif - int rotateNumber; } Log; char *adminEmail; @@ -1310,23 +1293,17 @@ int zero_object_sz; }; -class logformat_token; - -struct _logformat { - char *name; - logformat_token *format; - logformat *next; -}; - class Logfile; +class logformat; +#include "log/Formats.h" struct _customlog { char *filename; ACLList *aclList; logformat *logFormat; Logfile *logfile; customlog *next; - customlog_type type; + Log::Format::log_type type; }; #endif /* SQUID_STRUCTS_H */ === modified file 'src/time.cc' --- src/time.cc 2010-11-02 00:12:43 +0000 +++ src/time.cc 2010-11-21 04:53:14 +0000 @@ -68,3 +68,66 @@ { getCurrentTime(); } + +const char * +Time::FormatStrf(time_t t) +{ + struct tm *tm; + static char buf[128]; + static time_t last_t = 0; + + if (t != last_t) { + tm = localtime(&t); + strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm); + last_t = t; + } + + return buf; +} + +const char * +Time::FormatHttpd(time_t t) +{ + static char buf[128]; + static time_t last_t = 0; + + if (t != last_t) { + struct tm *gmt = gmtime(&t); + +#if !USE_GMT + int gmt_min, gmt_hour, gmt_yday, day_offset; + size_t len; + struct tm *lt; + int min_offset; + + /* localtime & gmtime may use the same static data */ + gmt_min = gmt->tm_min; + gmt_hour = gmt->tm_hour; + gmt_yday = gmt->tm_yday; + + lt = localtime(&t); + + day_offset = lt->tm_yday - gmt_yday; + /* wrap round on end of year */ + if (day_offset > 1) + day_offset = -1; + else if (day_offset < -1) + day_offset = 1; + + min_offset = day_offset * 1440 + (lt->tm_hour - gmt_hour) * 60 + + (lt->tm_min - gmt_min); + + len = strftime(buf, 127 - 5, "%d/%b/%Y:%H:%M:%S ", lt); + snprintf(buf + len, 128 - len, "%+03d%02d", + (min_offset / 60) % 24, + min_offset % 60); +#else /* USE_GMT */ + buf[0] = '\0'; + strftime(buf, 127, "%d/%b/%Y:%H:%M:%S -000", gmt); +#endif /* USE_GMT */ + + last_t = t; + } + + return buf; +} === modified file 'src/typedefs.h' --- src/typedefs.h 2010-10-06 03:50:45 +0000 +++ src/typedefs.h 2010-11-21 04:53:15 +0000 @@ -169,8 +169,6 @@ typedef struct _link_list link_list; -typedef struct _logformat logformat; - typedef struct _customlog customlog; #if SQUID_SNMP