]> git.ipfire.org Git - thirdparty/squid.git/blame - src/format/Token.cc
Docs: Copyright updates for 2018 (#114)
[thirdparty/squid.git] / src / format / Token.cc
CommitLineData
bbc27441 1/*
5b74111a 2 * Copyright (C) 1996-2018 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),
a96ea176 155 TokenTableEntry("EXT_TAG", LFT_TAG),
4e56d7f6
AJ
156 TokenTableEntry("EXT_USER", LFT_USER_EXTERNAL),
157 TokenTableEntry("IDENT", LFT_USER_IDENT),
158 TokenTableEntry("LOGIN", LFT_USER_LOGIN),
159 TokenTableEntry("METHOD", LFT_CLIENT_REQ_METHOD),
160 TokenTableEntry("MYADDR", LFT_LOCAL_LISTENING_IP),
161 TokenTableEntry("MYPORT", LFT_LOCAL_LISTENING_PORT),
162 TokenTableEntry("PATH", LFT_CLIENT_REQ_URLPATH),
163 TokenTableEntry("PORT", LFT_CLIENT_REQ_URLPORT),
164 TokenTableEntry("PROTO", LFT_CLIENT_REQ_URLSCHEME),
165 TokenTableEntry("SRCEUI48", LFT_EXT_ACL_CLIENT_EUI48),
166 TokenTableEntry("SRCEUI64", LFT_EXT_ACL_CLIENT_EUI64),
167 TokenTableEntry("SRCPORT", LFT_CLIENT_PORT),
168 TokenTableEntry("SRC", LFT_CLIENT_IP_ADDRESS), // keep after longer SRC* tokens
169 TokenTableEntry("TAG", LFT_TAG),
170 TokenTableEntry("URI", LFT_CLIENT_REQ_URI),
ce810e33 171#if USE_OPENSSL
4e56d7f6
AJ
172 TokenTableEntry("USER_CERTCHAIN", LFT_EXT_ACL_USER_CERTCHAIN_RAW),
173 TokenTableEntry("USER_CERT", LFT_EXT_ACL_USER_CERT_RAW),
ce810e33 174#endif
95cc1e3e 175 TokenTableEntry(NULL, LFT_NONE) /* this must be last */
31971e6a
AJ
176};
177
38e16f92 178#if USE_ADAPTATION
31971e6a 179static TokenTableEntry TokenTableAdapt[] = {
95cc1e3e
FC
180 TokenTableEntry("all_trs", LFT_ADAPTATION_ALL_XACT_TIMES),
181 TokenTableEntry("sum_trs", LFT_ADAPTATION_SUM_XACT_TIMES),
182 TokenTableEntry("<last_h", LFT_ADAPTATION_LAST_HEADER),
183 TokenTableEntry(NULL, LFT_NONE) /* this must be last */
aa99e35e 184};
38e16f92
AJ
185#endif
186
187#if ICAP_CLIENT
aa99e35e 188/// ICAP (icap::) tokens
31971e6a 189static TokenTableEntry TokenTableIcap[] = {
95cc1e3e
FC
190 TokenTableEntry("tt", LFT_ICAP_TOTAL_TIME),
191 TokenTableEntry("<last_h", LFT_ADAPTATION_LAST_HEADER), // deprecated
192
193 TokenTableEntry("<A", LFT_ICAP_ADDR),
194 TokenTableEntry("<service_name", LFT_ICAP_SERV_NAME),
195 TokenTableEntry("ru", LFT_ICAP_REQUEST_URI),
196 TokenTableEntry("rm", LFT_ICAP_REQUEST_METHOD),
197 TokenTableEntry(">st", LFT_ICAP_BYTES_SENT),
198 TokenTableEntry("<st", LFT_ICAP_BYTES_READ),
199 TokenTableEntry("<bs", LFT_ICAP_BODY_BYTES_READ),
200
201 TokenTableEntry(">h", LFT_ICAP_REQ_HEADER),
202 TokenTableEntry("<h", LFT_ICAP_REP_HEADER),
203
204 TokenTableEntry("tr", LFT_ICAP_TR_RESPONSE_TIME),
205 TokenTableEntry("tio", LFT_ICAP_IO_TIME),
206 TokenTableEntry("to", LFT_ICAP_OUTCOME),
207 TokenTableEntry("Hs", LFT_ICAP_STATUS_CODE),
208
209 TokenTableEntry(NULL, LFT_NONE) /* this must be last */
aa99e35e 210};
38e16f92
AJ
211#endif
212
cb4f4424 213#if USE_OPENSSL
1e2df2b7 214// TLS/SSL (tls:: or ssl::) tokens
08097970 215static TokenTableEntry TokenTableSsl[] = {
95cc1e3e
FC
216 TokenTableEntry("bump_mode", LFT_SSL_BUMP_MODE),
217 TokenTableEntry(">cert_subject", LFT_SSL_USER_CERT_SUBJECT),
218 TokenTableEntry(">cert_issuer", LFT_SSL_USER_CERT_ISSUER),
219 TokenTableEntry(">sni", LFT_SSL_CLIENT_SNI),
d4ddb3e6
CT
220 TokenTableEntry("<cert_subject", LFT_SSL_SERVER_CERT_SUBJECT),
221 TokenTableEntry("<cert_issuer", LFT_SSL_SERVER_CERT_ISSUER),
7598eb63 222 TokenTableEntry("<cert_errors", LFT_SSL_SERVER_CERT_ERRORS),
2bcab852
CT
223 TokenTableEntry(">negotiated_version", LFT_TLS_CLIENT_NEGOTIATED_VERSION),
224 TokenTableEntry("<negotiated_version", LFT_TLS_SERVER_NEGOTIATED_VERSION),
225 TokenTableEntry(">negotiated_cipher", LFT_TLS_CLIENT_NEGOTIATED_CIPHER),
226 TokenTableEntry("<negotiated_cipher", LFT_TLS_SERVER_NEGOTIATED_CIPHER),
227 TokenTableEntry(">received_hello_version", LFT_TLS_CLIENT_RECEIVED_HELLO_VERSION),
228 TokenTableEntry("<received_hello_version", LFT_TLS_SERVER_RECEIVED_HELLO_VERSION),
229 TokenTableEntry(">received_supported_version", LFT_TLS_CLIENT_SUPPORTED_VERSION),
230 TokenTableEntry("<received_supported_version", LFT_TLS_SERVER_SUPPORTED_VERSION),
95cc1e3e 231 TokenTableEntry(NULL, LFT_NONE)
08097970
AR
232};
233#endif
aa99e35e
AJ
234} // namespace Format
235
31971e6a
AJ
236/// Register all components custom format tokens
237void
238Format::Token::Init()
239{
240 // TODO standard log tokens
31971e6a
AJ
241
242#if USE_ADAPTATION
d32b56f3 243 TheConfig.registerTokens(SBuf("adapt"),::Format::TokenTableAdapt);
31971e6a
AJ
244#endif
245#if ICAP_CLIENT
d32b56f3 246 TheConfig.registerTokens(SBuf("icap"),::Format::TokenTableIcap);
31971e6a 247#endif
cb4f4424 248#if USE_OPENSSL
1e2df2b7 249 TheConfig.registerTokens(SBuf("tls"),::Format::TokenTableSsl);
d32b56f3 250 TheConfig.registerTokens(SBuf("ssl"),::Format::TokenTableSsl);
08097970 251#endif
31971e6a
AJ
252}
253
aa99e35e
AJ
254/// Scans a token table to see if the next token exists there
255/// returns a pointer to next unparsed byte and updates type member if found
f4698e0b
CT
256const char *
257Format::Token::scanForToken(TokenTableEntry const table[], const char *cur)
aa99e35e 258{
cb4185f1 259 for (TokenTableEntry const *lte = table; lte->configTag != NULL; ++lte) {
31971e6a
AJ
260 debugs(46, 8, HERE << "compare tokens '" << lte->configTag << "' with '" << cur << "'");
261 if (strncmp(lte->configTag, cur, strlen(lte->configTag)) == 0) {
262 type = lte->tokenType;
263 label = lte->configTag;
aa99e35e 264 debugs(46, 7, HERE << "Found token '" << label << "'");
31971e6a 265 return cur + strlen(lte->configTag);
aa99e35e
AJ
266 }
267 }
268 return cur;
269}
270
38e16f92
AJ
271/* parses a single token. Returns the token length in characters,
272 * and fills in the lt item with the token information.
273 * def is for sure null-terminated
274 */
275int
f4698e0b 276Format::Token::parse(const char *def, Quoting *quoting)
38e16f92 277{
f4698e0b 278 const char *cur = def;
38e16f92 279
38e16f92
AJ
280 int l;
281
282 l = strcspn(cur, "%");
283
284 if (l > 0) {
285 char *cp;
286 /* it's a string for sure, until \0 or the next % */
287 cp = (char *)xmalloc(l + 1);
288 xstrncpy(cp, cur, l + 1);
289 type = LFT_STRING;
290 data.string = cp;
291
292 while (l > 0) {
293 switch (*cur) {
294
295 case '"':
296
297 if (*quoting == LOG_QUOTE_NONE)
298 *quoting = LOG_QUOTE_QUOTES;
299 else if (*quoting == LOG_QUOTE_QUOTES)
300 *quoting = LOG_QUOTE_NONE;
301
302 break;
303
304 case '[':
305 if (*quoting == LOG_QUOTE_NONE)
306 *quoting = LOG_QUOTE_MIMEBLOB;
307
308 break;
309
310 case ']':
311 if (*quoting == LOG_QUOTE_MIMEBLOB)
312 *quoting = LOG_QUOTE_NONE;
313
314 break;
315 }
316
cb4185f1
FC
317 ++cur;
318 --l;
38e16f92
AJ
319 }
320
22473932 321 } else if (*cur) {
38e16f92 322
cb4185f1 323 ++cur;
38e16f92 324
22473932
AJ
325 // select quoting style for his particular token
326 switch (*cur) {
38e16f92 327
22473932
AJ
328 case '"':
329 quote = LOG_QUOTE_QUOTES;
330 ++cur;
331 break;
38e16f92 332
22473932
AJ
333 case '\'':
334 quote = LOG_QUOTE_RAW;
335 ++cur;
336 break;
38e16f92 337
22473932
AJ
338 case '[':
339 quote = LOG_QUOTE_MIMEBLOB;
340 ++cur;
341 break;
38e16f92 342
22473932
AJ
343 case '#':
344 quote = LOG_QUOTE_URL;
345 ++cur;
346 break;
38e16f92 347
71eb082c
DJ
348 case '/':
349 quote = LOG_QUOTE_SHELL;
350 ++cur;
351 break;
352
22473932
AJ
353 default:
354 quote = *quoting;
355 break;
356 }
38e16f92 357
22473932
AJ
358 if (*cur == '-') {
359 left = true;
360 ++cur;
361 }
38e16f92 362
22473932
AJ
363 if (*cur == '0') {
364 zero = true;
cb4185f1 365 ++cur;
22473932 366 }
38e16f92 367
22473932
AJ
368 char *endp;
369 if (xisdigit(*cur)) {
370 widthMin = strtol(cur, &endp, 10);
371 cur = endp;
31971e6a 372 }
31971e6a 373
22473932
AJ
374 if (*cur == '.' && xisdigit(*(++cur))) {
375 widthMax = strtol(cur, &endp, 10);
376 cur = endp;
377 }
aa99e35e 378
4e56d7f6 379 // when {arg} field is before the token (old logformat syntax)
22473932
AJ
380 if (*cur == '{') {
381 char *cp;
382 ++cur;
383 l = strcspn(cur, "}");
384 cp = (char *)xmalloc(l + 1);
385 xstrncpy(cp, cur, l + 1);
386 data.string = cp;
387 cur += l;
388
389 if (*cur == '}')
390 ++cur;
391 }
aa99e35e 392
22473932
AJ
393 type = LFT_NONE;
394
395 // Scan each registered token namespace
d32b56f3
AJ
396 debugs(46, 9, "check for token in " << TheConfig.tokens.size() << " namespaces.");
397 for (const auto &itr : TheConfig.tokens) {
398 debugs(46, 7, "check for possible " << itr.prefix << ":: token");
399 const size_t len = itr.prefix.length();
400 if (itr.prefix.cmp(cur, len) == 0 && cur[len] == ':' && cur[len+1] == ':') {
401 debugs(46, 5, "check for " << itr.prefix << ":: token in '" << cur << "'");
22473932 402 const char *old = cur;
d32b56f3 403 cur = scanForToken(itr.tokenSet, cur+len+2);
22473932
AJ
404 if (old != cur) // found
405 break;
406 else // reset to start of namespace
407 cur = cur - len - 2;
408 }
aa99e35e 409 }
22473932 410
aa99e35e 411 if (type == LFT_NONE) {
22473932
AJ
412 // For upward compatibility, assume "http::" prefix as default prefix
413 // for all log access formatting codes, except those starting with a
414 // "%" or a known namespace. (ie "icap::", "adapt::")
415 if (strncmp(cur,"http::", 6) == 0 && *(cur+6) != '%' )
416 cur += 6;
417
418 // NP: scan the sets of tokens in decreasing size to guarantee no
419 // mistakes made with overlapping names. (Bug 3310)
420
421 // Scan for various long tokens
422 debugs(46, 5, HERE << "scan for possible Misc token");
423 cur = scanForToken(TokenTableMisc, cur);
424 // scan for 2-char tokens
425 if (type == LFT_NONE) {
426 debugs(46, 5, HERE << "scan for possible 2C token");
427 cur = scanForToken(TokenTable2C, cur);
428 }
429 // finally scan for 1-char tokens.
430 if (type == LFT_NONE) {
431 debugs(46, 5, HERE << "scan for possible 1C token");
432 cur = scanForToken(TokenTable1C, cur);
433 }
38e16f92 434 }
38e16f92 435
22473932
AJ
436 if (type == LFT_NONE) {
437 fatalf("Can't parse configuration token: '%s'\n", def);
438 }
38e16f92 439
4e56d7f6
AJ
440 // when {arg} field is after the token (old external_acl_type token syntax)
441 // but accept only if there was none before the token
442 if (*cur == '{' && !data.string) {
443 char *cp;
444 ++cur;
445 l = strcspn(cur, "}");
446 cp = (char *)xmalloc(l + 1);
447 xstrncpy(cp, cur, l + 1);
448 data.string = cp;
449 cur += l;
450
451 if (*cur == '}')
452 ++cur;
453 }
454
22473932
AJ
455 if (*cur == ' ') {
456 space = true;
457 ++cur;
458 }
38e16f92
AJ
459 }
460
38e16f92
AJ
461 switch (type) {
462
463#if USE_ADAPTATION
464 case LFT_ADAPTATION_LAST_HEADER:
465#endif
466
467#if ICAP_CLIENT
468 case LFT_ICAP_REQ_HEADER:
469
470 case LFT_ICAP_REP_HEADER:
471#endif
472
473 case LFT_ADAPTED_REQUEST_HEADER:
474
475 case LFT_REQUEST_HEADER:
476
477 case LFT_REPLY_HEADER:
478
c7bcf010
CT
479 case LFT_NOTE:
480
38e16f92
AJ
481 if (data.string) {
482 char *header = data.string;
483 char *cp = strchr(header, ':');
484
485 if (cp) {
a38ec4b1
FC
486 *cp = '\0';
487 ++cp;
38e16f92 488
a38ec4b1
FC
489 if (*cp == ',' || *cp == ';' || *cp == ':') {
490 data.header.separator = *cp;
491 ++cp;
492 } else {
38e16f92 493 data.header.separator = ',';
a38ec4b1 494 }
38e16f92
AJ
495
496 data.header.element = cp;
497
498 switch (type) {
499 case LFT_REQUEST_HEADER:
500 type = LFT_REQUEST_HEADER_ELEM;
501 break;
502
503 case LFT_ADAPTED_REQUEST_HEADER:
504 type = LFT_ADAPTED_REQUEST_HEADER_ELEM;
505 break;
506
507 case LFT_REPLY_HEADER:
508 type = LFT_REPLY_HEADER_ELEM;
509 break;
510#if USE_ADAPTATION
511 case LFT_ADAPTATION_LAST_HEADER:
512 type = LFT_ADAPTATION_LAST_HEADER_ELEM;
513 break;
514#endif
515#if ICAP_CLIENT
516 case LFT_ICAP_REQ_HEADER:
517 type = LFT_ICAP_REQ_HEADER_ELEM;
518 break;
519 case LFT_ICAP_REP_HEADER:
520 type = LFT_ICAP_REP_HEADER_ELEM;
521 break;
522#endif
523 default:
524 break;
525 }
526 }
527
528 data.header.header = header;
529 } else {
530 switch (type) {
531 case LFT_REQUEST_HEADER:
532 type = LFT_REQUEST_ALL_HEADERS;
533 break;
534
535 case LFT_ADAPTED_REQUEST_HEADER:
536 type = LFT_ADAPTED_REQUEST_ALL_HEADERS;
537 break;
538
539 case LFT_REPLY_HEADER:
540 type = LFT_REPLY_ALL_HEADERS;
541 break;
542#if USE_ADAPTATION
543 case LFT_ADAPTATION_LAST_HEADER:
544 type = LFT_ADAPTATION_LAST_ALL_HEADERS;
545 break;
546#endif
547#if ICAP_CLIENT
548 case LFT_ICAP_REQ_HEADER:
549 type = LFT_ICAP_REQ_ALL_HEADERS;
550 break;
551 case LFT_ICAP_REP_HEADER:
552 type = LFT_ICAP_REP_ALL_HEADERS;
553 break;
554#endif
555 default:
556 break;
557 }
558 Config.onoff.log_mime_hdrs = 1;
559 }
560
561 break;
562
563 case LFT_CLIENT_FQDN:
564 Config.onoff.log_fqdn = 1;
565 break;
566
01bd87d8
CT
567 case LFT_TIME_TO_HANDLE_REQUEST:
568 case LFT_PEER_RESPONSE_TIME:
569 case LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME:
570 case LFT_DNS_WAIT_TIME:
ffac7e44 571#if ICAP_CLIENT
01bd87d8
CT
572 case LFT_ICAP_TR_RESPONSE_TIME:
573 case LFT_ICAP_IO_TIME:
574 case LFT_ICAP_TOTAL_TIME:
ffac7e44 575#endif
af0ded40 576 case LFT_TIME_START:
38e16f92
AJ
577 case LFT_TIME_SUBSECOND:
578 divisor = 1000;
579
8846a2b4 580 if (widthMax > 0) {
38e16f92
AJ
581 divisor = 1000000;
582
af0ded40 583 for (int i = widthMax; i > 0; --i)
38e16f92
AJ
584 divisor /= 10;
585
586 if (!divisor)
af0ded40 587 divisor = 1;
38e16f92 588 }
38e16f92
AJ
589 break;
590
591 case LFT_HTTP_SENT_STATUS_CODE_OLD_30:
874d775a 592 debugs(46, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: The \"Hs\" formatting code is deprecated. Use the \">Hs\" instead.");
38e16f92
AJ
593 type = LFT_HTTP_SENT_STATUS_CODE;
594 break;
595
8652f8e7 596 case LFT_SERVER_LOCAL_IP_OLD_27:
874d775a 597 debugs(46, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: The \"oa\" formatting code is deprecated. Use the \"<la\" instead.");
8652f8e7 598 type = LFT_SERVER_LOCAL_IP;
38e16f92
AJ
599 break;
600
601 case LFT_REQUEST_URLPATH_OLD_31:
874d775a 602 debugs(46, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: The \"rp\" formatting code is deprecated. Use the \">rp\" instead.");
38e16f92
AJ
603 type = LFT_CLIENT_REQ_URLPATH;
604 break;
605
606 case LFT_REQUEST_VERSION_OLD_2X:
874d775a 607 debugs(46, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: The \">v\" formatting code is deprecated. Use the \">rv\" instead.");
38e16f92
AJ
608 type = LFT_REQUEST_VERSION;
609 break;
610
8652f8e7
AJ
611#if !USE_SQUID_EUI
612 case LFT_CLIENT_EUI:
fa84c01d 613 debugs(46, DBG_CRITICAL, "WARNING: The \">eui\" formatting code requires EUI features which are disabled in this Squid.");
8652f8e7
AJ
614 break;
615#endif
616
2bcab852
CT
617#if USE_OPENSSL
618 case LFT_TLS_SERVER_NEGOTIATED_VERSION:
619 case LFT_TLS_SERVER_RECEIVED_HELLO_VERSION:
620 case LFT_TLS_SERVER_SUPPORTED_VERSION:
621 Config.onoff.logTlsServerHelloDetails = true;
622 break;
623#endif
624
d074f918
TT
625 case LFT_REQUEST_URLGROUP_OLD_2X:
626 debugs(46, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: The \"rG\" formatting code is deprecated. Use \"note{urlgroup}\" instead.");
627 type = LFT_NOTE;
628 data.header.header = xstrdup("urlgroup");
629 break;
630
38e16f92
AJ
631 default:
632 break;
633 }
634
635 return (cur - def);
636}
637
c7bcf010 638Format::Token::Token() : type(LFT_NONE),
f53969cc
SM
639 label(NULL),
640 widthMin(-1),
641 widthMax(-1),
642 quote(LOG_QUOTE_NONE),
643 left(false),
644 space(false),
645 zero(false),
646 divisor(1),
647 next(NULL)
c7bcf010
CT
648{
649 data.string = NULL;
e2849af8 650 data.header.header = NULL;
c7bcf010
CT
651 data.header.element = NULL;
652 data.header.separator = ',';
653}
654
38e16f92
AJ
655Format::Token::~Token()
656{
aa99e35e 657 label = NULL; // drop reference to global static.
38e16f92
AJ
658 safe_free(data.string);
659 while (next) {
660 Token *tokens = next;
661 next = next->next;
662 tokens->next = NULL;
663 delete tokens;
664 }
665}
666