]> git.ipfire.org Git - thirdparty/squid.git/blame - src/format/Token.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / format / Token.cc
CommitLineData
bbc27441 1/*
ef57eb7b 2 * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
bbc27441
AJ
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
f7f3304a 9#include "squid.h"
31971e6a
AJ
10#include "format/Config.h"
11#include "format/Token.h"
12#include "format/TokenTableEntry.h"
d87e94f8 13#include "globals.h"
4d5904f7 14#include "SquidConfig.h"
38e16f92
AJ
15#include "Store.h"
16
aa99e35e
AJ
17// Due to token overlaps between 1 and 2 letter tokens (Bug 3310)
18// We split the token table into sets determined by the token length
4ea0c6ab
A
19namespace Format
20{
aa99e35e
AJ
21
22/// 1-char tokens.
31971e6a 23static TokenTableEntry TokenTable1C[] = {
38e16f92 24
95cc1e3e
FC
25 TokenTableEntry(">a", LFT_CLIENT_IP_ADDRESS),
26 TokenTableEntry(">p", LFT_CLIENT_PORT),
27 TokenTableEntry(">A", LFT_CLIENT_FQDN),
38e16f92 28
95cc1e3e
FC
29 TokenTableEntry("<a", LFT_SERVER_IP_ADDRESS),
30 TokenTableEntry("<p", LFT_SERVER_PORT),
31 TokenTableEntry("<A", LFT_SERVER_FQDN_OR_PEER_NAME),
38e16f92 32
95cc1e3e
FC
33 TokenTableEntry(">h", LFT_REQUEST_HEADER),
34 TokenTableEntry(">h", LFT_REQUEST_ALL_HEADERS),
35 TokenTableEntry("<h", LFT_REPLY_HEADER),
36 TokenTableEntry("<h", LFT_REPLY_ALL_HEADERS),
aa99e35e 37
95cc1e3e 38 TokenTableEntry(">v", LFT_REQUEST_VERSION_OLD_2X),
aa99e35e 39
95cc1e3e 40 TokenTableEntry("%", LFT_PERCENT),
aa99e35e 41
95cc1e3e 42 TokenTableEntry(NULL, LFT_NONE) /* this must be last */
aa99e35e
AJ
43};
44
45/// 2-char tokens
31971e6a 46static TokenTableEntry TokenTable2C[] = {
aa99e35e 47
95cc1e3e
FC
48 TokenTableEntry(">la", LFT_CLIENT_LOCAL_IP),
49 TokenTableEntry("la", LFT_LOCAL_LISTENING_IP),
50 TokenTableEntry(">lp", LFT_CLIENT_LOCAL_PORT),
51 TokenTableEntry("lp", LFT_LOCAL_LISTENING_PORT),
52 /*TokenTableEntry( "lA", LFT_LOCAL_NAME ), */
53
54 TokenTableEntry("<la", LFT_SERVER_LOCAL_IP),
55 TokenTableEntry("oa", LFT_SERVER_LOCAL_IP_OLD_27),
56 TokenTableEntry("<lp", LFT_SERVER_LOCAL_PORT),
57
58 TokenTableEntry("ts", LFT_TIME_SECONDS_SINCE_EPOCH),
59 TokenTableEntry("tu", LFT_TIME_SUBSECOND),
60 TokenTableEntry("tl", LFT_TIME_LOCALTIME),
61 TokenTableEntry("tg", LFT_TIME_GMT),
62 TokenTableEntry("tS", LFT_TIME_START),
63 TokenTableEntry("tr", LFT_TIME_TO_HANDLE_REQUEST),
64
65 TokenTableEntry("<pt", LFT_PEER_RESPONSE_TIME),
66 TokenTableEntry("<tt", LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME),
67 TokenTableEntry("dt", LFT_DNS_WAIT_TIME),
68
69 TokenTableEntry(">ha", LFT_ADAPTED_REQUEST_HEADER),
70 TokenTableEntry(">ha", LFT_ADAPTED_REQUEST_ALL_HEADERS),
71
72 TokenTableEntry("un", LFT_USER_NAME),
73 TokenTableEntry("ul", LFT_USER_LOGIN),
74 /*TokenTableEntry( "ur", LFT_USER_REALM ), */
75 /*TokenTableEntry( "us", LFT_USER_SCHEME ), */
76 TokenTableEntry("ui", LFT_USER_IDENT),
77 TokenTableEntry("ue", LFT_USER_EXTERNAL),
78
79 TokenTableEntry("Hs", LFT_HTTP_SENT_STATUS_CODE_OLD_30),
80 TokenTableEntry(">Hs", LFT_HTTP_SENT_STATUS_CODE),
81 TokenTableEntry("<Hs", LFT_HTTP_RECEIVED_STATUS_CODE),
82 /*TokenTableEntry( "Ht", LFT_HTTP_STATUS ), */
83 TokenTableEntry("<bs", LFT_HTTP_BODY_BYTES_READ),
84
85 TokenTableEntry("Ss", LFT_SQUID_STATUS),
86 TokenTableEntry("Sh", LFT_SQUID_HIERARCHY),
87
88 TokenTableEntry("mt", LFT_MIME_TYPE),
89
90 TokenTableEntry(">rm", LFT_CLIENT_REQ_METHOD),
91 TokenTableEntry(">ru", LFT_CLIENT_REQ_URI),
92 TokenTableEntry(">rs", LFT_CLIENT_REQ_URLSCHEME),
93 TokenTableEntry(">rd", LFT_CLIENT_REQ_URLDOMAIN),
94 TokenTableEntry(">rP", LFT_CLIENT_REQ_URLPORT),
95 TokenTableEntry(">rp", LFT_CLIENT_REQ_URLPATH),
96 /*TokenTableEntry(">rq", LFT_CLIENT_REQ_QUERY),*/
97 TokenTableEntry(">rv", LFT_CLIENT_REQ_VERSION),
98
99 TokenTableEntry("rm", LFT_REQUEST_METHOD),
100 TokenTableEntry("ru", LFT_REQUEST_URI), /* doesn't include the query-string */
101 TokenTableEntry("rp", LFT_REQUEST_URLPATH_OLD_31),
102 /* TokenTableEntry( "rq", LFT_REQUEST_QUERY ), * / / * the query-string, INCLUDING the leading ? */
103 TokenTableEntry("rv", LFT_REQUEST_VERSION),
104 TokenTableEntry("rG", LFT_REQUEST_URLGROUP_OLD_2X),
105
106 TokenTableEntry("<rm", LFT_SERVER_REQ_METHOD),
107 TokenTableEntry("<ru", LFT_SERVER_REQ_URI),
108 TokenTableEntry("<rs", LFT_SERVER_REQ_URLSCHEME),
109 TokenTableEntry("<rd", LFT_SERVER_REQ_URLDOMAIN),
110 TokenTableEntry("<rP", LFT_SERVER_REQ_URLPORT),
111 TokenTableEntry("<rp", LFT_SERVER_REQ_URLPATH),
112 /*TokenTableEntry("<rq", LFT_SERVER_REQ_QUERY),*/
113 TokenTableEntry("<rv", LFT_SERVER_REQ_VERSION),
114
115 TokenTableEntry(">st", LFT_CLIENT_REQUEST_SIZE_TOTAL ),
116 TokenTableEntry(">sh", LFT_CLIENT_REQUEST_SIZE_HEADERS ),
117 /*TokenTableEntry( ">sb", LFT_REQUEST_SIZE_BODY ), */
118 /*TokenTableEntry( ">sB", LFT_REQUEST_SIZE_BODY_NO_TE ), */
119
120 TokenTableEntry("<st", LFT_ADAPTED_REPLY_SIZE_TOTAL), // XXX: adapted should be code: <sta
121 TokenTableEntry("<sH", LFT_REPLY_HIGHOFFSET),
122 TokenTableEntry("<sS", LFT_REPLY_OBJECTSIZE),
123 TokenTableEntry("<sh", LFT_ADAPTED_REPLY_SIZE_HEADERS ), // XXX: adapted should be code: <sha
124 /*TokenTableEntry( "<sb", LFT_REPLY_SIZE_BODY ), */
125 /*TokenTableEntry( "<sB", LFT_REPLY_SIZE_BODY_NO_TE ), */
126
127 TokenTableEntry("st", LFT_CLIENT_IO_SIZE_TOTAL), // XXX: total from client should be stC ??
128 /*TokenTableEntry("stP", LFT_SERVER_IO_SIZE_TOTAL),*/
129
130 TokenTableEntry("et", LFT_TAG),
131 TokenTableEntry("ea", LFT_EXT_LOG),
132 TokenTableEntry("sn", LFT_SEQUENCE_NUMBER),
133
134 TokenTableEntry(NULL, LFT_NONE) /* this must be last */
aa99e35e 135};
38e16f92 136
31971e6a
AJ
137/// Miscellaneous >2 byte tokens
138static TokenTableEntry TokenTableMisc[] = {
95cc1e3e
FC
139 TokenTableEntry(">eui", LFT_CLIENT_EUI),
140 TokenTableEntry(">qos", LFT_CLIENT_LOCAL_TOS),
141 TokenTableEntry("<qos", LFT_SERVER_LOCAL_TOS),
142 TokenTableEntry(">nfmark", LFT_CLIENT_LOCAL_NFMARK),
143 TokenTableEntry("<nfmark", LFT_SERVER_LOCAL_NFMARK),
144 TokenTableEntry("err_code", LFT_SQUID_ERROR ),
145 TokenTableEntry("err_detail", LFT_SQUID_ERROR_DETAIL ),
146 TokenTableEntry("note", LFT_NOTE ),
147 TokenTableEntry("credentials", LFT_CREDENTIALS),
4e56d7f6
AJ
148 /*
149 * Legacy external_acl_type format tokens
150 */
151 TokenTableEntry("ACL", LFT_EXT_ACL_NAME),
152 TokenTableEntry("DATA", LFT_EXT_ACL_DATA),
153 TokenTableEntry("DST", LFT_CLIENT_REQ_URLDOMAIN),
154 TokenTableEntry("EXT_LOG", LFT_EXT_LOG),
155 TokenTableEntry("EXT_USER", LFT_USER_EXTERNAL),
156 TokenTableEntry("IDENT", LFT_USER_IDENT),
157 TokenTableEntry("LOGIN", LFT_USER_LOGIN),
158 TokenTableEntry("METHOD", LFT_CLIENT_REQ_METHOD),
159 TokenTableEntry("MYADDR", LFT_LOCAL_LISTENING_IP),
160 TokenTableEntry("MYPORT", LFT_LOCAL_LISTENING_PORT),
161 TokenTableEntry("PATH", LFT_CLIENT_REQ_URLPATH),
162 TokenTableEntry("PORT", LFT_CLIENT_REQ_URLPORT),
163 TokenTableEntry("PROTO", LFT_CLIENT_REQ_URLSCHEME),
164 TokenTableEntry("SRCEUI48", LFT_EXT_ACL_CLIENT_EUI48),
165 TokenTableEntry("SRCEUI64", LFT_EXT_ACL_CLIENT_EUI64),
166 TokenTableEntry("SRCPORT", LFT_CLIENT_PORT),
167 TokenTableEntry("SRC", LFT_CLIENT_IP_ADDRESS), // keep after longer SRC* tokens
168 TokenTableEntry("TAG", LFT_TAG),
169 TokenTableEntry("URI", LFT_CLIENT_REQ_URI),
ce810e33 170#if USE_OPENSSL
4e56d7f6
AJ
171 TokenTableEntry("USER_CERTCHAIN", LFT_EXT_ACL_USER_CERTCHAIN_RAW),
172 TokenTableEntry("USER_CERT", LFT_EXT_ACL_USER_CERT_RAW),
ce810e33 173#endif
95cc1e3e 174 TokenTableEntry(NULL, LFT_NONE) /* this must be last */
31971e6a
AJ
175};
176
38e16f92 177#if USE_ADAPTATION
31971e6a 178static TokenTableEntry TokenTableAdapt[] = {
95cc1e3e
FC
179 TokenTableEntry("all_trs", LFT_ADAPTATION_ALL_XACT_TIMES),
180 TokenTableEntry("sum_trs", LFT_ADAPTATION_SUM_XACT_TIMES),
181 TokenTableEntry("<last_h", LFT_ADAPTATION_LAST_HEADER),
182 TokenTableEntry(NULL, LFT_NONE) /* this must be last */
aa99e35e 183};
38e16f92
AJ
184#endif
185
186#if ICAP_CLIENT
aa99e35e 187/// ICAP (icap::) tokens
31971e6a 188static TokenTableEntry TokenTableIcap[] = {
95cc1e3e
FC
189 TokenTableEntry("tt", LFT_ICAP_TOTAL_TIME),
190 TokenTableEntry("<last_h", LFT_ADAPTATION_LAST_HEADER), // deprecated
191
192 TokenTableEntry("<A", LFT_ICAP_ADDR),
193 TokenTableEntry("<service_name", LFT_ICAP_SERV_NAME),
194 TokenTableEntry("ru", LFT_ICAP_REQUEST_URI),
195 TokenTableEntry("rm", LFT_ICAP_REQUEST_METHOD),
196 TokenTableEntry(">st", LFT_ICAP_BYTES_SENT),
197 TokenTableEntry("<st", LFT_ICAP_BYTES_READ),
198 TokenTableEntry("<bs", LFT_ICAP_BODY_BYTES_READ),
199
200 TokenTableEntry(">h", LFT_ICAP_REQ_HEADER),
201 TokenTableEntry("<h", LFT_ICAP_REP_HEADER),
202
203 TokenTableEntry("tr", LFT_ICAP_TR_RESPONSE_TIME),
204 TokenTableEntry("tio", LFT_ICAP_IO_TIME),
205 TokenTableEntry("to", LFT_ICAP_OUTCOME),
206 TokenTableEntry("Hs", LFT_ICAP_STATUS_CODE),
207
208 TokenTableEntry(NULL, LFT_NONE) /* this must be last */
aa99e35e 209};
38e16f92
AJ
210#endif
211
cb4f4424 212#if USE_OPENSSL
08097970
AR
213// SSL (ssl::) tokens
214static TokenTableEntry TokenTableSsl[] = {
95cc1e3e
FC
215 TokenTableEntry("bump_mode", LFT_SSL_BUMP_MODE),
216 TokenTableEntry(">cert_subject", LFT_SSL_USER_CERT_SUBJECT),
217 TokenTableEntry(">cert_issuer", LFT_SSL_USER_CERT_ISSUER),
218 TokenTableEntry(">sni", LFT_SSL_CLIENT_SNI),
219 /*TokenTableEntry("<cert_subject", LFT_SSL_SERVER_CERT_SUBJECT), */
220 /*TokenTableEntry("<cert_issuer", LFT_SSL_SERVER_CERT_ISSUER), */
7598eb63 221 TokenTableEntry("<cert_errors", LFT_SSL_SERVER_CERT_ERRORS),
2bcab852
CT
222 TokenTableEntry(">negotiated_version", LFT_TLS_CLIENT_NEGOTIATED_VERSION),
223 TokenTableEntry("<negotiated_version", LFT_TLS_SERVER_NEGOTIATED_VERSION),
224 TokenTableEntry(">negotiated_cipher", LFT_TLS_CLIENT_NEGOTIATED_CIPHER),
225 TokenTableEntry("<negotiated_cipher", LFT_TLS_SERVER_NEGOTIATED_CIPHER),
226 TokenTableEntry(">received_hello_version", LFT_TLS_CLIENT_RECEIVED_HELLO_VERSION),
227 TokenTableEntry("<received_hello_version", LFT_TLS_SERVER_RECEIVED_HELLO_VERSION),
228 TokenTableEntry(">received_supported_version", LFT_TLS_CLIENT_SUPPORTED_VERSION),
229 TokenTableEntry("<received_supported_version", LFT_TLS_SERVER_SUPPORTED_VERSION),
95cc1e3e 230 TokenTableEntry(NULL, LFT_NONE)
08097970
AR
231};
232#endif
aa99e35e
AJ
233} // namespace Format
234
31971e6a
AJ
235/// Register all components custom format tokens
236void
237Format::Token::Init()
238{
239 // TODO standard log tokens
31971e6a
AJ
240
241#if USE_ADAPTATION
242 TheConfig.registerTokens(String("adapt"),::Format::TokenTableAdapt);
243#endif
244#if ICAP_CLIENT
245 TheConfig.registerTokens(String("icap"),::Format::TokenTableIcap);
246#endif
cb4f4424 247#if USE_OPENSSL
08097970
AR
248 TheConfig.registerTokens(String("ssl"),::Format::TokenTableSsl);
249#endif
31971e6a
AJ
250}
251
aa99e35e
AJ
252/// Scans a token table to see if the next token exists there
253/// returns a pointer to next unparsed byte and updates type member if found
f4698e0b
CT
254const char *
255Format::Token::scanForToken(TokenTableEntry const table[], const char *cur)
aa99e35e 256{
cb4185f1 257 for (TokenTableEntry const *lte = table; lte->configTag != NULL; ++lte) {
31971e6a
AJ
258 debugs(46, 8, HERE << "compare tokens '" << lte->configTag << "' with '" << cur << "'");
259 if (strncmp(lte->configTag, cur, strlen(lte->configTag)) == 0) {
260 type = lte->tokenType;
261 label = lte->configTag;
aa99e35e 262 debugs(46, 7, HERE << "Found token '" << label << "'");
31971e6a 263 return cur + strlen(lte->configTag);
aa99e35e
AJ
264 }
265 }
266 return cur;
267}
268
38e16f92
AJ
269/* parses a single token. Returns the token length in characters,
270 * and fills in the lt item with the token information.
271 * def is for sure null-terminated
272 */
273int
f4698e0b 274Format::Token::parse(const char *def, Quoting *quoting)
38e16f92 275{
f4698e0b 276 const char *cur = def;
38e16f92 277
38e16f92
AJ
278 int l;
279
280 l = strcspn(cur, "%");
281
282 if (l > 0) {
283 char *cp;
284 /* it's a string for sure, until \0 or the next % */
285 cp = (char *)xmalloc(l + 1);
286 xstrncpy(cp, cur, l + 1);
287 type = LFT_STRING;
288 data.string = cp;
289
290 while (l > 0) {
291 switch (*cur) {
292
293 case '"':
294
295 if (*quoting == LOG_QUOTE_NONE)
296 *quoting = LOG_QUOTE_QUOTES;
297 else if (*quoting == LOG_QUOTE_QUOTES)
298 *quoting = LOG_QUOTE_NONE;
299
300 break;
301
302 case '[':
303 if (*quoting == LOG_QUOTE_NONE)
304 *quoting = LOG_QUOTE_MIMEBLOB;
305
306 break;
307
308 case ']':
309 if (*quoting == LOG_QUOTE_MIMEBLOB)
310 *quoting = LOG_QUOTE_NONE;
311
312 break;
313 }
314
cb4185f1
FC
315 ++cur;
316 --l;
38e16f92
AJ
317 }
318
22473932 319 } else if (*cur) {
38e16f92 320
cb4185f1 321 ++cur;
38e16f92 322
22473932
AJ
323 // select quoting style for his particular token
324 switch (*cur) {
38e16f92 325
22473932
AJ
326 case '"':
327 quote = LOG_QUOTE_QUOTES;
328 ++cur;
329 break;
38e16f92 330
22473932
AJ
331 case '\'':
332 quote = LOG_QUOTE_RAW;
333 ++cur;
334 break;
38e16f92 335
22473932
AJ
336 case '[':
337 quote = LOG_QUOTE_MIMEBLOB;
338 ++cur;
339 break;
38e16f92 340
22473932
AJ
341 case '#':
342 quote = LOG_QUOTE_URL;
343 ++cur;
344 break;
38e16f92 345
22473932
AJ
346 default:
347 quote = *quoting;
348 break;
349 }
38e16f92 350
22473932
AJ
351 if (*cur == '-') {
352 left = true;
353 ++cur;
354 }
38e16f92 355
22473932
AJ
356 if (*cur == '0') {
357 zero = true;
cb4185f1 358 ++cur;
22473932 359 }
38e16f92 360
22473932
AJ
361 char *endp;
362 if (xisdigit(*cur)) {
363 widthMin = strtol(cur, &endp, 10);
364 cur = endp;
31971e6a 365 }
31971e6a 366
22473932
AJ
367 if (*cur == '.' && xisdigit(*(++cur))) {
368 widthMax = strtol(cur, &endp, 10);
369 cur = endp;
370 }
aa99e35e 371
4e56d7f6 372 // when {arg} field is before the token (old logformat syntax)
22473932
AJ
373 if (*cur == '{') {
374 char *cp;
375 ++cur;
376 l = strcspn(cur, "}");
377 cp = (char *)xmalloc(l + 1);
378 xstrncpy(cp, cur, l + 1);
379 data.string = cp;
380 cur += l;
381
382 if (*cur == '}')
383 ++cur;
384 }
aa99e35e 385
22473932
AJ
386 type = LFT_NONE;
387
388 // Scan each registered token namespace
389 debugs(46, 9, HERE << "check for token in " << TheConfig.tokens.size() << " namespaces.");
390 for (std::list<TokenNamespace>::const_iterator itr = TheConfig.tokens.begin(); itr != TheConfig.tokens.end(); ++itr) {
391 debugs(46, 7, HERE << "check for possible " << itr->prefix << ":: token");
392 const size_t len = itr->prefix.size();
393 if (itr->prefix.cmp(cur, len) == 0 && cur[len] == ':' && cur[len+1] == ':') {
394 debugs(46, 5, HERE << "check for " << itr->prefix << ":: token in '" << cur << "'");
395 const char *old = cur;
396 cur = scanForToken(itr->tokenSet, cur+len+2);
397 if (old != cur) // found
398 break;
399 else // reset to start of namespace
400 cur = cur - len - 2;
401 }
aa99e35e 402 }
22473932 403
aa99e35e 404 if (type == LFT_NONE) {
22473932
AJ
405 // For upward compatibility, assume "http::" prefix as default prefix
406 // for all log access formatting codes, except those starting with a
407 // "%" or a known namespace. (ie "icap::", "adapt::")
408 if (strncmp(cur,"http::", 6) == 0 && *(cur+6) != '%' )
409 cur += 6;
410
411 // NP: scan the sets of tokens in decreasing size to guarantee no
412 // mistakes made with overlapping names. (Bug 3310)
413
414 // Scan for various long tokens
415 debugs(46, 5, HERE << "scan for possible Misc token");
416 cur = scanForToken(TokenTableMisc, cur);
417 // scan for 2-char tokens
418 if (type == LFT_NONE) {
419 debugs(46, 5, HERE << "scan for possible 2C token");
420 cur = scanForToken(TokenTable2C, cur);
421 }
422 // finally scan for 1-char tokens.
423 if (type == LFT_NONE) {
424 debugs(46, 5, HERE << "scan for possible 1C token");
425 cur = scanForToken(TokenTable1C, cur);
426 }
38e16f92 427 }
38e16f92 428
22473932
AJ
429 if (type == LFT_NONE) {
430 fatalf("Can't parse configuration token: '%s'\n", def);
431 }
38e16f92 432
4e56d7f6
AJ
433 // when {arg} field is after the token (old external_acl_type token syntax)
434 // but accept only if there was none before the token
435 if (*cur == '{' && !data.string) {
436 char *cp;
437 ++cur;
438 l = strcspn(cur, "}");
439 cp = (char *)xmalloc(l + 1);
440 xstrncpy(cp, cur, l + 1);
441 data.string = cp;
442 cur += l;
443
444 if (*cur == '}')
445 ++cur;
446 }
447
22473932
AJ
448 if (*cur == ' ') {
449 space = true;
450 ++cur;
451 }
38e16f92
AJ
452 }
453
38e16f92
AJ
454 switch (type) {
455
456#if USE_ADAPTATION
457 case LFT_ADAPTATION_LAST_HEADER:
458#endif
459
460#if ICAP_CLIENT
461 case LFT_ICAP_REQ_HEADER:
462
463 case LFT_ICAP_REP_HEADER:
464#endif
465
466 case LFT_ADAPTED_REQUEST_HEADER:
467
468 case LFT_REQUEST_HEADER:
469
470 case LFT_REPLY_HEADER:
471
c7bcf010
CT
472 case LFT_NOTE:
473
38e16f92
AJ
474 if (data.string) {
475 char *header = data.string;
476 char *cp = strchr(header, ':');
477
478 if (cp) {
a38ec4b1
FC
479 *cp = '\0';
480 ++cp;
38e16f92 481
a38ec4b1
FC
482 if (*cp == ',' || *cp == ';' || *cp == ':') {
483 data.header.separator = *cp;
484 ++cp;
485 } else {
38e16f92 486 data.header.separator = ',';
a38ec4b1 487 }
38e16f92
AJ
488
489 data.header.element = cp;
490
491 switch (type) {
492 case LFT_REQUEST_HEADER:
493 type = LFT_REQUEST_HEADER_ELEM;
494 break;
495
496 case LFT_ADAPTED_REQUEST_HEADER:
497 type = LFT_ADAPTED_REQUEST_HEADER_ELEM;
498 break;
499
500 case LFT_REPLY_HEADER:
501 type = LFT_REPLY_HEADER_ELEM;
502 break;
503#if USE_ADAPTATION
504 case LFT_ADAPTATION_LAST_HEADER:
505 type = LFT_ADAPTATION_LAST_HEADER_ELEM;
506 break;
507#endif
508#if ICAP_CLIENT
509 case LFT_ICAP_REQ_HEADER:
510 type = LFT_ICAP_REQ_HEADER_ELEM;
511 break;
512 case LFT_ICAP_REP_HEADER:
513 type = LFT_ICAP_REP_HEADER_ELEM;
514 break;
515#endif
516 default:
517 break;
518 }
519 }
520
521 data.header.header = header;
522 } else {
523 switch (type) {
524 case LFT_REQUEST_HEADER:
525 type = LFT_REQUEST_ALL_HEADERS;
526 break;
527
528 case LFT_ADAPTED_REQUEST_HEADER:
529 type = LFT_ADAPTED_REQUEST_ALL_HEADERS;
530 break;
531
532 case LFT_REPLY_HEADER:
533 type = LFT_REPLY_ALL_HEADERS;
534 break;
535#if USE_ADAPTATION
536 case LFT_ADAPTATION_LAST_HEADER:
537 type = LFT_ADAPTATION_LAST_ALL_HEADERS;
538 break;
539#endif
540#if ICAP_CLIENT
541 case LFT_ICAP_REQ_HEADER:
542 type = LFT_ICAP_REQ_ALL_HEADERS;
543 break;
544 case LFT_ICAP_REP_HEADER:
545 type = LFT_ICAP_REP_ALL_HEADERS;
546 break;
547#endif
548 default:
549 break;
550 }
551 Config.onoff.log_mime_hdrs = 1;
552 }
553
554 break;
555
556 case LFT_CLIENT_FQDN:
557 Config.onoff.log_fqdn = 1;
558 break;
559
01bd87d8
CT
560 case LFT_TIME_TO_HANDLE_REQUEST:
561 case LFT_PEER_RESPONSE_TIME:
562 case LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME:
563 case LFT_DNS_WAIT_TIME:
ffac7e44 564#if ICAP_CLIENT
01bd87d8
CT
565 case LFT_ICAP_TR_RESPONSE_TIME:
566 case LFT_ICAP_IO_TIME:
567 case LFT_ICAP_TOTAL_TIME:
ffac7e44 568#endif
af0ded40 569 case LFT_TIME_START:
38e16f92
AJ
570 case LFT_TIME_SUBSECOND:
571 divisor = 1000;
572
8846a2b4 573 if (widthMax > 0) {
38e16f92
AJ
574 divisor = 1000000;
575
af0ded40 576 for (int i = widthMax; i > 0; --i)
38e16f92
AJ
577 divisor /= 10;
578
579 if (!divisor)
af0ded40 580 divisor = 1;
38e16f92 581 }
38e16f92
AJ
582 break;
583
584 case LFT_HTTP_SENT_STATUS_CODE_OLD_30:
874d775a 585 debugs(46, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: The \"Hs\" formatting code is deprecated. Use the \">Hs\" instead.");
38e16f92
AJ
586 type = LFT_HTTP_SENT_STATUS_CODE;
587 break;
588
8652f8e7 589 case LFT_SERVER_LOCAL_IP_OLD_27:
874d775a 590 debugs(46, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: The \"oa\" formatting code is deprecated. Use the \"<la\" instead.");
8652f8e7 591 type = LFT_SERVER_LOCAL_IP;
38e16f92
AJ
592 break;
593
594 case LFT_REQUEST_URLPATH_OLD_31:
874d775a 595 debugs(46, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: The \"rp\" formatting code is deprecated. Use the \">rp\" instead.");
38e16f92
AJ
596 type = LFT_CLIENT_REQ_URLPATH;
597 break;
598
599 case LFT_REQUEST_VERSION_OLD_2X:
874d775a 600 debugs(46, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: The \">v\" formatting code is deprecated. Use the \">rv\" instead.");
38e16f92
AJ
601 type = LFT_REQUEST_VERSION;
602 break;
603
8652f8e7
AJ
604#if !USE_SQUID_EUI
605 case LFT_CLIENT_EUI:
fa84c01d 606 debugs(46, DBG_CRITICAL, "WARNING: The \">eui\" formatting code requires EUI features which are disabled in this Squid.");
8652f8e7
AJ
607 break;
608#endif
609
2bcab852
CT
610#if USE_OPENSSL
611 case LFT_TLS_SERVER_NEGOTIATED_VERSION:
612 case LFT_TLS_SERVER_RECEIVED_HELLO_VERSION:
613 case LFT_TLS_SERVER_SUPPORTED_VERSION:
614 Config.onoff.logTlsServerHelloDetails = true;
615 break;
616#endif
617
d074f918
TT
618 case LFT_REQUEST_URLGROUP_OLD_2X:
619 debugs(46, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: The \"rG\" formatting code is deprecated. Use \"note{urlgroup}\" instead.");
620 type = LFT_NOTE;
621 data.header.header = xstrdup("urlgroup");
622 break;
623
38e16f92
AJ
624 default:
625 break;
626 }
627
628 return (cur - def);
629}
630
c7bcf010 631Format::Token::Token() : type(LFT_NONE),
f53969cc
SM
632 label(NULL),
633 widthMin(-1),
634 widthMax(-1),
635 quote(LOG_QUOTE_NONE),
636 left(false),
637 space(false),
638 zero(false),
639 divisor(1),
640 next(NULL)
c7bcf010
CT
641{
642 data.string = NULL;
e2849af8 643 data.header.header = NULL;
c7bcf010
CT
644 data.header.element = NULL;
645 data.header.separator = ',';
646}
647
38e16f92
AJ
648Format::Token::~Token()
649{
aa99e35e 650 label = NULL; // drop reference to global static.
38e16f92
AJ
651 safe_free(data.string);
652 while (next) {
653 Token *tokens = next;
654 next = next->next;
655 tokens->next = NULL;
656 delete tokens;
657 }
658}
659