]> git.ipfire.org Git - thirdparty/squid.git/blob - src/format/Token.cc
Merged from trunk rev.14331
[thirdparty/squid.git] / src / format / Token.cc
1 /*
2 * Copyright (C) 1996-2015 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(NULL, LFT_NONE)
222 };
223 #endif
224 } // namespace Format
225
226 /// Register all components custom format tokens
227 void
228 Format::Token::Init()
229 {
230 // TODO standard log tokens
231
232 #if USE_ADAPTATION
233 TheConfig.registerTokens(String("adapt"),::Format::TokenTableAdapt);
234 #endif
235 #if ICAP_CLIENT
236 TheConfig.registerTokens(String("icap"),::Format::TokenTableIcap);
237 #endif
238 #if USE_OPENSSL
239 TheConfig.registerTokens(String("ssl"),::Format::TokenTableSsl);
240 #endif
241 }
242
243 /// Scans a token table to see if the next token exists there
244 /// returns a pointer to next unparsed byte and updates type member if found
245 const char *
246 Format::Token::scanForToken(TokenTableEntry const table[], const char *cur)
247 {
248 for (TokenTableEntry const *lte = table; lte->configTag != NULL; ++lte) {
249 debugs(46, 8, HERE << "compare tokens '" << lte->configTag << "' with '" << cur << "'");
250 if (strncmp(lte->configTag, cur, strlen(lte->configTag)) == 0) {
251 type = lte->tokenType;
252 label = lte->configTag;
253 debugs(46, 7, HERE << "Found token '" << label << "'");
254 return cur + strlen(lte->configTag);
255 }
256 }
257 return cur;
258 }
259
260 /* parses a single token. Returns the token length in characters,
261 * and fills in the lt item with the token information.
262 * def is for sure null-terminated
263 */
264 int
265 Format::Token::parse(const char *def, Quoting *quoting)
266 {
267 const char *cur = def;
268
269 int l;
270
271 l = strcspn(cur, "%");
272
273 if (l > 0) {
274 char *cp;
275 /* it's a string for sure, until \0 or the next % */
276 cp = (char *)xmalloc(l + 1);
277 xstrncpy(cp, cur, l + 1);
278 type = LFT_STRING;
279 data.string = cp;
280
281 while (l > 0) {
282 switch (*cur) {
283
284 case '"':
285
286 if (*quoting == LOG_QUOTE_NONE)
287 *quoting = LOG_QUOTE_QUOTES;
288 else if (*quoting == LOG_QUOTE_QUOTES)
289 *quoting = LOG_QUOTE_NONE;
290
291 break;
292
293 case '[':
294 if (*quoting == LOG_QUOTE_NONE)
295 *quoting = LOG_QUOTE_MIMEBLOB;
296
297 break;
298
299 case ']':
300 if (*quoting == LOG_QUOTE_MIMEBLOB)
301 *quoting = LOG_QUOTE_NONE;
302
303 break;
304 }
305
306 ++cur;
307 --l;
308 }
309
310 } else if (*cur) {
311
312 ++cur;
313
314 // select quoting style for his particular token
315 switch (*cur) {
316
317 case '"':
318 quote = LOG_QUOTE_QUOTES;
319 ++cur;
320 break;
321
322 case '\'':
323 quote = LOG_QUOTE_RAW;
324 ++cur;
325 break;
326
327 case '[':
328 quote = LOG_QUOTE_MIMEBLOB;
329 ++cur;
330 break;
331
332 case '#':
333 quote = LOG_QUOTE_URL;
334 ++cur;
335 break;
336
337 default:
338 quote = *quoting;
339 break;
340 }
341
342 if (*cur == '-') {
343 left = true;
344 ++cur;
345 }
346
347 if (*cur == '0') {
348 zero = true;
349 ++cur;
350 }
351
352 char *endp;
353 if (xisdigit(*cur)) {
354 widthMin = strtol(cur, &endp, 10);
355 cur = endp;
356 }
357
358 if (*cur == '.' && xisdigit(*(++cur))) {
359 widthMax = strtol(cur, &endp, 10);
360 cur = endp;
361 }
362
363 // when {arg} field is before the token (old logformat syntax)
364 if (*cur == '{') {
365 char *cp;
366 ++cur;
367 l = strcspn(cur, "}");
368 cp = (char *)xmalloc(l + 1);
369 xstrncpy(cp, cur, l + 1);
370 data.string = cp;
371 cur += l;
372
373 if (*cur == '}')
374 ++cur;
375 }
376
377 type = LFT_NONE;
378
379 // Scan each registered token namespace
380 debugs(46, 9, HERE << "check for token in " << TheConfig.tokens.size() << " namespaces.");
381 for (std::list<TokenNamespace>::const_iterator itr = TheConfig.tokens.begin(); itr != TheConfig.tokens.end(); ++itr) {
382 debugs(46, 7, HERE << "check for possible " << itr->prefix << ":: token");
383 const size_t len = itr->prefix.size();
384 if (itr->prefix.cmp(cur, len) == 0 && cur[len] == ':' && cur[len+1] == ':') {
385 debugs(46, 5, HERE << "check for " << itr->prefix << ":: token in '" << cur << "'");
386 const char *old = cur;
387 cur = scanForToken(itr->tokenSet, cur+len+2);
388 if (old != cur) // found
389 break;
390 else // reset to start of namespace
391 cur = cur - len - 2;
392 }
393 }
394
395 if (type == LFT_NONE) {
396 // For upward compatibility, assume "http::" prefix as default prefix
397 // for all log access formatting codes, except those starting with a
398 // "%" or a known namespace. (ie "icap::", "adapt::")
399 if (strncmp(cur,"http::", 6) == 0 && *(cur+6) != '%' )
400 cur += 6;
401
402 // NP: scan the sets of tokens in decreasing size to guarantee no
403 // mistakes made with overlapping names. (Bug 3310)
404
405 // Scan for various long tokens
406 debugs(46, 5, HERE << "scan for possible Misc token");
407 cur = scanForToken(TokenTableMisc, cur);
408 // scan for 2-char tokens
409 if (type == LFT_NONE) {
410 debugs(46, 5, HERE << "scan for possible 2C token");
411 cur = scanForToken(TokenTable2C, cur);
412 }
413 // finally scan for 1-char tokens.
414 if (type == LFT_NONE) {
415 debugs(46, 5, HERE << "scan for possible 1C token");
416 cur = scanForToken(TokenTable1C, cur);
417 }
418 }
419
420 if (type == LFT_NONE) {
421 fatalf("Can't parse configuration token: '%s'\n", def);
422 }
423
424 // when {arg} field is after the token (old external_acl_type token syntax)
425 // but accept only if there was none before the token
426 if (*cur == '{' && !data.string) {
427 char *cp;
428 ++cur;
429 l = strcspn(cur, "}");
430 cp = (char *)xmalloc(l + 1);
431 xstrncpy(cp, cur, l + 1);
432 data.string = cp;
433 cur += l;
434
435 if (*cur == '}')
436 ++cur;
437 }
438
439 if (*cur == ' ') {
440 space = true;
441 ++cur;
442 }
443 }
444
445 switch (type) {
446
447 #if USE_ADAPTATION
448 case LFT_ADAPTATION_LAST_HEADER:
449 #endif
450
451 #if ICAP_CLIENT
452 case LFT_ICAP_REQ_HEADER:
453
454 case LFT_ICAP_REP_HEADER:
455 #endif
456
457 case LFT_ADAPTED_REQUEST_HEADER:
458
459 case LFT_REQUEST_HEADER:
460
461 case LFT_REPLY_HEADER:
462
463 case LFT_NOTE:
464
465 if (data.string) {
466 char *header = data.string;
467 char *cp = strchr(header, ':');
468
469 if (cp) {
470 *cp = '\0';
471 ++cp;
472
473 if (*cp == ',' || *cp == ';' || *cp == ':') {
474 data.header.separator = *cp;
475 ++cp;
476 } else {
477 data.header.separator = ',';
478 }
479
480 data.header.element = cp;
481
482 switch (type) {
483 case LFT_REQUEST_HEADER:
484 type = LFT_REQUEST_HEADER_ELEM;
485 break;
486
487 case LFT_ADAPTED_REQUEST_HEADER:
488 type = LFT_ADAPTED_REQUEST_HEADER_ELEM;
489 break;
490
491 case LFT_REPLY_HEADER:
492 type = LFT_REPLY_HEADER_ELEM;
493 break;
494 #if USE_ADAPTATION
495 case LFT_ADAPTATION_LAST_HEADER:
496 type = LFT_ADAPTATION_LAST_HEADER_ELEM;
497 break;
498 #endif
499 #if ICAP_CLIENT
500 case LFT_ICAP_REQ_HEADER:
501 type = LFT_ICAP_REQ_HEADER_ELEM;
502 break;
503 case LFT_ICAP_REP_HEADER:
504 type = LFT_ICAP_REP_HEADER_ELEM;
505 break;
506 #endif
507 default:
508 break;
509 }
510 }
511
512 data.header.header = header;
513 } else {
514 switch (type) {
515 case LFT_REQUEST_HEADER:
516 type = LFT_REQUEST_ALL_HEADERS;
517 break;
518
519 case LFT_ADAPTED_REQUEST_HEADER:
520 type = LFT_ADAPTED_REQUEST_ALL_HEADERS;
521 break;
522
523 case LFT_REPLY_HEADER:
524 type = LFT_REPLY_ALL_HEADERS;
525 break;
526 #if USE_ADAPTATION
527 case LFT_ADAPTATION_LAST_HEADER:
528 type = LFT_ADAPTATION_LAST_ALL_HEADERS;
529 break;
530 #endif
531 #if ICAP_CLIENT
532 case LFT_ICAP_REQ_HEADER:
533 type = LFT_ICAP_REQ_ALL_HEADERS;
534 break;
535 case LFT_ICAP_REP_HEADER:
536 type = LFT_ICAP_REP_ALL_HEADERS;
537 break;
538 #endif
539 default:
540 break;
541 }
542 Config.onoff.log_mime_hdrs = 1;
543 }
544
545 break;
546
547 case LFT_CLIENT_FQDN:
548 Config.onoff.log_fqdn = 1;
549 break;
550
551 case LFT_TIME_TO_HANDLE_REQUEST:
552 case LFT_PEER_RESPONSE_TIME:
553 case LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME:
554 case LFT_DNS_WAIT_TIME:
555 #if ICAP_CLIENT
556 case LFT_ICAP_TR_RESPONSE_TIME:
557 case LFT_ICAP_IO_TIME:
558 case LFT_ICAP_TOTAL_TIME:
559 #endif
560 case LFT_TIME_START:
561 case LFT_TIME_SUBSECOND:
562 divisor = 1000;
563
564 if (widthMax > 0) {
565 divisor = 1000000;
566
567 for (int i = widthMax; i > 0; --i)
568 divisor /= 10;
569
570 if (!divisor)
571 divisor = 1;
572 }
573 break;
574
575 case LFT_HTTP_SENT_STATUS_CODE_OLD_30:
576 debugs(46, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: The \"Hs\" formatting code is deprecated. Use the \">Hs\" instead.");
577 type = LFT_HTTP_SENT_STATUS_CODE;
578 break;
579
580 case LFT_SERVER_LOCAL_IP_OLD_27:
581 debugs(46, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: The \"oa\" formatting code is deprecated. Use the \"<la\" instead.");
582 type = LFT_SERVER_LOCAL_IP;
583 break;
584
585 case LFT_REQUEST_URLPATH_OLD_31:
586 debugs(46, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: The \"rp\" formatting code is deprecated. Use the \">rp\" instead.");
587 type = LFT_CLIENT_REQ_URLPATH;
588 break;
589
590 case LFT_REQUEST_VERSION_OLD_2X:
591 debugs(46, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: The \">v\" formatting code is deprecated. Use the \">rv\" instead.");
592 type = LFT_REQUEST_VERSION;
593 break;
594
595 #if !USE_SQUID_EUI
596 case LFT_CLIENT_EUI:
597 debugs(46, DBG_CRITICAL, "WARNING: The \">eui\" formatting code requires EUI features which are disabled in this Squid.");
598 break;
599 #endif
600
601 case LFT_REQUEST_URLGROUP_OLD_2X:
602 debugs(46, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: The \"rG\" formatting code is deprecated. Use \"note{urlgroup}\" instead.");
603 type = LFT_NOTE;
604 data.header.header = xstrdup("urlgroup");
605 break;
606
607 default:
608 break;
609 }
610
611 return (cur - def);
612 }
613
614 Format::Token::Token() : type(LFT_NONE),
615 label(NULL),
616 widthMin(-1),
617 widthMax(-1),
618 quote(LOG_QUOTE_NONE),
619 left(false),
620 space(false),
621 zero(false),
622 divisor(1),
623 next(NULL)
624 {
625 data.string = NULL;
626 data.header.header = NULL;
627 data.header.element = NULL;
628 data.header.separator = ',';
629 }
630
631 Format::Token::~Token()
632 {
633 label = NULL; // drop reference to global static.
634 safe_free(data.string);
635 while (next) {
636 Token *tokens = next;
637 next = next->next;
638 tokens->next = NULL;
639 delete tokens;
640 }
641 }
642