=== 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.
 
+<p>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".
 
 <sect1> Client Bandwidth Limits
 <p>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.
 	<p>New <em>tcp</em> module to send each log line as text data to a TCP receiver.
 	<p>New <em>udp</em> module to send each log line as text data to a UDP receiver.
+	<p>New format <em>referrer</em> to log with the format prevously used by referer_log directive.
+	<p>New format <em>useragent</em> to log with the format prevously used by useragent_log directive.
 
 	<tag>acl random</tag>
 	<p>New type <em>random</em>. Pseudo-randomly match requests based on a configured probability.
@@ -532,6 +536,12 @@
 <sect1>Removed tags<label id="removedtags">
 <p>
 <descrip>
+	<tag>emulate_httpd_log</tag>
+	<p>Replaced by <em>common</em> format option on an <em>access_log</em> directive.
+
+	<tag>forward_log</tag>
+	<p>Obsolete.
+
 	<tag>ftp_list_width</tag>
 	<p>Obsolete.
 
@@ -541,9 +551,14 @@
 	<tag>log_fqdn</tag>
 	<p>Obsolete. Replaced by automatic detection of the %>A logformat tag.
 
+	<tag>referer_log</tag>
+	<p>Replaced by the <em>referrer</em> format option on an <em>access_log</em> directive.
+
 	<tag>url_rewrite_concurrency</tag>
 	<p>Replaced by url_rewrite_children ... concurrency=N option.
 
+	<tag>useragent_log</tag>
+	<p>Replaced by the <em>useragent</em> format option on an <em>access_log</em> directive.
 </descrip>
 
 
@@ -644,6 +659,12 @@
 	<tag>--enable-auth-ntlm-helpers</tag>
 	<p>replaced by <em>--enable-auth-ntlm</em>.
 
+	<tag>--enable-referer-log</tag>
+	<p>Obsolete.
+
+	<tag>--enable-useragent-log</tag>
+	<p>Obsolete.
+
 </descrip>
 
 

=== 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 %<st %rm %ru %un %Sh/%<A %mt
-logformat squidmime %ts.%03tu %6tr %>a %Ss/%03>Hs %<st %rm %ru %un %Sh/%<A %mt [%>h] [%<h]
-logformat common %>a %ui %un [%tl] "%rm %ru HTTP/%rv" %>Hs %<st %Ss:%Sh
-logformat combined %>a %ui %un [%tl] "%rm %ru HTTP/%rv" %>Hs %<st "%{Referer}>h" "%{User-Agent}>h" %Ss:%Sh
+logformat squid      %ts.%03tu %6tr %>a %Ss/%03>Hs %<st %rm %ru %un %Sh/%<A %mt
+logformat common     %>a %ui %un [%tl] "%rm %ru HTTP/%rv" %>Hs %<st %Ss:%Sh
+logformat combined   %>a %ui %un [%tl] "%rm %ru HTTP/%rv" %>Hs %<st "%{Referer}>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<int64_t>(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<size_t>(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 <ramey@csc.ti.com> (useragent)
- *         Jens-S. Vöckler <voeckler@rvs.uni-hannover.de> (mod 4 referer)
+ *         Jens-S. V?ckler <voeckler@rvs.uni-hannover.de> (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 <ramey@csc.ti.com>
+ * AUTHOR: Amos Jeffries <amosjeffries@squid-cache.org>
  *
  * 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<char *>(xcalloc(1, 1));
+        *buf = '\0';
+        return buf;
+    }
+
+    buf = static_cast<char *>(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<char *>(xcalloc(1, 1));
+        *buf = '\0';
+        return buf;
+    }
+
+    buf = static_cast<char *>(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
+
+    /*{ "<a", LFT_SERVER_IP_ADDRESS }, */
+    /*{ "<p", LFT_SERVER_PORT }, */
+    {"<A", LFT_SERVER_IP_OR_PEER_NAME},
+
+    /* {"oa", LFT_OUTGOING_IP}, */
+    /* {"ot", LFT_OUTGOING_TOS}, */
+
+    {"la", LFT_LOCAL_IP},
+    {"lp", LFT_LOCAL_PORT},
+    /*{ "lA", LFT_LOCAL_NAME }, */
+    {"<lp", LFT_PEER_LOCAL_PORT},
+
+    {"ts", LFT_TIME_SECONDS_SINCE_EPOCH},
+    {"tu", LFT_TIME_SUBSECOND},
+    {"tl", LFT_TIME_LOCALTIME},
+    {"tg", LFT_TIME_GMT},
+    {"tr", LFT_TIME_TO_HANDLE_REQUEST},
+
+    {"<pt", LFT_PEER_RESPONSE_TIME},
+    {"<tt", LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME},
+    {"dt", LFT_DNS_WAIT_TIME},
+
+    {">ha", LFT_ADAPTED_REQUEST_HEADER},
+    {">ha", LFT_ADAPTED_REQUEST_ALL_HEADERS},
+    {">h", LFT_REQUEST_HEADER},
+    {">h", LFT_REQUEST_ALL_HEADERS},
+    {"<h", LFT_REPLY_HEADER},
+    {"<h", LFT_REPLY_ALL_HEADERS},
+
+    {"un", LFT_USER_NAME},
+    {"ul", LFT_USER_LOGIN},
+    /*{ "ur", LFT_USER_REALM }, */
+    /*{ "us", LFT_USER_SCHEME }, */
+    {"ui", LFT_USER_IDENT},
+    {"ue", LFT_USER_EXTERNAL},
+
+    {"Hs", LFT_HTTP_SENT_STATUS_CODE_OLD_30},
+    {">Hs", LFT_HTTP_SENT_STATUS_CODE},
+    {"<Hs", LFT_HTTP_RECEIVED_STATUS_CODE},
+    /*{ "Ht", LFT_HTTP_STATUS }, */
+    {"<bs", LFT_HTTP_BODY_BYTES_READ},
+
+    {"Ss", LFT_SQUID_STATUS},
+    { "err_code", LFT_SQUID_ERROR },
+    { "err_detail", LFT_SQUID_ERROR_DETAIL },
+    {"Sh", LFT_SQUID_HIERARCHY},
+
+    {"mt", LFT_MIME_TYPE},
+
+    {"rm", LFT_REQUEST_METHOD},
+    {"ru", LFT_REQUEST_URI},	/* doesn't include the query-string */
+    {"rp", LFT_REQUEST_URLPATH},	/* doesn't include the host */
+    /* { "rq", LFT_REQUEST_QUERY }, * /     / * the query-string, INCLUDING the leading ? */
+    {">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_REPLY_SIZE_TOTAL},
+    {"<sH", LFT_REPLY_HIGHOFFSET},
+    {"<sS", LFT_REPLY_OBJECTSIZE},
+    /*{ "<sl", LFT_REPLY_SIZE_LINE }, * /   / * the reply line (protocol, code, text) */
+    { "<sh", LFT_REPLY_SIZE_HEADERS },
+    /*{ "<sb", LFT_REPLY_SIZE_BODY }, */
+    /*{ "<sB", LFT_REPLY_SIZE_BODY_NO_TE }, */
+
+    {"et", LFT_TAG},
+    {"st", LFT_IO_SIZE_TOTAL},
+    {"ea", LFT_EXT_LOG},
+    {"sn", LFT_SEQUENCE_NUMBER},
+
+    {"%", LFT_PERCENT},
+
+#if USE_ADAPTATION
+    {"adapt::all_trs", LTF_ADAPTATION_ALL_XACT_TIMES},
+    {"adapt::sum_trs", LTF_ADAPTATION_SUM_XACT_TIMES},
+#endif
+
+#if ICAP_CLIENT
+    {"icap::tt", LFT_ICAP_TOTAL_TIME},
+    {"icap::<last_h", LFT_ICAP_LAST_MATCHED_HEADER},
+
+    {"icap::<A",  LFT_ICAP_ADDR},
+    {"icap::<service_name",  LFT_ICAP_SERV_NAME},
+    {"icap::ru",  LFT_ICAP_REQUEST_URI},
+    {"icap::rm",  LFT_ICAP_REQUEST_METHOD},
+    {"icap::>st",  LFT_ICAP_BYTES_SENT},
+    {"icap::<st",  LFT_ICAP_BYTES_READ},
+    {"icap::<bs", LFT_ICAP_BODY_BYTES_READ},
+
+    {"icap::>h",  LFT_ICAP_REQ_HEADER},
+    {"icap::<h",  LFT_ICAP_REP_HEADER},
+
+    {"icap::tr",  LFT_ICAP_TR_RESPONSE_TIME},
+    {"icap::tio",  LFT_ICAP_IO_TIME},
+    {"icap::to",  LFT_ICAP_OUTCOME},
+    {"icap::Hs",  LFT_ICAP_STATUS_CODE},
+#endif
+
+    {NULL, LFT_NONE}		/* this must be last */
+};
+
+/* 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)
+{
+    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_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, &quote);
+
+    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, &quote);
+    }
+
+    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<char *>(xcalloc(1, 1));
-        *buf = '\0';
-        return buf;
-    }
-
-    buf = static_cast<char *>(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<char *>(xcalloc(1, 1));
-        *buf = '\0';
-        return buf;
-    }
-
-    buf = static_cast<char *>(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
-
-    /*{ "<a", LFT_SERVER_IP_ADDRESS }, */
-    /*{ "<p", LFT_SERVER_PORT }, */
-    {"<A", LFT_SERVER_IP_OR_PEER_NAME},
-
-    /* {"oa", LFT_OUTGOING_IP}, */
-    /* {"ot", LFT_OUTGOING_TOS}, */
-
-    {"la", LFT_LOCAL_IP},
-    {"lp", LFT_LOCAL_PORT},
-    /*{ "lA", LFT_LOCAL_NAME }, */
-    {"<lp", LFT_PEER_LOCAL_PORT},
-
-    {"ts", LFT_TIME_SECONDS_SINCE_EPOCH},
-    {"tu", LFT_TIME_SUBSECOND},
-    {"tl", LFT_TIME_LOCALTIME},
-    {"tg", LFT_TIME_GMT},
-    {"tr", LFT_TIME_TO_HANDLE_REQUEST},
-
-    {"<pt", LFT_PEER_RESPONSE_TIME},
-    {"<tt", LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME},
-    {"dt", LFT_DNS_WAIT_TIME},
-
-    {">ha", LFT_ADAPTED_REQUEST_HEADER},
-    {">ha", LFT_ADAPTED_REQUEST_ALL_HEADERS},
-    {">h", LFT_REQUEST_HEADER},
-    {">h", LFT_REQUEST_ALL_HEADERS},
-    {"<h", LFT_REPLY_HEADER},
-    {"<h", LFT_REPLY_ALL_HEADERS},
-
-    {"un", LFT_USER_NAME},
-    {"ul", LFT_USER_LOGIN},
-    /*{ "ur", LFT_USER_REALM }, */
-    /*{ "us", LFT_USER_SCHEME }, */
-    {"ui", LFT_USER_IDENT},
-    {"ue", LFT_USER_EXTERNAL},
-
-    {"Hs", LFT_HTTP_SENT_STATUS_CODE_OLD_30},
-    {">Hs", LFT_HTTP_SENT_STATUS_CODE},
-    {"<Hs", LFT_HTTP_RECEIVED_STATUS_CODE},
-    /*{ "Ht", LFT_HTTP_STATUS }, */
-    {"<bs", LFT_HTTP_BODY_BYTES_READ},
-
-    {"Ss", LFT_SQUID_STATUS},
-    { "err_code", LFT_SQUID_ERROR },
-    { "err_detail", LFT_SQUID_ERROR_DETAIL },
-    {"Sh", LFT_SQUID_HIERARCHY},
-
-    {"mt", LFT_MIME_TYPE},
-
-    {"rm", LFT_REQUEST_METHOD},
-    {"ru", LFT_REQUEST_URI},	/* doesn't include the query-string */
-    {"rp", LFT_REQUEST_URLPATH},	/* doesn't include the host */
-    /* { "rq", LFT_REQUEST_QUERY }, * /     / * the query-string, INCLUDING the leading ? */
-    {">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_REPLY_SIZE_TOTAL},
-    {"<sH", LFT_REPLY_HIGHOFFSET},
-    {"<sS", LFT_REPLY_OBJECTSIZE},
-    /*{ "<sl", LFT_REPLY_SIZE_LINE }, * /   / * the reply line (protocol, code, text) */
-    { "<sh", LFT_REPLY_SIZE_HEADERS },
-    /*{ "<sb", LFT_REPLY_SIZE_BODY }, */
-    /*{ "<sB", LFT_REPLY_SIZE_BODY_NO_TE }, */
-
-    {"et", LFT_TAG},
-    {"st", LFT_IO_SIZE_TOTAL},
-    {"ea", LFT_EXT_LOG},
-    {"sn", LFT_SEQUENCE_NUMBER},
-
-    {"%", LFT_PERCENT},
-
-#if USE_ADAPTATION
-    {"adapt::all_trs", LTF_ADAPTATION_ALL_XACT_TIMES},
-    {"adapt::sum_trs", LTF_ADAPTATION_SUM_XACT_TIMES},
-#endif
-
-#if ICAP_CLIENT
-    {"icap::tt", LFT_ICAP_TOTAL_TIME},
-    {"icap::<last_h", LFT_ICAP_LAST_MATCHED_HEADER},
-
-    {"icap::<A",  LFT_ICAP_ADDR},
-    {"icap::<service_name",  LFT_ICAP_SERV_NAME},
-    {"icap::ru",  LFT_ICAP_REQUEST_URI},
-    {"icap::rm",  LFT_ICAP_REQUEST_METHOD},
-    {"icap::>st",  LFT_ICAP_BYTES_SENT},
-    {"icap::<st",  LFT_ICAP_BYTES_READ},
-    {"icap::<bs", LFT_ICAP_BODY_BYTES_READ},
-
-    {"icap::>h",  LFT_ICAP_REQ_HEADER},
-    {"icap::<h",  LFT_ICAP_REP_HEADER},
-
-    {"icap::tr",  LFT_ICAP_TR_RESPONSE_TIME},
-    {"icap::tio",  LFT_ICAP_IO_TIME},
-    {"icap::to",  LFT_ICAP_OUTCOME},
-    {"icap::Hs",  LFT_ICAP_STATUS_CODE},
-#endif
-
-    {NULL, LFT_NONE}		/* this must be last */
-};
-
-static void
-accessLogCustom(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<int64_t>(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, &quote);
-
-    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, &quote);
-    }
-
-    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


