src/comm/Makefile \
src/esi/Makefile \
src/eui/Makefile \
+ src/format/Makefile \
src/icmp/Makefile \
src/ident/Makefile \
src/ip/Makefile \
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
class ACLChecklist;
class StoreEntry;
-class logformat_token;
/* Should be in 'AccessLog.h' as the driver */
extern void accessLogLogTo(customlog* log, AccessLogEntry* al, ACLChecklist* checklist = NULL);
extern void accessLogInit(void);
extern void accessLogFreeMemory(AccessLogEntry * aLogEntry);
extern const char *accessLogTime(time_t);
-extern int accessLogParseLogFormat(logformat_token ** fmt, char *def);
-extern void accessLogDumpLogFormat(StoreEntry * entry, const char *name, logformat * definitions);
-extern void accessLogFreeLogFormat(logformat_token ** fmt);
#endif /* SQUID_HTTPACCESSLOGENTRY_H */
#include "auth/UserRequest.h"
#endif
#include "HttpHeaderRange.h"
+#include "log/Config.h"
#include "MemBuf.h"
#include "Store.h"
#if ICAP_CLIENT
HttpRequest::icapHistory() const
{
if (!icapHistory_) {
- if ((LogfileStatus == LOG_ENABLE && alLogformatHasIcapToken) ||
- IcapLogfileStatus == LOG_ENABLE) {
+ if (Log::TheConfig.hasIcapToken || IcapLogfileStatus == LOG_ENABLE) {
icapHistory_ = new Adaptation::Icap::History();
debugs(93,4, HERE << "made " << icapHistory_ << " for " << this);
}
Adaptation::History::Pointer
HttpRequest::adaptLogHistory() const
{
- const bool loggingNeedsHistory = (LogfileStatus == LOG_ENABLE) &&
- alLogformatHasAdaptToken; // TODO: make global to remove this method?
- return HttpRequest::adaptHistory(loggingNeedsHistory);
+ return HttpRequest::adaptHistory(Log::TheConfig.hasAdaptToken);
}
void
//DEAD?: extern int httpRequestHdrAllowedByName(http_hdr_type id);
extern void httpRequestPack(void *obj, Packer *p);
-// TODO: Move these three to access_log.h or AccessLogEntry.h
-#if USE_ADAPTATION
-extern bool alLogformatHasAdaptToken;
-#endif
-#if ICAP_CLIENT
-extern bool alLogformatHasIcapToken;
-#endif
-extern int LogfileStatus;
-
class HttpHdrRange;
class DnsLookupDetails;
LoadableModules.h \
LoadableModules.cc
-SUBDIRS = base anyp comm eui acl fs repl
-DIST_SUBDIRS = base anyp comm eui acl fs repl
+SUBDIRS = base anyp comm eui acl format fs repl
+DIST_SUBDIRS = base anyp comm eui acl format fs repl
if ENABLE_AUTH
SUBDIRS += auth
eui/libeui.la \
icmp/libicmp.la icmp/libicmp-core.la \
log/liblog.la \
+ format/libformat.la \
$(XTRA_OBJS) \
$(DISK_LINKOBJS) \
$(REPL_OBJS) \
libsquid.la \
ip/libip.la \
fs/libfs.la \
+ format/libformat.la \
ipc/libipc.la \
mgr/libmgr.la
comm/libcomm.la \
icmp/libicmp.la icmp/libicmp-core.la \
log/liblog.la \
+ format/libformat.la \
$(REPL_OBJS) \
$(ADAPTATION_LIBS) \
$(ESI_LIBS) \
icmp/libicmp.la icmp/libicmp-core.la \
comm/libcomm.la \
log/liblog.la \
+ format/libformat.la \
$(REPL_OBJS) \
$(ADAPTATION_LIBS) \
$(ESI_LIBS) \
icmp/libicmp.la icmp/libicmp-core.la \
comm/libcomm.la \
log/liblog.la \
+ format/libformat.la \
$(REPL_OBJS) \
$(ADAPTATION_LIBS) \
$(ESI_LIBS) \
icmp/libicmp.la icmp/libicmp-core.la \
comm/libcomm.la \
log/liblog.la \
+ format/libformat.la \
$(REPL_OBJS) \
$(ADAPTATION_LIBS) \
$(ESI_LIBS) \
icmp/libicmp.la icmp/libicmp-core.la \
comm/libcomm.la \
log/liblog.la \
+ format/libformat.la \
$(REPL_OBJS) \
$(ADAPTATION_LIBS) \
$(ESI_LIBS) \
icmp/libicmp.la icmp/libicmp-core.la \
comm/libcomm.la \
log/liblog.la \
+ format/libformat.la \
$(REGEXLIB) \
$(REPL_OBJS) \
$(ADAPTATION_LIBS) \
#include "adaptation/History.h"
#include "base/TextException.h"
#include "globals.h"
-#include "HttpRequest.h" /* for alLogformatHasAdaptToken */
#include "SquidTime.h"
/// impossible services value to identify unset theNextServices
#if USE_SQUID_ESI
#include "esi/Parser.h"
#endif
+#include "format/Format.h"
#include "HttpRequestMethod.h"
#include "ident/Config.h"
#include "ip/Intercept.h"
parse_access_log(customlog ** logs)
{
const char *filename, *logdef_name;
- customlog *cl;
- logformat *lf;
- cl = (customlog *)xcalloc(1, sizeof(*cl));
+ customlog *cl = (customlog *)xcalloc(1, sizeof(*cl));
if ((filename = strtok(NULL, w_space)) == NULL) {
self_destruct();
cl->filename = xstrdup(filename);
/* look for the definition pointer corresponding to this name */
- lf = Log::TheConfig.logformats;
+ Format::Format *lf = Log::TheConfig.logformats;
while (lf != NULL) {
debugs(3, 9, "Comparing against '" << lf->name << "'");
#include "squid.h"
#include "event.h"
+#include "format/Tokens.h"
#include "ClientInfo.h"
#include "ip/Address.h"
-#include "log/Tokens.h"
#include "mgr/Registration.h"
#include "SquidMath.h"
#include "SquidTime.h"
if (LOG_UDP_HIT == l)
icp_hits += c->Icp.result_hist[l];
- storeAppendPrintf(sentry, " %-20.20s %7d %3d%%\n",log_tags[l], c->Icp.result_hist[l], Math::intPercent(c->Icp.result_hist[l], c->Icp.n_requests));
+ storeAppendPrintf(sentry, " %-20.20s %7d %3d%%\n",Format::log_tags[l], c->Icp.result_hist[l], Math::intPercent(c->Icp.result_hist[l], c->Icp.n_requests));
}
storeAppendPrintf(sentry, " HTTP Requests %d\n", c->Http.n_requests);
storeAppendPrintf(sentry,
" %-20.20s %7d %3d%%\n",
- log_tags[l],
+ Format::log_tags[l],
c->Http.result_hist[l],
Math::intPercent(c->Http.result_hist[l], c->Http.n_requests));
}
#endif
#include "fde.h"
#include "forward.h"
+#include "format/Tokens.h"
#include "HttpReply.h"
#include "HttpRequest.h"
#include "ip/QosConfig.h"
#include "ipcache.h"
-#include "log/Tokens.h"
#include "MemObject.h"
#include "ProtoPort.h"
#include "SquidTime.h"
if (http->storeEntry()) {
if (EBIT_TEST(http->storeEntry()->flags, ENTRY_SPECIAL)) {
debugs(88, 0, "clientProcessMiss: miss on a special object (" << url << ").");
- debugs(88, 0, "\tlog_type = " << log_tags[http->logType]);
+ debugs(88, 0, "\tlog_type = " << Format::log_tags[http->logType]);
http->storeEntry()->dump(1);
}
#include "comm/Write.h"
#include "compat/inet_pton.h"
#include "fde.h"
+#include "format/Tokens.h"
#include "HttpReply.h"
#include "HttpRequest.h"
#include "ip/QosConfig.h"
-#include "log/Tokens.h"
#include "MemObject.h"
#include "ProtoPort.h"
#include "Store.h"
{
PROF_start(httpStart);
logType = LOG_TAG_NONE;
- debugs(85, 4, "ClientHttpRequest::httpStart: " << log_tags[logType] << " for '" << uri << "'");
+ debugs(85, 4, "ClientHttpRequest::httpStart: " << Format::log_tags[logType] << " for '" << uri << "'");
/* no one should have touched this */
assert(out.offset == 0);
--- /dev/null
+#include "config.h"
+#include "AccessLogEntry.h"
+#include "comm/Connection.h"
+#include "err_detail_type.h"
+#include "errorpage.h"
+#include "format/Format.h"
+#include "format/Quoting.h"
+#include "format/Tokens.h"
+#include "HttpRequest.h"
+#include "MemBuf.h"
+#include "rfc1738.h"
+#include "SquidTime.h"
+#include "Store.h"
+
+
+Format::Format::Format(const char *n) :
+ format(NULL),
+ next(NULL)
+{
+ name = xstrdup(n);
+}
+
+Format::Format::~Format()
+{
+ // erase the list without consuming stack space
+ while (next) {
+ // unlink the next entry for deletion
+ Format *temp = next;
+ next = temp->next;
+ temp->next = NULL;
+ delete temp;
+ }
+
+ // remove locals
+ xfree(name);
+ delete format;
+}
+
+bool
+Format::Format::parse(char *def)
+{
+ char *cur, *eos;
+ Token *new_lt, *last_lt;
+ enum Quoting quote = LOG_QUOTE_NONE;
+
+ debugs(46, 2, HERE << "got definition '" << def << "'");
+
+ if (format) {
+ debugs(46, DBG_IMPORTANT, "WARNING: existing format for '" << name << " " << def << "'");
+ return false;
+ }
+
+ /* 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);
+ format = new_lt = last_lt = new Token;
+ cur += new_lt->parse(cur, "e);
+
+ while (cur < eos) {
+ new_lt = new Token;
+ last_lt->next = new_lt;
+ last_lt = new_lt;
+ cur += new_lt->parse(cur, "e);
+ }
+
+ return true;
+}
+
+void
+Format::Format::dump(StoreEntry * entry, const char *name)
+{
+ debugs(46, 4, HERE);
+
+ // loop rather than recursing to conserve stack space.
+ for (Format *format = this; format; format = format->next) {
+ debugs(46, 3, HERE << "Dumping format definition for " << format->name);
+ storeAppendPrintf(entry, "format %s ", format->name);
+
+ for (Token *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;
+ ByteCode_t type = t->type;
+
+ switch (type) {
+ /* special cases */
+
+ case LFT_STRING:
+ break;
+#if USE_ADAPTATION
+ case LFT_ADAPTATION_LAST_HEADER_ELEM:
+#endif
+#if ICAP_CLIENT
+ 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; // XXX: remove _ELEM?
+ break;
+ case LFT_ADAPTED_REQUEST_HEADER_ELEM:
+ type = LFT_ADAPTED_REQUEST_HEADER_ELEM; // XXX: remove _ELEM?
+ break;
+ case LFT_REPLY_HEADER_ELEM:
+ type = LFT_REPLY_HEADER_ELEM; // XXX: remove _ELEM?
+ break;
+#if USE_ADAPTATION
+ case LFT_ADAPTATION_LAST_HEADER_ELEM:
+ type = LFT_ADAPTATION_LAST_HEADER;
+ break;
+#endif
+#if ICAP_CLIENT
+ 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 USE_ADAPTATION
+ case LFT_ADAPTATION_LAST_ALL_HEADERS:
+#endif
+#if ICAP_CLIENT
+ 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 USE_ADAPTATION
+ case LFT_ADAPTATION_LAST_ALL_HEADERS:
+ type = LFT_ADAPTATION_LAST_HEADER;
+ break;
+#endif
+#if ICAP_CLIENT
+ 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 (struct TokenTableEntry *te = TokenTable; te->config != NULL; te++) {
+ if (te->token_type == type) {
+ storeAppendPrintf(entry, "%s", te->config);
+ break;
+ }
+ }
+
+ if (t->space)
+ entry->append(" ", 1);
+ }
+ }
+
+ entry->append("\n", 1);
+ }
+
+}
+
+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
+Format::Format::assemble(MemBuf &mb, AccessLogEntry *al, int logSequenceNumber) const
+{
+ char tmp[1024];
+ String sb;
+
+ for (Token *fmt = 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:
+ // TODO make the ACL checklist have a direct link to any TCP details.
+ if (al->request && al->request->clientConnectionManager.valid() && al->request->clientConnectionManager->clientConnection != NULL) {
+ if (al->request->clientConnectionManager->clientConnection->remote.IsIPv4())
+ al->request->clientConnectionManager->clientConnection->remoteEui48.encode(tmp, 1024);
+ else
+ al->request->clientConnectionManager->clientConnection->remoteEui64.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,sizeof(tmp));
+ }
+
+ break;
+
+ case LFT_LOCAL_PORT:
+ if (al->request) {
+ outint = al->request->my_addr.GetPort();
+ doint = 1;
+ }
+
+ break;
+
+ // the fmt->type can not be LFT_PEER_LOCAL_IP_OLD_27
+ // but compiler complains if ommited
+ case LFT_PEER_LOCAL_IP_OLD_27:
+ case LFT_PEER_LOCAL_IP:
+ if (!al->hier.peer_local_addr.IsAnyAddr()) {
+ out = al->hier.peer_local_addr.NtoA(tmp,sizeof(tmp));
+ }
+ break;
+
+ case LFT_PEER_LOCAL_PORT:
+ if ((outint = al->hier.peer_local_addr.GetPort())) {
+ 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;
+
+ case LFT_ADAPTATION_LAST_HEADER:
+ if (al->request) {
+ const Adaptation::History::Pointer ah = al->request->adaptHistory();
+ if (ah != NULL) // XXX: add adapt::<all_h but use lastMeta here
+ sb = ah->allMeta.getByName(fmt->data.header.header);
+ }
+
+ // XXX: here and elsewhere: move such code inside the if guard
+ out = sb.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ case LFT_ADAPTATION_LAST_HEADER_ELEM:
+ if (al->request) {
+ const Adaptation::History::Pointer ah = al->request->adaptHistory();
+ if (ah != NULL) // XXX: add adapt::<all_h but use lastMeta here
+ sb = ah->allMeta.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
+ }
+
+ out = sb.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ case LFT_ADAPTATION_LAST_ALL_HEADERS:
+ out = al->adapt.last_meta;
+
+ quote = 1;
+
+ break;
+#endif
+
+#if ICAP_CLIENT
+ 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 = QuoteUrlEncodeUsername(al->cache.authuser);
+
+ if (!out)
+ out = QuoteUrlEncodeUsername(al->cache.extuser);
+
+#if USE_SSL
+
+ if (!out)
+ out = QuoteUrlEncodeUsername(al->cache.ssluser);
+
+#endif
+
+ if (!out)
+ out = QuoteUrlEncodeUsername(al->cache.rfc931);
+
+ dofree = 1;
+
+ break;
+
+ case LFT_USER_LOGIN:
+ out = QuoteUrlEncodeUsername(al->cache.authuser);
+
+ dofree = 1;
+
+ break;
+
+ case LFT_USER_IDENT:
+ out = QuoteUrlEncodeUsername(al->cache.rfc931);
+
+ dofree = 1;
+
+ break;
+
+ case LFT_USER_EXTERNAL:
+ out = QuoteUrlEncodeUsername(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_CLIENT_REQ_METHOD:
+ if (al->request) {
+ out = al->request->method.image();
+ quote = 1;
+ }
+ break;
+
+ case LFT_CLIENT_REQ_URI:
+ // original client URI
+ if (al->request) {
+ out = urlCanonical(al->request);
+ quote = 1;
+ }
+ break;
+
+ case LFT_REQUEST_URLPATH_OLD_31:
+ case LFT_CLIENT_REQ_URLPATH:
+ if (al->request) {
+ out = al->request->urlpath.termedBuf();
+ quote = 1;
+ }
+ break;
+
+ case LFT_CLIENT_REQ_VERSION:
+ if (al->request) {
+ snprintf(tmp, sizeof(tmp), "%d.%d", (int) al->request->http_ver.major, (int) al->request->http_ver.minor);
+ out = tmp;
+ }
+ break;
+
+ case LFT_REQUEST_METHOD:
+ out = al->_private.method_str;
+ break;
+
+ case LFT_REQUEST_URI:
+ out = al->url;
+ break;
+
+ case LFT_REQUEST_VERSION_OLD_2X:
+ 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_SERVER_REQ_METHOD:
+ if (al->adapted_request) {
+ out = al->adapted_request->method.image();
+ quote = 1;
+ }
+ break;
+
+ case LFT_SERVER_REQ_URI:
+ // adapted request URI sent to server/peer
+ if (al->adapted_request) {
+ out = urlCanonical(al->adapted_request);
+ quote = 1;
+ }
+ break;
+
+ case LFT_SERVER_REQ_URLPATH:
+ if (al->adapted_request) {
+ out = al->adapted_request->urlpath.termedBuf();
+ quote = 1;
+ }
+ break;
+
+ case LFT_SERVER_REQ_VERSION:
+ if (al->adapted_request) {
+ snprintf(tmp, sizeof(tmp), "%d.%d",
+ (int) al->adapted_request->http_ver.major,
+ (int) al->adapted_request->http_ver.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 = logSequenceNumber;
+ 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 = 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);
+ }
+}
--- /dev/null
+#ifndef _SQUID_FORMAT_FORMAT_H
+#define _SQUID_FORMAT_FORMAT_H
+
+/*
+ * Squid configuration allows users to define custom formats in
+ * several components.
+ * - logging
+ * - external ACL input
+ * - deny page URL
+ *
+ * These enumerations and classes define the API for parsing of
+ * format directives to define these patterns. Along with output
+ * functionality to produce formatted buffers.
+ */
+
+class AccessLogEntry;
+class MemBuf;
+class StoreEntry;
+
+namespace Format
+{
+
+class Token;
+
+// XXX: inherit from linked list
+class Format
+{
+public:
+ Format(const char *name);
+ ~Format();
+
+ /* 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. */
+ bool parse(char *def);
+
+ /// assemble the state information into a formatted line.
+ void assemble(MemBuf &mb, AccessLogEntry *al, int logSequenceNumber) const;
+
+ /// dump this whole list of formats into the provided StoreEntry
+ void dump(StoreEntry * entry, const char *name);
+
+ char *name;
+ Token *format;
+ Format *next;
+};
+
+} // namespace Format
+
+#endif /* _SQUID_FORMAT_FORMAT_H */
--- /dev/null
+include $(top_srcdir)/src/Common.am
+include $(top_srcdir)/src/TestHeaders.am
+
+noinst_LTLIBRARIES = libformat.la
+
+libformat_la_SOURCES = \
+ Format.cc \
+ Format.h \
+ Quoting.cc \
+ Quoting.h \
+ Tokens.cc \
+ Tokens.h
+
#include "config.h"
-#include "log/Gadgets.h"
+#include "format/Quoting.h"
static const char c2x[] =
"000102030405060708090a0b0c0d0e0f"
#endif // DEAD
char *
-Log::FormatName(const char *name)
+Format::QuoteUrlEncodeUsername(const char *name)
{
if (NULL == name)
return NULL;
}
char *
-Log::QuoteMimeBlob(const char *header)
+Format::QuoteMimeBlob(const char *header)
{
int c;
int i;
-#ifndef _SQUID_LOG_GADGETS_H
-#define _SQUID_LOG_GADGETS_H
+#ifndef _SQUID_FORMAT_QUOTING_H
+#define _SQUID_FORMAT_QUOTING_H
-namespace Log
+namespace Format
{
/// Safely URL-encode a username.
/// Accepts NULL or empty strings.
-char * FormatName(const char *name);
+extern char * QuoteUrlEncodeUsername(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);
+extern char *QuoteMimeBlob(const char *header);
-}; // namespace Log
+}; // namespace Format
-#endif /* _SQUID_LOG_GADGETS_H */
+#endif /* _SQUID_FORMAT_QUOTING_H */
--- /dev/null
+#include "config.h"
+#include "format/Tokens.h"
+#include "Store.h"
+
+const char *Format::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"
+};
+
+struct Format::TokenTableEntry Format::TokenTable[] = {
+
+ {">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},
+
+ {"la", LFT_LOCAL_IP},
+ {"lp", LFT_LOCAL_PORT},
+ /*{ "lA", LFT_LOCAL_NAME }, */
+
+ {"<la", LFT_PEER_LOCAL_IP},
+ {"oa", LFT_PEER_LOCAL_IP_OLD_27},
+ {"<lp", LFT_PEER_LOCAL_PORT},
+ /* {"ot", LFT_PEER_OUTGOING_TOS}, */
+
+ {"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_CLIENT_REQ_METHOD},
+ {">ru", LFT_CLIENT_REQ_URI},
+ {">rp", LFT_CLIENT_REQ_URLPATH},
+ /*{">rq", LFT_CLIENT_REQ_QUERY},*/
+ {">rv", LFT_CLIENT_REQ_VERSION},
+
+ {"rm", LFT_REQUEST_METHOD},
+ {"ru", LFT_REQUEST_URI}, /* doesn't include the query-string */
+ {"rp", LFT_REQUEST_URLPATH_OLD_31},
+ /* { "rq", LFT_REQUEST_QUERY }, * / / * the query-string, INCLUDING the leading ? */
+ {">v", LFT_REQUEST_VERSION_OLD_2X},
+ {"rv", LFT_REQUEST_VERSION},
+
+ {"<rm", LFT_SERVER_REQ_METHOD},
+ {"<ru", LFT_SERVER_REQ_URI},
+ {"<rp", LFT_SERVER_REQ_URLPATH},
+ /*{"<rq", LFT_SERVER_REQ_QUERY},*/
+ {"<rv", LFT_SERVER_REQ_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},
+ {"adapt::<last_h", LFT_ADAPTATION_LAST_HEADER},
+#endif
+
+#if ICAP_CLIENT
+ {"icap::tt", LFT_ICAP_TOTAL_TIME},
+ {"icap::<last_h", LFT_ADAPTATION_LAST_HEADER}, // deprecated
+
+ {"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
+Format::Token::parse(char *def, Quoting *quoting)
+{
+ char *cur = def;
+
+ struct TokenTableEntry *lte;
+ int l;
+
+ 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);
+ type = LFT_STRING;
+ data.string = cp;
+
+ while (l > 0) {
+ switch (*cur) {
+
+ case '"':
+
+ if (*quoting == LOG_QUOTE_NONE)
+ *quoting = LOG_QUOTE_QUOTES;
+ else if (*quoting == LOG_QUOTE_QUOTES)
+ *quoting = LOG_QUOTE_NONE;
+
+ break;
+
+ case '[':
+ if (*quoting == LOG_QUOTE_NONE)
+ *quoting = LOG_QUOTE_MIMEBLOB;
+
+ break;
+
+ case ']':
+ if (*quoting == LOG_QUOTE_MIMEBLOB)
+ *quoting = LOG_QUOTE_NONE;
+
+ break;
+ }
+
+ cur++;
+ l--;
+ }
+
+ goto done;
+ }
+
+ if (!*cur)
+ goto done;
+
+ cur++;
+
+ // select quoting style for his particular token
+ switch (*cur) {
+
+ case '"':
+ quote = LOG_QUOTE_QUOTES;
+ cur++;
+ break;
+
+ case '\'':
+ quote = LOG_QUOTE_RAW;
+ cur++;
+ break;
+
+ case '[':
+ quote = LOG_QUOTE_MIMEBLOB;
+ cur++;
+ break;
+
+ case '#':
+ quote = LOG_QUOTE_URL;
+ cur++;
+ break;
+
+ default:
+ quote = *quoting;
+ break;
+ }
+
+ if (*cur == '-') {
+ left = 1;
+ cur++;
+ }
+
+ if (*cur == '0') {
+ zero = 1;
+ cur++;
+ }
+
+ if (xisdigit(*cur))
+ width = strtol(cur, &cur, 10);
+
+ if (*cur == '.')
+ precision = strtol(cur + 1, &cur, 10);
+
+ if (*cur == '{') {
+ char *cp;
+ cur++;
+ l = strcspn(cur, "}");
+ cp = (char *)xmalloc(l + 1);
+ xstrncpy(cp, cur, l + 1);
+ 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;
+ }
+
+ type = LFT_NONE;
+
+ for (lte = TokenTable; lte->config != NULL; lte++) {
+ if (strncmp(lte->config, cur, strlen(lte->config)) == 0) {
+ type = lte->token_type;
+ cur += strlen(lte->config);
+ break;
+ }
+ }
+
+ if (type == LFT_NONE) {
+ fatalf("Can't parse configuration token: '%s'\n",
+ def);
+ }
+
+ if (*cur == ' ') {
+ space = 1;
+ cur++;
+ }
+
+done:
+
+ switch (type) {
+
+#if USE_ADAPTATION
+ case LFT_ADAPTATION_LAST_HEADER:
+#endif
+
+#if ICAP_CLIENT
+ 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 (data.string) {
+ char *header = data.string;
+ char *cp = strchr(header, ':');
+
+ if (cp) {
+ *cp++ = '\0';
+
+ if (*cp == ',' || *cp == ';' || *cp == ':')
+ data.header.separator = *cp++;
+ else
+ data.header.separator = ',';
+
+ data.header.element = cp;
+
+ switch (type) {
+ case LFT_REQUEST_HEADER:
+ type = LFT_REQUEST_HEADER_ELEM;
+ break;
+
+ case LFT_ADAPTED_REQUEST_HEADER:
+ type = LFT_ADAPTED_REQUEST_HEADER_ELEM;
+ break;
+
+ case LFT_REPLY_HEADER:
+ type = LFT_REPLY_HEADER_ELEM;
+ break;
+#if USE_ADAPTATION
+ case LFT_ADAPTATION_LAST_HEADER:
+ type = LFT_ADAPTATION_LAST_HEADER_ELEM;
+ break;
+#endif
+#if ICAP_CLIENT
+ case LFT_ICAP_REQ_HEADER:
+ type = LFT_ICAP_REQ_HEADER_ELEM;
+ break;
+ case LFT_ICAP_REP_HEADER:
+ type = LFT_ICAP_REP_HEADER_ELEM;
+ break;
+#endif
+ default:
+ break;
+ }
+ }
+
+ data.header.header = header;
+ } else {
+ switch (type) {
+ case LFT_REQUEST_HEADER:
+ type = LFT_REQUEST_ALL_HEADERS;
+ break;
+
+ case LFT_ADAPTED_REQUEST_HEADER:
+ type = LFT_ADAPTED_REQUEST_ALL_HEADERS;
+ break;
+
+ case LFT_REPLY_HEADER:
+ type = LFT_REPLY_ALL_HEADERS;
+ break;
+#if USE_ADAPTATION
+ case LFT_ADAPTATION_LAST_HEADER:
+ type = LFT_ADAPTATION_LAST_ALL_HEADERS;
+ break;
+#endif
+#if ICAP_CLIENT
+ case LFT_ICAP_REQ_HEADER:
+ type = LFT_ICAP_REQ_ALL_HEADERS;
+ break;
+ case LFT_ICAP_REP_HEADER:
+ 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:
+ divisor = 1000;
+
+ if (precision) {
+ int i;
+ divisor = 1000000;
+
+ for (i = precision; i > 1; i--)
+ divisor /= 10;
+
+ if (!divisor)
+ divisor = 0;
+ }
+
+ break;
+
+ case LFT_HTTP_SENT_STATUS_CODE_OLD_30:
+ debugs(46, 0, "WARNING: The \"Hs\" formatting code is deprecated. Use the \">Hs\" instead.");
+ type = LFT_HTTP_SENT_STATUS_CODE;
+ break;
+
+ case LFT_PEER_LOCAL_IP_OLD_27:
+ debugs(46, 0, "WARNING: The \"oa\" formatting code is deprecated. Use the \"<la\" instead.");
+ type = LFT_PEER_LOCAL_IP;
+ break;
+
+ case LFT_REQUEST_URLPATH_OLD_31:
+ debugs(46, 0, "WARNING: The \"rp\" formatting code is deprecated. Use the \">rp\" instead.");
+ type = LFT_CLIENT_REQ_URLPATH;
+ break;
+
+ case LFT_REQUEST_VERSION_OLD_2X:
+ debugs(46, 0, "WARNING: The \">v\" formatting code is deprecated. Use the \">rv\" instead.");
+ type = LFT_REQUEST_VERSION;
+ break;
+
+ default:
+ break;
+ }
+
+ return (cur - def);
+}
+
+Format::Token::~Token()
+{
+ safe_free(data.string);
+ while (next) {
+ Token *tokens = next;
+ next = next->next;
+ tokens->next = NULL;
+ delete tokens;
+ }
+}
+
+#ifndef _SQUID_FMT_TOKENS_H
+#define _SQUID_FMT_TOKENS_H
+
/*
- * $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.
+ * Squid configuration allows users to define custom formats in
+ * several components.
+ * - logging
+ * - external ACL input
+ * - deny page URL
*
+ * These enumerations and classes define the API for parsing of
+ * format directives to define these patterns. Along with output
+ * functionality to produce formatted buffers.
*/
-#ifndef _SQUID_LOG_TOKENS_H
-#define _SQUID_LOG_TOKENS_H
-class StoreEntry;
+namespace Format
+{
#define LOG_BUF_SZ (MAX_URL<<2)
/*
- * Bytecodes for the configureable logformat stuff
+ * Bytecodes for the configureable format stuff
*/
typedef enum {
LFT_NONE, /* dummy */
#endif
LFT_PERCENT /* special string cases for escaped chars */
-} logformat_bcode_t;
+} ByteCode_t;
-enum log_quote {
+/// Quoting style for a format output.
+enum Quoting {
LOG_QUOTE_NONE = 0,
LOG_QUOTE_QUOTES,
LOG_QUOTE_MIMEBLOB,
LOG_QUOTE_RAW
};
-/* FIXME: public class so we can pre-define its type. */
-class logformat_token
+// XXX: inherit from linked list
+class Token
{
public:
- logformat_bcode_t type;
+ Token() {};
+ ~Token();
+
+ /** parses a single token. Returns the token length in characters,
+ * and fills in this item with the token information.
+ * def is for sure null-terminated.
+ */
+ int parse(char *def, enum Quoting *quote);
+
+ ByteCode_t type;
union {
char *string;
} data;
unsigned char width;
unsigned char precision;
- enum log_quote quote;
+ enum Quoting 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 */
+ Token *next; /* todo: move from linked list to array */
};
-struct logformat_token_table_entry {
+struct TokenTableEntry {
const char *config;
- logformat_bcode_t token_type;
+ ByteCode_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);
+extern struct TokenTableEntry TokenTable[];
-void accessLogFreeLogFormat(logformat_token ** tokens);
+} // namespace Format
-#endif /* _SQUID_LOG_TOKENS_H */
+#endif /* _SQUID_FMT_TOKENS_H */
#include "comm/Connection.h"
#include "comm/Write.h"
#include "helper.h"
-#include "log/Gadgets.h"
+#include "format/Quoting.h"
#include "MemBuf.h"
#include "SquidMath.h"
#include "SquidTime.h"
srv->flags.shutdown ? 'S' : ' ',
tt < 0.0 ? 0.0 : tt,
(int) srv->roffset,
- srv->requests[0] ? Log::QuoteMimeBlob(srv->requests[0]->buf) : "(none)");
+ srv->requests[0] ? Format::QuoteMimeBlob(srv->requests[0]->buf) : "(none)");
}
storeAppendPrintf(sentry, "\nFlags key:\n\n");
srv->request ? (srv->request->placeholder ? 'P' : ' ') : ' ',
tt < 0.0 ? 0.0 : tt,
(int) srv->roffset,
- srv->request ? Log::QuoteMimeBlob(srv->request->buf) : "(none)");
+ srv->request ? Format::QuoteMimeBlob(srv->request->buf) : "(none)");
}
storeAppendPrintf(sentry, "\nFlags key:\n\n");
#include "config.h"
#include "log/Config.h"
-#include "log/Tokens.h"
#include "protos.h"
Log::LogConfig Log::TheConfig;
return;
}
- debugs(3, 2, "Logformat for '" << name << "' is '" << def << "'");
+ debugs(3, 2, "Log Format for '" << name << "' is '" << def << "'");
- logformat *nlf = new logformat(name);
+ ::Format::Format *nlf = new ::Format::Format(name);
- if (!accessLogParseLogFormat(&nlf->format, def)) {
+ if (!nlf->parse(def)) {
self_destruct();
return;
}
#ifndef SQUID_SRC_LOG_CONFIG_H
#define SQUID_SRC_LOG_CONFIG_H
-#include "log/Tokens.h"
+#include "format/Format.h"
class StoreEntry;
public:
void parseFormats();
void dumpFormats(StoreEntry *e, const char *name) {
- accessLogDumpLogFormat(e, name, logformats);
+ logformats->dump(e, name);
}
/// File path to logging daemon executable
char *logfile_daemon;
/// Linked list of custom log formats
- logformat *logformats;
+ ::Format::Format *logformats;
+
+#if USE_ADAPTATION
+ bool hasAdaptToken;
+#endif
+
+#if ICAP_CLIENT
+ bool hasIcapToken;
+#endif
};
extern LogConfig TheConfig;
#include "config.h"
#include "AccessLogEntry.h"
+#include "format/Tokens.h"
+#include "format/Quoting.h"
#include "HttpRequest.h"
#include "log/File.h"
#include "log/Formats.h"
-#include "log/Gadgets.h"
-#include "log/Tokens.h"
#include "SquidTime.h"
void
{
char clientip[MAX_IPSTRLEN];
- const char *user_ident = FormatName(al->cache.rfc931);
+ const char *user_ident = ::Format::QuoteUrlEncodeUsername(al->cache.rfc931);
- const char *user_auth = FormatName(al->cache.authuser);
+ const char *user_auth = ::Format::QuoteUrlEncodeUsername(al->cache.authuser);
const char *referer = al->request->header.getStr(HDR_REFERER);
if (!referer || *referer == '\0')
al->cache.replySize,
referer,
agent,
- log_tags[al->cache.code],
+ ::Format::log_tags[al->cache.code],
al->http.statusSfx(),
hier_code_str[al->hier.code],
(Config.onoff.log_mime_hdrs?"":"\n"));
safe_free(user_auth);
if (Config.onoff.log_mime_hdrs) {
- char *ereq = QuoteMimeBlob(al->headers.request);
- char *erep = QuoteMimeBlob(al->headers.reply);
+ char *ereq = ::Format::QuoteMimeBlob(al->headers.request);
+ char *erep = ::Format::QuoteMimeBlob(al->headers.reply);
logfilePrintf(logfile, " [%s] [%s]\n", ereq, erep);
safe_free(ereq);
safe_free(erep);
#include "config.h"
#include "AccessLogEntry.h"
+#include "format/Quoting.h"
+#include "format/Tokens.h"
#include "log/File.h"
#include "log/Formats.h"
-#include "log/Gadgets.h"
-#include "log/Tokens.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);
+ const char *user_auth = ::Format::QuoteUrlEncodeUsername(al->cache.authuser);
+ const char *user_ident = ::Format::QuoteUrlEncodeUsername(al->cache.rfc931);
logfilePrintf(logfile, "%s %s %s [%s] \"%s %s %s/%d.%d\" %d %"PRId64" %s%s:%s%s",
al->cache.caddr.NtoA(clientip,MAX_IPSTRLEN),
al->http.version.major, al->http.version.minor,
al->http.code,
al->cache.replySize,
- log_tags[al->cache.code],
+ ::Format::log_tags[al->cache.code],
al->http.statusSfx(),
hier_code_str[al->hier.code],
(Config.onoff.log_mime_hdrs?"":"\n"));
safe_free(user_ident);
if (Config.onoff.log_mime_hdrs) {
- char *ereq = QuoteMimeBlob(al->headers.request);
- char *erep = QuoteMimeBlob(al->headers.reply);
+ char *ereq = ::Format::QuoteMimeBlob(al->headers.request);
+ char *erep = ::Format::QuoteMimeBlob(al->headers.reply);
logfilePrintf(logfile, " [%s] [%s]\n", ereq, erep);
safe_free(ereq);
safe_free(erep);
#include "config.h"
#include "AccessLogEntry.h"
-#include "comm/Connection.h"
+#include "format/Tokens.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:
- // TODO make the ACL checklist have a direct link to any TCP details.
- if (al->request && al->request->clientConnectionManager.valid() && al->request->clientConnectionManager->clientConnection != NULL) {
- if (al->request->clientConnectionManager->clientConnection->remote.IsIPv4())
- al->request->clientConnectionManager->clientConnection->remoteEui48.encode(tmp, 1024);
- else
- al->request->clientConnectionManager->clientConnection->remoteEui64.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,sizeof(tmp));
- }
-
- break;
-
- case LFT_LOCAL_PORT:
- if (al->request) {
- outint = al->request->my_addr.GetPort();
- doint = 1;
- }
-
- break;
-
- // the fmt->type can not be LFT_PEER_LOCAL_IP_OLD_27
- // but compiler complains if ommited
- case LFT_PEER_LOCAL_IP_OLD_27:
- case LFT_PEER_LOCAL_IP:
- if (!al->hier.peer_local_addr.IsAnyAddr()) {
- out = al->hier.peer_local_addr.NtoA(tmp,sizeof(tmp));
- }
- break;
-
- case LFT_PEER_LOCAL_PORT:
- if ((outint = al->hier.peer_local_addr.GetPort())) {
- 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;
-
- case LFT_ADAPTATION_LAST_HEADER:
- if (al->request) {
- const Adaptation::History::Pointer ah = al->request->adaptHistory();
- if (ah != NULL) // XXX: add adapt::<all_h but use lastMeta here
- sb = ah->allMeta.getByName(fmt->data.header.header);
- }
-
- // XXX: here and elsewhere: move such code inside the if guard
- out = sb.termedBuf();
-
- quote = 1;
-
- break;
-
- case LFT_ADAPTATION_LAST_HEADER_ELEM:
- if (al->request) {
- const Adaptation::History::Pointer ah = al->request->adaptHistory();
- if (ah != NULL) // XXX: add adapt::<all_h but use lastMeta here
- sb = ah->allMeta.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
- }
-
- out = sb.termedBuf();
-
- quote = 1;
-
- break;
-
- case LFT_ADAPTATION_LAST_ALL_HEADERS:
- out = al->adapt.last_meta;
-
- quote = 1;
-
- break;
-#endif
-
-#if ICAP_CLIENT
- 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_CLIENT_REQ_METHOD:
- if (al->request) {
- out = al->request->method.image();
- quote = 1;
- }
- break;
-
- case LFT_CLIENT_REQ_URI:
- // original client URI
- if (al->request) {
- out = urlCanonical(al->request);
- quote = 1;
- }
- break;
-
- case LFT_REQUEST_URLPATH_OLD_31:
- case LFT_CLIENT_REQ_URLPATH:
- if (al->request) {
- out = al->request->urlpath.termedBuf();
- quote = 1;
- }
- break;
-
- case LFT_CLIENT_REQ_VERSION:
- if (al->request) {
- snprintf(tmp, sizeof(tmp), "%d.%d", (int) al->request->http_ver.major, (int) al->request->http_ver.minor);
- out = tmp;
- }
- break;
-
- case LFT_REQUEST_METHOD:
- out = al->_private.method_str;
- break;
-
- case LFT_REQUEST_URI:
- out = al->url;
- break;
-
- case LFT_REQUEST_VERSION_OLD_2X:
- 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_SERVER_REQ_METHOD:
- if (al->adapted_request) {
- out = al->adapted_request->method.image();
- quote = 1;
- }
- break;
-
- case LFT_SERVER_REQ_URI:
- // adapted request URI sent to server/peer
- if (al->adapted_request) {
- out = urlCanonical(al->adapted_request);
- quote = 1;
- }
- break;
-
- case LFT_SERVER_REQ_URLPATH:
- if (al->adapted_request) {
- out = al->adapted_request->urlpath.termedBuf();
- quote = 1;
- }
- break;
-
- case LFT_SERVER_REQ_VERSION:
- if (al->adapted_request) {
- snprintf(tmp, sizeof(tmp), "%d.%d",
- (int) al->adapted_request->http_ver.major,
- (int) al->adapted_request->http_ver.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);
- }
+ // XXX: because we do not yet have a neutral form of transaction slab. use AccessLogEntry
+ log->logFormat->assemble(mb, al, log->logfile->sequence_number);
- logfilePrintf(logfile, "%s\n", mb.buf);
+ logfilePrintf(log->logfile, "%s\n", mb.buf);
}
#if ICAP_CLIENT
#include "AccessLogEntry.h"
+#include "format/Quoting.h"
#include "HttpRequest.h"
#include "log/File.h"
#include "log/Formats.h"
-#include "log/Gadgets.h"
#include "SquidTime.h"
void
client = al->cache.caddr.NtoA(clientbuf, MAX_IPSTRLEN);
}
- user = Log::FormatName(al->cache.authuser);
+ user = ::Format::QuoteUrlEncodeUsername(al->cache.authuser);
if (!user)
- user = Log::FormatName(al->cache.extuser);
+ user = ::Format::QuoteUrlEncodeUsername(al->cache.extuser);
#if USE_SSL
if (!user)
- user = Log::FormatName(al->cache.ssluser);
+ user = ::Format::QuoteUrlEncodeUsername(al->cache.ssluser);
#endif
if (!user)
- user = Log::FormatName(al->cache.rfc931);
+ user = ::Format::QuoteUrlEncodeUsername(al->cache.rfc931);
if (user && !*user)
safe_free(user);
#include "config.h"
#include "AccessLogEntry.h"
+#include "format/Quoting.h"
+#include "format/Tokens.h"
#include "log/File.h"
#include "log/Formats.h"
-#include "log/Gadgets.h"
-#include "log/Tokens.h"
#include "SquidTime.h"
void
const char *user = NULL;
char clientip[MAX_IPSTRLEN];
- user = FormatName(al->cache.authuser);
+ user = ::Format::QuoteUrlEncodeUsername(al->cache.authuser);
if (!user)
- user = FormatName(al->cache.extuser);
+ user = ::Format::QuoteUrlEncodeUsername(al->cache.extuser);
#if USE_SSL
if (!user)
- user = FormatName(al->cache.ssluser);
+ user = ::Format::QuoteUrlEncodeUsername(al->cache.ssluser);
#endif
if (!user)
- user = FormatName(al->cache.rfc931);
+ user = ::Format::QuoteUrlEncodeUsername(al->cache.rfc931);
if (user && !*user)
safe_free(user);
(int) current_time.tv_usec / 1000,
al->cache.msec,
al->cache.caddr.NtoA(clientip, MAX_IPSTRLEN),
- log_tags[al->cache.code],
+ ::Format::log_tags[al->cache.code],
al->http.statusSfx(),
al->http.code,
al->cache.replySize,
safe_free(user);
if (Config.onoff.log_mime_hdrs) {
- char *ereq = QuoteMimeBlob(al->headers.request);
- char *erep = QuoteMimeBlob(al->headers.reply);
+ char *ereq = ::Format::QuoteMimeBlob(al->headers.request);
+ char *erep = ::Format::QuoteMimeBlob(al->headers.reply);
logfilePrintf(logfile, " [%s] [%s]\n", ereq, erep);
safe_free(ereq);
safe_free(erep);
FormatSquidNative.cc \
FormatSquidReferer.cc \
FormatSquidUseragent.cc \
- Gadgets.cc \
- Gadgets.h \
ModDaemon.cc \
ModDaemon.h \
ModStdio.cc \
ModTcp.cc \
ModTcp.h \
ModUdp.cc \
- ModUdp.h \
- Tokens.cc \
- Tokens.h
+ ModUdp.h
+++ /dev/null
-/*
- * $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},
-
- {"la", LFT_LOCAL_IP},
- {"lp", LFT_LOCAL_PORT},
- /*{ "lA", LFT_LOCAL_NAME }, */
-
- {"<la", LFT_PEER_LOCAL_IP},
- {"oa", LFT_PEER_LOCAL_IP_OLD_27},
- {"<lp", LFT_PEER_LOCAL_PORT},
- /* {"ot", LFT_PEER_OUTGOING_TOS}, */
-
- {"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_CLIENT_REQ_METHOD},
- {">ru", LFT_CLIENT_REQ_URI},
- {">rp", LFT_CLIENT_REQ_URLPATH},
- /*{">rq", LFT_CLIENT_REQ_QUERY},*/
- {">rv", LFT_CLIENT_REQ_VERSION},
-
- {"rm", LFT_REQUEST_METHOD},
- {"ru", LFT_REQUEST_URI}, /* doesn't include the query-string */
- {"rp", LFT_REQUEST_URLPATH_OLD_31},
- /* { "rq", LFT_REQUEST_QUERY }, * / / * the query-string, INCLUDING the leading ? */
- {">v", LFT_REQUEST_VERSION_OLD_2X},
- {"rv", LFT_REQUEST_VERSION},
-
- {"<rm", LFT_SERVER_REQ_METHOD},
- {"<ru", LFT_SERVER_REQ_URI},
- {"<rp", LFT_SERVER_REQ_URLPATH},
- /*{"<rq", LFT_SERVER_REQ_QUERY},*/
- {"<rv", LFT_SERVER_REQ_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},
- {"adapt::<last_h", LFT_ADAPTATION_LAST_HEADER},
-#endif
-
-#if ICAP_CLIENT
- {"icap::tt", LFT_ICAP_TOTAL_TIME},
- {"icap::<last_h", LFT_ADAPTATION_LAST_HEADER}, // deprecated
-
- {"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 USE_ADAPTATION
- case LFT_ADAPTATION_LAST_HEADER:
-#endif
-
-#if ICAP_CLIENT
- 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 USE_ADAPTATION
- case LFT_ADAPTATION_LAST_HEADER:
- lt->type = LFT_ADAPTATION_LAST_HEADER_ELEM;
- break;
-#endif
-#if ICAP_CLIENT
- 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 USE_ADAPTATION
- case LFT_ADAPTATION_LAST_HEADER:
- lt->type = LFT_ADAPTATION_LAST_ALL_HEADERS;
- break;
-#endif
-#if ICAP_CLIENT
- 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\" formatting code is deprecated. Use the \">Hs\" instead.");
- lt->type = LFT_HTTP_SENT_STATUS_CODE;
- break;
-
- case LFT_PEER_LOCAL_IP_OLD_27:
- debugs(46, 0, "WARNING: The \"oa\" formatting code is deprecated. Use the \"<la\" instead.");
- lt->type = LFT_PEER_LOCAL_IP;
- break;
-
- case LFT_REQUEST_URLPATH_OLD_31:
- debugs(46, 0, "WARNING: The \"rp\" formatting code is deprecated. Use the \">rp\" instead.");
- lt->type = LFT_CLIENT_REQ_URLPATH;
- break;
-
- case LFT_REQUEST_VERSION_OLD_2X:
- debugs(46, 0, "WARNING: The \">v\" formatting code is deprecated. Use the \">rv\" instead.");
- lt->type = LFT_REQUEST_VERSION;
- break;
-
- default:
- break;
- }
-
- return (cur - def);
-}
-
-int
-accessLogParseLogFormat(logformat_token ** fmt, char *def)
-{
- char *cur, *eos;
- logformat_token *new_lt, *last_lt;
- enum log_quote quote = LOG_QUOTE_NONE;
-
- debugs(46, 2, "accessLogParseLogFormat: got definition '" << def << "'");
-
- /* very inefficent parser, but who cares, this needs to be simple */
- /* First off, let's tokenize, we'll optimize in a second pass.
- * A token can either be a %-prefixed sequence (usually a dynamic
- * token but it can be an escaped sequence), or a string. */
- cur = def;
- eos = def + strlen(def);
- *fmt = new_lt = last_lt = (logformat_token *)xmalloc(sizeof(logformat_token));
- cur += accessLogGetNewLogFormatToken(new_lt, cur, "e);
-
- while (cur < eos) {
- new_lt = (logformat_token *)xmalloc(sizeof(logformat_token));
- last_lt->next = new_lt;
- last_lt = new_lt;
- cur += accessLogGetNewLogFormatToken(new_lt, cur, "e);
- }
-
- return 1;
-}
-
-void
-accessLogDumpLogFormat(StoreEntry * entry, const char *name, logformat * definitions)
-{
- logformat_token *t;
- logformat *format;
-
- struct logformat_token_table_entry *te;
- debugs(46, 4, "accessLogDumpLogFormat called");
-
- for (format = definitions; format; format = format->next) {
- debugs(46, 3, "Dumping logformat definition for " << format->name);
- storeAppendPrintf(entry, "logformat %s ", format->name);
-
- for (t = format->format; t; t = t->next) {
- if (t->type == LFT_STRING)
- storeAppendPrintf(entry, "%s", t->data.string);
- else {
- char argbuf[256];
- char *arg = NULL;
- logformat_bcode_t type = t->type;
-
- switch (type) {
- /* special cases */
-
- case LFT_STRING:
- break;
-#if USE_ADAPTATION
- case LFT_ADAPTATION_LAST_HEADER_ELEM:
-#endif
-#if ICAP_CLIENT
- 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; // XXX: remove _ELEM?
- break;
- case LFT_ADAPTED_REQUEST_HEADER_ELEM:
- type = LFT_ADAPTED_REQUEST_HEADER_ELEM; // XXX: remove _ELEM?
- break;
- case LFT_REPLY_HEADER_ELEM:
- type = LFT_REPLY_HEADER_ELEM; // XXX: remove _ELEM?
- break;
-#if USE_ADAPTATION
- case LFT_ADAPTATION_LAST_HEADER_ELEM:
- type = LFT_ADAPTATION_LAST_HEADER;
- break;
-#endif
-#if ICAP_CLIENT
- 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 USE_ADAPTATION
- case LFT_ADAPTATION_LAST_ALL_HEADERS:
-#endif
-#if ICAP_CLIENT
- 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 USE_ADAPTATION
- case LFT_ADAPTATION_LAST_ALL_HEADERS:
- type = LFT_ADAPTATION_LAST_HEADER;
- break;
-#endif
-#if ICAP_CLIENT
- 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);
-}
#include "eui/Eui48.h"
#include "eui/Eui64.h"
#endif
+#include "format/Tokens.h"
#include "hier_code.h"
#include "HttpReply.h"
#include "HttpRequest.h"
+#include "log/Config.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"
accessLogRegisterWithCacheManager();
#if USE_ADAPTATION
- alLogformatHasAdaptToken = false;
+ Log::TheConfig.hasAdaptToken = false;
#endif
#if ICAP_CLIENT
- alLogformatHasIcapToken = false;
+ Log::TheConfig.hasIcapToken = false;
#endif
for (log = Config.Log.accesslogs; log; log = log->next) {
LogfileStatus = LOG_ENABLE;
#if USE_ADAPTATION
- for (logformat_token * curr_token = (log->logFormat?log->logFormat->format:NULL); curr_token; curr_token = curr_token->next) {
- if (curr_token->type == LTF_ADAPTATION_SUM_XACT_TIMES ||
- curr_token->type == LTF_ADAPTATION_ALL_XACT_TIMES ||
- curr_token->type == LFT_ADAPTATION_LAST_HEADER ||
- curr_token->type == LFT_ADAPTATION_LAST_HEADER_ELEM ||
- curr_token->type == LFT_ADAPTATION_LAST_ALL_HEADERS) {
- alLogformatHasAdaptToken = true;
+ for (Format::Token * curr_token = (log->logFormat?log->logFormat->format:NULL); curr_token; curr_token = curr_token->next) {
+ if (curr_token->type == Format::LTF_ADAPTATION_SUM_XACT_TIMES ||
+ curr_token->type == Format::LTF_ADAPTATION_ALL_XACT_TIMES ||
+ curr_token->type == Format::LFT_ADAPTATION_LAST_HEADER ||
+ curr_token->type == Format::LFT_ADAPTATION_LAST_HEADER_ELEM ||
+ curr_token->type == Format::LFT_ADAPTATION_LAST_ALL_HEADERS) {
+ Log::TheConfig.hasAdaptToken = true;
}
#if ICAP_CLIENT
- if (curr_token->type == LFT_ICAP_TOTAL_TIME) {
- alLogformatHasIcapToken = true;
+ if (curr_token->type == Format::LFT_ICAP_TOTAL_TIME) {
+ Log::TheConfig.hasIcapToken = true;
}
#endif
}
#include "squid.h"
#include "event.h"
+#include "format/Tokens.h"
#include "StoreClient.h"
#if USE_AUTH
#include "auth/UserRequest.h"
#include "mgr/Registration.h"
#include "Store.h"
#include "HttpRequest.h"
-#include "log/Tokens.h"
#include "MemObject.h"
#include "fde.h"
#include "mem_node.h"
}
storeAppendPrintf(s, "uri %s\n", http->uri);
- storeAppendPrintf(s, "logType %s\n", log_tags[http->logType]);
+ storeAppendPrintf(s, "logType %s\n", Format::log_tags[http->logType]);
storeAppendPrintf(s, "out.offset %ld, out.size %lu\n",
(long int) http->out.offset, (unsigned long int) http->out.size);
storeAppendPrintf(s, "req_sz %ld\n", (long int) http->req_sz);
*/
#include "squid.h"
+#include "format/Tokens.h"
#include "HttpReply.h"
#include "log/File.h"
-#include "log/Tokens.h"
#include "MemObject.h"
#include "mgr/Registration.h"
#include "Store.h"
};
class Logfile;
-class logformat;
+#include "format/Format.h"
#include "log/Formats.h"
struct _customlog {
char *filename;
ACLList *aclList;
- logformat *logFormat;
+ Format::Format *logFormat;
Logfile *logfile;
customlog *next;
Log::Format::log_type type;