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