2 * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
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.
10 #include "format/Config.h"
11 #include "format/Token.h"
12 #include "format/TokenTableEntry.h"
14 #include "proxyp/Elements.h"
15 #include "sbuf/Stream.h"
16 #include "SquidConfig.h"
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
25 static TokenTableEntry TokenTable1C
[] = {
27 TokenTableEntry(">a", LFT_CLIENT_IP_ADDRESS
),
28 TokenTableEntry(">p", LFT_CLIENT_PORT
),
29 TokenTableEntry(">A", LFT_CLIENT_FQDN
),
31 TokenTableEntry("<a", LFT_SERVER_IP_ADDRESS
),
32 TokenTableEntry("<p", LFT_SERVER_PORT
),
33 TokenTableEntry("<A", LFT_SERVER_FQDN_OR_PEER_NAME
),
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
),
40 TokenTableEntry(">v", LFT_REQUEST_VERSION_OLD_2X
),
42 TokenTableEntry("%", LFT_PERCENT
),
44 TokenTableEntry(nullptr, LFT_NONE
) /* this must be last */
48 static TokenTableEntry TokenTable2C
[] = {
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 ), */
56 TokenTableEntry("<la", LFT_SERVER_LOCAL_IP
),
57 TokenTableEntry("oa", LFT_SERVER_LOCAL_IP_OLD_27
),
58 TokenTableEntry("<lp", LFT_SERVER_LOCAL_PORT
),
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
),
67 TokenTableEntry("<pt", LFT_PEER_RESPONSE_TIME
),
68 TokenTableEntry("<tt", LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME
),
69 TokenTableEntry("dt", LFT_DNS_WAIT_TIME
),
71 TokenTableEntry(">ha", LFT_ADAPTED_REQUEST_HEADER
),
72 TokenTableEntry(">ha", LFT_ADAPTED_REQUEST_ALL_HEADERS
),
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
),
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
),
87 TokenTableEntry("Ss", LFT_SQUID_STATUS
),
88 TokenTableEntry("Sh", LFT_SQUID_HIERARCHY
),
90 TokenTableEntry("mt", LFT_MIME_TYPE
),
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
),
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
),
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
),
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 ), */
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 ), */
129 TokenTableEntry("st", LFT_CLIENT_IO_SIZE_TOTAL
), // XXX: total from client should be stC ??
130 /*TokenTableEntry("stP", LFT_SERVER_IO_SIZE_TOTAL),*/
132 TokenTableEntry("et", LFT_TAG
),
133 TokenTableEntry("ea", LFT_EXT_LOG
),
134 TokenTableEntry("sn", LFT_SEQUENCE_NUMBER
),
136 TokenTableEntry(nullptr, LFT_NONE
) /* this must be last */
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
),
153 * Legacy external_acl_type format tokens
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
),
176 TokenTableEntry("USER_CERTCHAIN", LFT_EXT_ACL_USER_CERTCHAIN_RAW
),
177 TokenTableEntry("USER_CERT", LFT_EXT_ACL_USER_CERT_RAW
),
179 TokenTableEntry(nullptr, LFT_NONE
) /* this must be last */
182 static TokenTableEntry TokenTableProxyProtocol
[] = {
183 TokenTableEntry(">h", LFT_PROXY_PROTOCOL_RECEIVED_HEADER
),
186 static TokenTableEntry TokenTableTransport
[] = {
187 TokenTableEntry(">connection_id", LFT_TRANSPORT_CLIENT_CONNECTION_ID
),
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 */
200 /// ICAP (icap::) tokens
201 static TokenTableEntry TokenTableIcap
[] = {
202 TokenTableEntry("tt", LFT_ICAP_TOTAL_TIME
),
203 TokenTableEntry("<last_h", LFT_ADAPTATION_LAST_HEADER
), // deprecated
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
),
213 TokenTableEntry(">h", LFT_ICAP_REQ_HEADER
),
214 TokenTableEntry("<h", LFT_ICAP_REP_HEADER
),
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
),
221 TokenTableEntry(nullptr, LFT_NONE
) /* this must be last */
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
)
247 } // namespace Format
249 /// Register all components custom format tokens
251 Format::Token::Init()
253 // TODO standard log tokens
256 TheConfig
.registerTokens(SBuf("adapt"),::Format::TokenTableAdapt
);
259 TheConfig
.registerTokens(SBuf("icap"),::Format::TokenTableIcap
);
262 TheConfig
.registerTokens(SBuf("tls"),::Format::TokenTableSsl
);
263 TheConfig
.registerTokens(SBuf("ssl"),::Format::TokenTableSsl
);
265 TheConfig
.registerTokens(SBuf("proxy_protocol"), ::Format::TokenTableProxyProtocol
);
266 TheConfig
.registerTokens(SBuf("transport"), ::Format::TokenTableTransport
);
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
272 Format::Token::scanForToken(TokenTableEntry
const table
[], const char *cur
)
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
);
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
291 Format::Token::parse(const char *def
, Quoting
*quoting
)
293 const char *cur
= def
;
297 l
= strcspn(cur
, "%");
301 /* it's a string for sure, until \0 or the next % */
302 cp
= (char *)xmalloc(l
+ 1);
303 xstrncpy(cp
, cur
, l
+ 1);
312 if (*quoting
== LOG_QUOTE_NONE
)
313 *quoting
= LOG_QUOTE_QUOTES
;
314 else if (*quoting
== LOG_QUOTE_QUOTES
)
315 *quoting
= LOG_QUOTE_NONE
;
320 if (*quoting
== LOG_QUOTE_NONE
)
321 *quoting
= LOG_QUOTE_MIMEBLOB
;
326 if (*quoting
== LOG_QUOTE_MIMEBLOB
)
327 *quoting
= LOG_QUOTE_NONE
;
340 // select quoting style for his particular token
344 quote
= LOG_QUOTE_QUOTES
;
349 quote
= LOG_QUOTE_RAW
;
354 quote
= LOG_QUOTE_MIMEBLOB
;
359 quote
= LOG_QUOTE_URL
;
364 quote
= LOG_QUOTE_SHELL
;
384 if (xisdigit(*cur
)) {
385 widthMin
= strtol(cur
, &endp
, 10);
389 if (*cur
== '.' && xisdigit(*(++cur
))) {
390 widthMax
= strtol(cur
, &endp
, 10);
394 // when {arg} field is before the token (old logformat syntax)
398 l
= strcspn(cur
, "}");
399 cp
= (char *)xmalloc(l
+ 1);
400 xstrncpy(cp
, cur
, l
+ 1);
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
421 else // reset to start of namespace
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) != '%' )
433 // NP: scan the sets of tokens in decreasing size to guarantee no
434 // mistakes made with overlapping names. (Bug 3310)
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
);
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
);
451 if (type
== LFT_NONE
)
452 throw TexcHere(ToSBuf("Unsupported %code: '", def
, "'"));
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
) {
459 l
= strcspn(cur
, "}");
460 cp
= (char *)xmalloc(l
+ 1);
461 xstrncpy(cp
, cur
, l
+ 1);
478 case LFT_ADAPTATION_LAST_HEADER
:
482 case LFT_ICAP_REQ_HEADER
:
484 case LFT_ICAP_REP_HEADER
:
487 case LFT_ADAPTED_REQUEST_HEADER
:
489 case LFT_REQUEST_HEADER
:
491 case LFT_REPLY_HEADER
:
495 case LFT_PROXY_PROTOCOL_RECEIVED_HEADER
:
498 char *header
= data
.string
;
499 const auto initialType
= type
;
501 const auto pseudoHeader
= header
[0] == ':';
502 char *cp
= strchr(pseudoHeader
? header
+1 : header
, ':');
508 if (*cp
== ',' || *cp
== ';' || *cp
== ':') {
509 data
.header
.separator
= *cp
;
512 data
.header
.separator
= ',';
515 data
.header
.element
= cp
;
518 case LFT_REQUEST_HEADER
:
519 type
= LFT_REQUEST_HEADER_ELEM
;
522 case LFT_ADAPTED_REQUEST_HEADER
:
523 type
= LFT_ADAPTED_REQUEST_HEADER_ELEM
;
526 case LFT_REPLY_HEADER
:
527 type
= LFT_REPLY_HEADER_ELEM
;
530 case LFT_ADAPTATION_LAST_HEADER
:
531 type
= LFT_ADAPTATION_LAST_HEADER_ELEM
;
535 case LFT_ICAP_REQ_HEADER
:
536 type
= LFT_ICAP_REQ_HEADER_ELEM
;
538 case LFT_ICAP_REP_HEADER
:
539 type
= LFT_ICAP_REP_HEADER_ELEM
;
542 case LFT_PROXY_PROTOCOL_RECEIVED_HEADER
:
543 type
= LFT_PROXY_PROTOCOL_RECEIVED_HEADER_ELEM
;
551 throw TexcHere(ToSBuf("Can't parse configuration token: '", def
, "': missing header name"));
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
, "'"));
558 data
.header
.header
= header
;
561 case LFT_REQUEST_HEADER
:
562 type
= LFT_REQUEST_ALL_HEADERS
;
565 case LFT_ADAPTED_REQUEST_HEADER
:
566 type
= LFT_ADAPTED_REQUEST_ALL_HEADERS
;
569 case LFT_REPLY_HEADER
:
570 type
= LFT_REPLY_ALL_HEADERS
;
573 case LFT_ADAPTATION_LAST_HEADER
:
574 type
= LFT_ADAPTATION_LAST_ALL_HEADERS
;
578 case LFT_ICAP_REQ_HEADER
:
579 type
= LFT_ICAP_REQ_ALL_HEADERS
;
581 case LFT_ICAP_REP_HEADER
:
582 type
= LFT_ICAP_REP_ALL_HEADERS
;
585 case LFT_PROXY_PROTOCOL_RECEIVED_HEADER
:
586 type
= LFT_PROXY_PROTOCOL_RECEIVED_ALL_HEADERS
;
591 Config
.onoff
.log_mime_hdrs
= 1;
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
:
601 case LFT_ICAP_TR_RESPONSE_TIME
:
602 case LFT_ICAP_IO_TIME
:
603 case LFT_ICAP_TOTAL_TIME
:
606 case LFT_TIME_SUBSECOND
:
612 for (int i
= widthMax
; i
> 0; --i
)
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
;
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
;
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
;
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
;
642 debugs(46, DBG_CRITICAL
, "WARNING: The \">eui\" formatting code requires EUI features which are disabled in this Squid.");
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;
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.");
657 data
.header
.header
= xstrdup("urlgroup");
667 Format::Token::Token() : type(LFT_NONE
),
671 quote(LOG_QUOTE_NONE
),
678 data
.string
= nullptr;
679 data
.header
.header
= nullptr;
680 data
.header
.element
= nullptr;
681 data
.header
.separator
= ',';
682 data
.headerId
= ProxyProtocol::Two::htUnknown
;
685 Format::Token::~Token()
687 label
= nullptr; // drop reference to global static.
688 safe_free(data
.string
);
690 Token
*tokens
= next
;
692 tokens
->next
= nullptr;