]> git.ipfire.org Git - thirdparty/squid.git/blob - src/format/Token.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / format / Token.cc
1 /*
2 * Copyright (C) 1996-2016 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 "SquidConfig.h"
15 #include "Store.h"
16
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
19 namespace Format
20 {
21
22 /// 1-char tokens.
23 static TokenTableEntry TokenTable1C[] = {
24
25 TokenTableEntry(">a", LFT_CLIENT_IP_ADDRESS),
26 TokenTableEntry(">p", LFT_CLIENT_PORT),
27 TokenTableEntry(">A", LFT_CLIENT_FQDN),
28
29 TokenTableEntry("<a", LFT_SERVER_IP_ADDRESS),
30 TokenTableEntry("<p", LFT_SERVER_PORT),
31 TokenTableEntry("<A", LFT_SERVER_FQDN_OR_PEER_NAME),
32
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),
37
38 TokenTableEntry(">v", LFT_REQUEST_VERSION_OLD_2X),
39
40 TokenTableEntry("%", LFT_PERCENT),
41
42 TokenTableEntry(NULL, LFT_NONE) /* this must be last */
43 };
44
45 /// 2-char tokens
46 static TokenTableEntry TokenTable2C[] = {
47
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 */
135 };
136
137 /// Miscellaneous >2 byte tokens
138 static TokenTableEntry TokenTableMisc[] = {
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),
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),
170 #if USE_OPENSSL
171 TokenTableEntry("USER_CERTCHAIN", LFT_EXT_ACL_USER_CERTCHAIN_RAW),
172 TokenTableEntry("USER_CERT", LFT_EXT_ACL_USER_CERT_RAW),
173 #endif
174 TokenTableEntry(NULL, LFT_NONE) /* this must be last */
175 };
176
177 #if USE_ADAPTATION
178 static TokenTableEntry TokenTableAdapt[] = {
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 */
183 };
184 #endif
185
186 #if ICAP_CLIENT
187 /// ICAP (icap::) tokens
188 static TokenTableEntry TokenTableIcap[] = {
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 */
209 };
210 #endif
211
212 #if USE_OPENSSL
213 // SSL (ssl::) tokens
214 static TokenTableEntry TokenTableSsl[] = {
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), */
221 TokenTableEntry("<cert_errors", LFT_SSL_SERVER_CERT_ERRORS),
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),
230 TokenTableEntry(NULL, LFT_NONE)
231 };
232 #endif
233 } // namespace Format
234
235 /// Register all components custom format tokens
236 void
237 Format::Token::Init()
238 {
239 // TODO standard log tokens
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
247 #if USE_OPENSSL
248 TheConfig.registerTokens(String("ssl"),::Format::TokenTableSsl);
249 #endif
250 }
251
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
254 const char *
255 Format::Token::scanForToken(TokenTableEntry const table[], const char *cur)
256 {
257 for (TokenTableEntry const *lte = table; lte->configTag != NULL; ++lte) {
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;
262 debugs(46, 7, HERE << "Found token '" << label << "'");
263 return cur + strlen(lte->configTag);
264 }
265 }
266 return cur;
267 }
268
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 */
273 int
274 Format::Token::parse(const char *def, Quoting *quoting)
275 {
276 const char *cur = def;
277
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
315 ++cur;
316 --l;
317 }
318
319 } else if (*cur) {
320
321 ++cur;
322
323 // select quoting style for his particular token
324 switch (*cur) {
325
326 case '"':
327 quote = LOG_QUOTE_QUOTES;
328 ++cur;
329 break;
330
331 case '\'':
332 quote = LOG_QUOTE_RAW;
333 ++cur;
334 break;
335
336 case '[':
337 quote = LOG_QUOTE_MIMEBLOB;
338 ++cur;
339 break;
340
341 case '#':
342 quote = LOG_QUOTE_URL;
343 ++cur;
344 break;
345
346 default:
347 quote = *quoting;
348 break;
349 }
350
351 if (*cur == '-') {
352 left = true;
353 ++cur;
354 }
355
356 if (*cur == '0') {
357 zero = true;
358 ++cur;
359 }
360
361 char *endp;
362 if (xisdigit(*cur)) {
363 widthMin = strtol(cur, &endp, 10);
364 cur = endp;
365 }
366
367 if (*cur == '.' && xisdigit(*(++cur))) {
368 widthMax = strtol(cur, &endp, 10);
369 cur = endp;
370 }
371
372 // when {arg} field is before the token (old logformat syntax)
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 }
385
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 }
402 }
403
404 if (type == LFT_NONE) {
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 }
427 }
428
429 if (type == LFT_NONE) {
430 fatalf("Can't parse configuration token: '%s'\n", def);
431 }
432
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
448 if (*cur == ' ') {
449 space = true;
450 ++cur;
451 }
452 }
453
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
472 case LFT_NOTE:
473
474 if (data.string) {
475 char *header = data.string;
476 char *cp = strchr(header, ':');
477
478 if (cp) {
479 *cp = '\0';
480 ++cp;
481
482 if (*cp == ',' || *cp == ';' || *cp == ':') {
483 data.header.separator = *cp;
484 ++cp;
485 } else {
486 data.header.separator = ',';
487 }
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
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:
564 #if ICAP_CLIENT
565 case LFT_ICAP_TR_RESPONSE_TIME:
566 case LFT_ICAP_IO_TIME:
567 case LFT_ICAP_TOTAL_TIME:
568 #endif
569 case LFT_TIME_START:
570 case LFT_TIME_SUBSECOND:
571 divisor = 1000;
572
573 if (widthMax > 0) {
574 divisor = 1000000;
575
576 for (int i = widthMax; i > 0; --i)
577 divisor /= 10;
578
579 if (!divisor)
580 divisor = 1;
581 }
582 break;
583
584 case LFT_HTTP_SENT_STATUS_CODE_OLD_30:
585 debugs(46, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: The \"Hs\" formatting code is deprecated. Use the \">Hs\" instead.");
586 type = LFT_HTTP_SENT_STATUS_CODE;
587 break;
588
589 case LFT_SERVER_LOCAL_IP_OLD_27:
590 debugs(46, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: The \"oa\" formatting code is deprecated. Use the \"<la\" instead.");
591 type = LFT_SERVER_LOCAL_IP;
592 break;
593
594 case LFT_REQUEST_URLPATH_OLD_31:
595 debugs(46, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: The \"rp\" formatting code is deprecated. Use the \">rp\" instead.");
596 type = LFT_CLIENT_REQ_URLPATH;
597 break;
598
599 case LFT_REQUEST_VERSION_OLD_2X:
600 debugs(46, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: The \">v\" formatting code is deprecated. Use the \">rv\" instead.");
601 type = LFT_REQUEST_VERSION;
602 break;
603
604 #if !USE_SQUID_EUI
605 case LFT_CLIENT_EUI:
606 debugs(46, DBG_CRITICAL, "WARNING: The \">eui\" formatting code requires EUI features which are disabled in this Squid.");
607 break;
608 #endif
609
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
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
624 default:
625 break;
626 }
627
628 return (cur - def);
629 }
630
631 Format::Token::Token() : type(LFT_NONE),
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)
641 {
642 data.string = NULL;
643 data.header.header = NULL;
644 data.header.element = NULL;
645 data.header.separator = ',';
646 }
647
648 Format::Token::~Token()
649 {
650 label = NULL; // drop reference to global static.
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