2 #include "AccessLogEntry.h"
3 #include "client_side.h"
4 #include "comm/Connection.h"
5 #include "err_detail_type.h"
8 #include "format/Format.h"
9 #include "format/Quoting.h"
10 #include "format/Token.h"
11 #include "fqdncache.h"
12 #include "HttpRequest.h"
15 #include "SquidTime.h"
19 #include "ssl/ErrorDetail.h"
20 #include "ssl/ServerBump.h"
23 /// Convert a string to NULL pointer if it is ""
24 #define strOrNull(s) ((s)==NULL||(s)[0]=='\0'?NULL:(s))
26 Format::Format::Format(const char *n
) :
33 Format::Format::~Format()
35 // erase the list without consuming stack space
37 // unlink the next entry for deletion
50 Format::Format::parse(const char *def
)
52 const char *cur
, *eos
;
53 Token
*new_lt
, *last_lt
;
54 enum Quoting quote
= LOG_QUOTE_NONE
;
56 debugs(46, 2, HERE
<< "got definition '" << def
<< "'");
59 debugs(46, DBG_IMPORTANT
, "WARNING: existing format for '" << name
<< " " << def
<< "'");
63 /* very inefficent parser, but who cares, this needs to be simple */
64 /* First off, let's tokenize, we'll optimize in a second pass.
65 * A token can either be a %-prefixed sequence (usually a dynamic
66 * token but it can be an escaped sequence), or a string. */
68 eos
= def
+ strlen(def
);
69 format
= new_lt
= last_lt
= new Token
;
70 cur
+= new_lt
->parse(cur
, "e
);
74 last_lt
->next
= new_lt
;
76 cur
+= new_lt
->parse(cur
, "e
);
83 Format::Format::dump(StoreEntry
* entry
, const char *directiveName
)
87 // loop rather than recursing to conserve stack space.
88 for (Format
*fmt
= this; fmt
; fmt
= fmt
->next
) {
89 debugs(46, 3, HERE
<< "Dumping format definition for " << fmt
->name
);
90 storeAppendPrintf(entry
, "%s %s ", directiveName
, fmt
->name
);
92 for (Token
*t
= fmt
->format
; t
; t
= t
->next
) {
93 if (t
->type
== LFT_STRING
)
94 storeAppendPrintf(entry
, "%s", t
->data
.string
);
98 ByteCode_t type
= t
->type
;
106 case LFT_ADAPTATION_LAST_HEADER_ELEM
:
109 case LFT_ICAP_REQ_HEADER_ELEM
:
110 case LFT_ICAP_REP_HEADER_ELEM
:
112 case LFT_REQUEST_HEADER_ELEM
:
113 case LFT_ADAPTED_REQUEST_HEADER_ELEM
:
114 case LFT_REPLY_HEADER_ELEM
:
116 if (t
->data
.header
.separator
!= ',')
117 snprintf(argbuf
, sizeof(argbuf
), "%s:%c%s", t
->data
.header
.header
, t
->data
.header
.separator
, t
->data
.header
.element
);
119 snprintf(argbuf
, sizeof(argbuf
), "%s:%s", t
->data
.header
.header
, t
->data
.header
.element
);
124 case LFT_REQUEST_HEADER_ELEM
:
125 type
= LFT_REQUEST_HEADER_ELEM
; // XXX: remove _ELEM?
127 case LFT_ADAPTED_REQUEST_HEADER_ELEM
:
128 type
= LFT_ADAPTED_REQUEST_HEADER_ELEM
; // XXX: remove _ELEM?
130 case LFT_REPLY_HEADER_ELEM
:
131 type
= LFT_REPLY_HEADER_ELEM
; // XXX: remove _ELEM?
134 case LFT_ADAPTATION_LAST_HEADER_ELEM
:
135 type
= LFT_ADAPTATION_LAST_HEADER
;
139 case LFT_ICAP_REQ_HEADER_ELEM
:
140 type
= LFT_ICAP_REQ_HEADER
;
142 case LFT_ICAP_REP_HEADER_ELEM
:
143 type
= LFT_ICAP_REP_HEADER
;
152 case LFT_REQUEST_ALL_HEADERS
:
153 case LFT_ADAPTED_REQUEST_ALL_HEADERS
:
154 case LFT_REPLY_ALL_HEADERS
:
157 case LFT_ADAPTATION_LAST_ALL_HEADERS
:
160 case LFT_ICAP_REQ_ALL_HEADERS
:
161 case LFT_ICAP_REP_ALL_HEADERS
:
165 case LFT_REQUEST_ALL_HEADERS
:
166 type
= LFT_REQUEST_HEADER
;
168 case LFT_ADAPTED_REQUEST_ALL_HEADERS
:
169 type
= LFT_ADAPTED_REQUEST_HEADER
;
171 case LFT_REPLY_ALL_HEADERS
:
172 type
= LFT_REPLY_HEADER
;
175 case LFT_ADAPTATION_LAST_ALL_HEADERS
:
176 type
= LFT_ADAPTATION_LAST_HEADER
;
180 case LFT_ICAP_REQ_ALL_HEADERS
:
181 type
= LFT_ICAP_REQ_HEADER
;
183 case LFT_ICAP_REP_ALL_HEADERS
:
184 type
= LFT_ICAP_REP_HEADER
;
195 arg
= t
->data
.string
;
200 entry
->append("%", 1);
204 case LOG_QUOTE_QUOTES
:
205 entry
->append("\"", 1);
208 case LOG_QUOTE_MIMEBLOB
:
209 entry
->append("[", 1);
213 entry
->append("#", 1);
217 entry
->append("'", 1);
225 entry
->append("-", 1);
228 entry
->append("0", 1);
230 if (t
->widthMin
>= 0)
231 storeAppendPrintf(entry
, "%d", t
->widthMin
);
233 if (t
->widthMax
>= 0)
234 storeAppendPrintf(entry
, ".%d", t
->widthMax
);
237 storeAppendPrintf(entry
, "{%s}", arg
);
239 storeAppendPrintf(entry
, "%s", t
->label
);
242 entry
->append(" ", 1);
246 entry
->append("\n", 1);
252 log_quoted_string(const char *str
, char *out
)
257 int l
= strcspn(str
, "\"\\\r\n\t");
305 Format::Format::assemble(MemBuf
&mb
, const AccessLogEntry::Pointer
&al
, int logSequenceNumber
) const
310 for (Token
*fmt
= format
; fmt
!= NULL
; fmt
= fmt
->next
) { /* for each token */
311 const char *out
= NULL
;
326 out
= fmt
->data
.string
;
329 case LFT_CLIENT_IP_ADDRESS
:
330 al
->getLogClientIp(tmp
, sizeof(tmp
));
334 case LFT_CLIENT_FQDN
:
335 if (al
->cache
.caddr
.isAnyAddr()) // e.g., ICAP OPTIONS lack client
338 out
= fqdncache_gethostbyaddr(al
->cache
.caddr
, FQDN_LOOKUP_IF_MISS
);
340 out
= al
->cache
.caddr
.toStr(tmp
,1024);
345 case LFT_CLIENT_PORT
:
347 outint
= al
->request
->client_addr
.port();
354 // TODO make the ACL checklist have a direct link to any TCP details.
355 if (al
->request
&& al
->request
->clientConnectionManager
.valid() && al
->request
->clientConnectionManager
->clientConnection
!= NULL
) {
356 if (al
->request
->clientConnectionManager
->clientConnection
->remote
.isIPv4())
357 al
->request
->clientConnectionManager
->clientConnection
->remoteEui48
.encode(tmp
, 1024);
359 al
->request
->clientConnectionManager
->clientConnection
->remoteEui64
.encode(tmp
, 1024);
367 case LFT_SERVER_IP_ADDRESS
:
368 if (al
->hier
.tcpServer
!= NULL
) {
369 out
= al
->hier
.tcpServer
->remote
.toStr(tmp
,sizeof(tmp
));
373 case LFT_SERVER_FQDN_OR_PEER_NAME
:
377 case LFT_SERVER_PORT
:
378 if (al
->hier
.tcpServer
!= NULL
) {
379 outint
= al
->hier
.tcpServer
->remote
.port();
384 case LFT_LOCAL_LISTENING_IP
: {
385 // avoid logging a dash if we have reliable info
386 const bool interceptedAtKnownPort
= al
->request
?
387 (al
->request
->flags
.interceptTproxy
||
388 al
->request
->flags
.intercepted
) && al
->cache
.port
:
390 if (interceptedAtKnownPort
) {
391 const bool portAddressConfigured
= !al
->cache
.port
->s
.isAnyAddr();
392 if (portAddressConfigured
)
393 out
= al
->cache
.port
->s
.toStr(tmp
, sizeof(tmp
));
394 } else if (al
->tcpClient
!= NULL
)
395 out
= al
->tcpClient
->local
.toStr(tmp
, sizeof(tmp
));
399 case LFT_CLIENT_LOCAL_IP
:
400 if (al
->tcpClient
!= NULL
) {
401 out
= al
->tcpClient
->local
.toStr(tmp
,sizeof(tmp
));
405 case LFT_CLIENT_LOCAL_TOS
:
406 if (al
->tcpClient
!= NULL
) {
407 snprintf(tmp
, sizeof(tmp
), "0x%x", (uint32_t)al
->tcpClient
->tos
);
412 case LFT_CLIENT_LOCAL_NFMARK
:
413 if (al
->tcpClient
!= NULL
) {
414 snprintf(tmp
, sizeof(tmp
), "0x%x", al
->tcpClient
->nfmark
);
419 case LFT_LOCAL_LISTENING_PORT
:
420 if (al
->cache
.port
) {
421 outint
= al
->cache
.port
->s
.port();
426 case LFT_CLIENT_LOCAL_PORT
:
427 if (al
->tcpClient
!= NULL
) {
428 outint
= al
->tcpClient
->local
.port();
433 case LFT_SERVER_LOCAL_IP_OLD_27
:
434 case LFT_SERVER_LOCAL_IP
:
435 if (al
->hier
.tcpServer
!= NULL
) {
436 out
= al
->hier
.tcpServer
->local
.toStr(tmp
,sizeof(tmp
));
440 case LFT_SERVER_LOCAL_PORT
:
441 if (al
->hier
.tcpServer
!= NULL
) {
442 outint
= al
->hier
.tcpServer
->local
.port();
448 case LFT_SERVER_LOCAL_TOS
:
449 if (al
->hier
.tcpServer
!= NULL
) {
450 snprintf(tmp
, sizeof(tmp
), "0x%x", (uint32_t)al
->hier
.tcpServer
->tos
);
455 case LFT_SERVER_LOCAL_NFMARK
:
456 if (al
->hier
.tcpServer
!= NULL
) {
457 snprintf(tmp
, sizeof(tmp
), "0x%x", al
->hier
.tcpServer
->nfmark
);
462 case LFT_TIME_SECONDS_SINCE_EPOCH
:
463 // some platforms store time in 32-bit, some 64-bit...
464 outoff
= static_cast<int64_t>(current_time
.tv_sec
);
468 case LFT_TIME_SUBSECOND
:
469 outint
= current_time
.tv_usec
/ fmt
->divisor
;
473 case LFT_TIME_LOCALTIME
:
479 spec
= fmt
->data
.string
;
481 if (fmt
->type
== LFT_TIME_LOCALTIME
) {
483 spec
= "%d/%b/%Y:%H:%M:%S %z";
484 t
= localtime(&squid_curtime
);
487 spec
= "%d/%b/%Y:%H:%M:%S";
489 t
= gmtime(&squid_curtime
);
492 strftime(tmp
, sizeof(tmp
), spec
, t
);
499 case LFT_TIME_START
: {
500 int precision
= fmt
->widthMax
>=0 ? fmt
->widthMax
:3;
501 snprintf(tmp
, sizeof(tmp
), "%0*" PRId64
".%0*d", fmt
->zero
&& (fmt
->widthMin
- precision
- 1 >= 0) ? fmt
->widthMin
- precision
- 1 : 0, static_cast<int64_t>(al
->cache
.start_time
.tv_sec
), precision
, (int)(al
->cache
.start_time
.tv_usec
/ fmt
->divisor
));
506 case LFT_TIME_TO_HANDLE_REQUEST
:
507 outint
= al
->cache
.msec
;
511 case LFT_PEER_RESPONSE_TIME
:
512 if (al
->hier
.peer_response_time
< 0) {
515 outoff
= al
->hier
.peer_response_time
;
520 case LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME
:
521 if (al
->hier
.total_response_time
< 0) {
524 outoff
= al
->hier
.total_response_time
;
529 case LFT_DNS_WAIT_TIME
:
530 if (al
->request
&& al
->request
->dnsWait
>= 0) {
531 outint
= al
->request
->dnsWait
;
536 case LFT_REQUEST_HEADER
:
539 sb
= al
->request
->header
.getByName(fmt
->data
.header
.header
);
541 out
= sb
.termedBuf();
547 case LFT_ADAPTED_REQUEST_HEADER
:
549 if (al
->adapted_request
)
550 sb
= al
->adapted_request
->header
.getByName(fmt
->data
.header
.header
);
552 out
= sb
.termedBuf();
558 case LFT_REPLY_HEADER
:
560 sb
= al
->reply
->header
.getByName(fmt
->data
.header
.header
);
562 out
= sb
.termedBuf();
569 case LFT_ADAPTATION_SUM_XACT_TIMES
:
571 Adaptation::History::Pointer ah
= al
->request
->adaptHistory();
573 ah
->sumLogString(fmt
->data
.string
, sb
);
574 out
= sb
.termedBuf();
578 case LFT_ADAPTATION_ALL_XACT_TIMES
:
580 Adaptation::History::Pointer ah
= al
->request
->adaptHistory();
582 ah
->allLogString(fmt
->data
.string
, sb
);
583 out
= sb
.termedBuf();
587 case LFT_ADAPTATION_LAST_HEADER
:
589 const Adaptation::History::Pointer ah
= al
->request
->adaptHistory();
590 if (ah
!= NULL
) // XXX: add adapt::<all_h but use lastMeta here
591 sb
= ah
->allMeta
.getByName(fmt
->data
.header
.header
);
594 // XXX: here and elsewhere: move such code inside the if guard
595 out
= sb
.termedBuf();
601 case LFT_ADAPTATION_LAST_HEADER_ELEM
:
603 const Adaptation::History::Pointer ah
= al
->request
->adaptHistory();
604 if (ah
!= NULL
) // XXX: add adapt::<all_h but use lastMeta here
605 sb
= ah
->allMeta
.getByNameListMember(fmt
->data
.header
.header
, fmt
->data
.header
.element
, fmt
->data
.header
.separator
);
608 out
= sb
.termedBuf();
614 case LFT_ADAPTATION_LAST_ALL_HEADERS
:
615 out
= al
->adapt
.last_meta
;
625 out
= al
->icap
.hostAddr
.toStr(tmp
,1024);
628 case LFT_ICAP_SERV_NAME
:
629 out
= al
->icap
.serviceName
.termedBuf();
632 case LFT_ICAP_REQUEST_URI
:
633 out
= al
->icap
.reqUri
.termedBuf();
636 case LFT_ICAP_REQUEST_METHOD
:
637 out
= Adaptation::Icap::ICAP::methodStr(al
->icap
.reqMethod
);
640 case LFT_ICAP_BYTES_SENT
:
641 outoff
= al
->icap
.bytesSent
;
645 case LFT_ICAP_BYTES_READ
:
646 outoff
= al
->icap
.bytesRead
;
650 case LFT_ICAP_BODY_BYTES_READ
:
651 if (al
->icap
.bodyBytesRead
>= 0) {
652 outoff
= al
->icap
.bodyBytesRead
;
655 // else if icap.bodyBytesRead < 0, we do not have any http data,
656 // so just print a "-" (204 responses etc)
659 case LFT_ICAP_REQ_HEADER
:
660 if (NULL
!= al
->icap
.request
) {
661 sb
= al
->icap
.request
->header
.getByName(fmt
->data
.header
.header
);
662 out
= sb
.termedBuf();
667 case LFT_ICAP_REQ_HEADER_ELEM
:
668 if (al
->icap
.request
)
669 sb
= al
->icap
.request
->header
.getByNameListMember(fmt
->data
.header
.header
, fmt
->data
.header
.element
, fmt
->data
.header
.separator
);
671 out
= sb
.termedBuf();
677 case LFT_ICAP_REQ_ALL_HEADERS
:
678 if (al
->icap
.request
) {
679 HttpHeaderPos pos
= HttpHeaderInitPos
;
680 while (const HttpHeaderEntry
*e
= al
->icap
.request
->header
.getEntry(&pos
)) {
686 out
= sb
.termedBuf();
691 case LFT_ICAP_REP_HEADER
:
692 if (NULL
!= al
->icap
.reply
) {
693 sb
= al
->icap
.reply
->header
.getByName(fmt
->data
.header
.header
);
694 out
= sb
.termedBuf();
699 case LFT_ICAP_REP_HEADER_ELEM
:
700 if (NULL
!= al
->icap
.reply
)
701 sb
= al
->icap
.reply
->header
.getByNameListMember(fmt
->data
.header
.header
, fmt
->data
.header
.element
, fmt
->data
.header
.separator
);
703 out
= sb
.termedBuf();
709 case LFT_ICAP_REP_ALL_HEADERS
:
710 if (al
->icap
.reply
) {
711 HttpHeaderPos pos
= HttpHeaderInitPos
;
712 while (const HttpHeaderEntry
*e
= al
->icap
.reply
->header
.getEntry(&pos
)) {
718 out
= sb
.termedBuf();
723 case LFT_ICAP_TR_RESPONSE_TIME
:
724 outint
= al
->icap
.trTime
;
728 case LFT_ICAP_IO_TIME
:
729 outint
= al
->icap
.ioTime
;
733 case LFT_ICAP_STATUS_CODE
:
734 outint
= al
->icap
.resStatus
;
738 case LFT_ICAP_OUTCOME
:
739 out
= al
->icap
.outcome
;
742 case LFT_ICAP_TOTAL_TIME
:
743 outint
= al
->icap
.processingTime
;
747 case LFT_REQUEST_HEADER_ELEM
:
749 sb
= al
->request
->header
.getByNameListMember(fmt
->data
.header
.header
, fmt
->data
.header
.element
, fmt
->data
.header
.separator
);
751 out
= sb
.termedBuf();
757 case LFT_ADAPTED_REQUEST_HEADER_ELEM
:
758 if (al
->adapted_request
)
759 sb
= al
->adapted_request
->header
.getByNameListMember(fmt
->data
.header
.header
, fmt
->data
.header
.element
, fmt
->data
.header
.separator
);
761 out
= sb
.termedBuf();
767 case LFT_REPLY_HEADER_ELEM
:
769 sb
= al
->reply
->header
.getByNameListMember(fmt
->data
.header
.header
, fmt
->data
.header
.element
, fmt
->data
.header
.separator
);
771 out
= sb
.termedBuf();
777 case LFT_REQUEST_ALL_HEADERS
:
778 out
= al
->headers
.request
;
784 case LFT_ADAPTED_REQUEST_ALL_HEADERS
:
785 out
= al
->headers
.adapted_request
;
791 case LFT_REPLY_ALL_HEADERS
:
792 out
= al
->headers
.reply
;
800 if (al
->request
&& al
->request
->auth_user_request
!= NULL
)
801 out
= strOrNull(al
->request
->auth_user_request
->username());
804 out
= strOrNull(al
->cache
.extuser
);
807 out
= strOrNull(al
->cache
.ssluser
);
810 out
= strOrNull(al
->cache
.rfc931
);
815 if (al
->request
&& al
->request
->auth_user_request
!= NULL
)
816 out
= strOrNull(al
->request
->auth_user_request
->username());
821 out
= strOrNull(al
->cache
.rfc931
);
824 case LFT_USER_EXTERNAL
:
825 out
= strOrNull(al
->cache
.extuser
);
828 /* case LFT_USER_REALM: */
829 /* case LFT_USER_SCHEME: */
831 // the fmt->type can not be LFT_HTTP_SENT_STATUS_CODE_OLD_30
832 // but compiler complains if ommited
833 case LFT_HTTP_SENT_STATUS_CODE_OLD_30
:
834 case LFT_HTTP_SENT_STATUS_CODE
:
835 outint
= al
->http
.code
;
841 case LFT_HTTP_RECEIVED_STATUS_CODE
:
842 if (al
->hier
.peer_reply_status
== Http::scNone
) {
845 outint
= al
->hier
.peer_reply_status
;
849 /* case LFT_HTTP_STATUS:
850 * out = statusline->text;
854 case LFT_HTTP_BODY_BYTES_READ
:
855 if (al
->hier
.bodyBytesRead
>= 0) {
856 outoff
= al
->hier
.bodyBytesRead
;
859 // else if hier.bodyBytesRead < 0 we did not have any data exchange with
860 // a peer server so just print a "-" (eg requests served from cache,
861 // or internal error messages).
864 case LFT_SQUID_STATUS
:
865 if (al
->http
.timedout
|| al
->http
.aborted
) {
866 snprintf(tmp
, sizeof(tmp
), "%s%s", LogTags_str
[al
->cache
.code
],
867 al
->http
.statusSfx());
870 out
= LogTags_str
[al
->cache
.code
];
875 case LFT_SQUID_ERROR
:
876 if (al
->request
&& al
->request
->errType
!= ERR_NONE
)
877 out
= errorPageName(al
->request
->errType
);
880 case LFT_SQUID_ERROR_DETAIL
:
882 if (al
->request
&& al
->request
->errType
== ERR_SECURE_CONNECT_FAIL
) {
883 if (! (out
= Ssl::GetErrorName(al
->request
->errDetail
))) {
884 snprintf(tmp
, sizeof(tmp
), "SSL_ERR=%d", al
->request
->errDetail
);
889 if (al
->request
&& al
->request
->errDetail
!= ERR_DETAIL_NONE
) {
890 if (al
->request
->errDetail
> ERR_DETAIL_START
&&
891 al
->request
->errDetail
< ERR_DETAIL_MAX
)
892 out
= errorDetailName(al
->request
->errDetail
);
894 if (al
->request
->errDetail
>= ERR_DETAIL_EXCEPTION_START
)
895 snprintf(tmp
, sizeof(tmp
), "%s=0x%X",
896 errorDetailName(al
->request
->errDetail
), (uint32_t) al
->request
->errDetail
);
898 snprintf(tmp
, sizeof(tmp
), "%s=%d",
899 errorDetailName(al
->request
->errDetail
), al
->request
->errDetail
);
905 case LFT_SQUID_HIERARCHY
:
906 if (al
->hier
.ping
.timedout
)
907 mb
.append("TIMEOUT_", 8);
909 out
= hier_code_str
[al
->hier
.code
];
914 out
= al
->http
.content_type
;
918 case LFT_CLIENT_REQ_METHOD
:
920 const SBuf
&s
= al
->request
->method
.image();
921 sb
.append(s
.rawContent(), s
.length());
922 out
= sb
.termedBuf();
927 case LFT_CLIENT_REQ_URI
:
928 // original client URI
930 out
= urlCanonical(al
->request
);
935 case LFT_CLIENT_REQ_URLSCHEME
:
937 out
= al
->request
->url
.getScheme().c_str();
942 case LFT_CLIENT_REQ_URLDOMAIN
:
944 out
= al
->request
->GetHost();
949 case LFT_CLIENT_REQ_URLPORT
:
951 outint
= al
->request
->port
;
956 case LFT_REQUEST_URLPATH_OLD_31
:
957 case LFT_CLIENT_REQ_URLPATH
:
959 out
= al
->request
->urlpath
.termedBuf();
964 case LFT_CLIENT_REQ_VERSION
:
966 snprintf(tmp
, sizeof(tmp
), "%d.%d", (int) al
->request
->http_ver
.major
, (int) al
->request
->http_ver
.minor
);
971 case LFT_REQUEST_METHOD
:
972 if (al
->_private
.method_str
) // ICP, HTCP method code
973 out
= al
->_private
.method_str
;
975 const SBuf
&s
= al
->http
.method
.image();
976 sb
.append(s
.rawContent(), s
.length());
977 out
= sb
.termedBuf();
982 case LFT_REQUEST_URI
:
986 case LFT_REQUEST_VERSION_OLD_2X
:
987 case LFT_REQUEST_VERSION
:
988 snprintf(tmp
, sizeof(tmp
), "%d.%d", (int) al
->http
.version
.major
, (int) al
->http
.version
.minor
);
992 case LFT_SERVER_REQ_METHOD
:
993 if (al
->adapted_request
) {
994 const SBuf
&s
= al
->adapted_request
->method
.image();
995 sb
.append(s
.rawContent(), s
.length());
996 out
= sb
.termedBuf();
1001 case LFT_SERVER_REQ_URI
:
1002 // adapted request URI sent to server/peer
1003 if (al
->adapted_request
) {
1004 out
= urlCanonical(al
->adapted_request
);
1009 case LFT_SERVER_REQ_URLSCHEME
:
1010 if (al
->adapted_request
) {
1011 out
= al
->adapted_request
->url
.getScheme().c_str();
1016 case LFT_SERVER_REQ_URLDOMAIN
:
1017 if (al
->adapted_request
) {
1018 out
= al
->adapted_request
->GetHost();
1023 case LFT_SERVER_REQ_URLPORT
:
1024 if (al
->adapted_request
) {
1025 outint
= al
->adapted_request
->port
;
1030 case LFT_SERVER_REQ_URLPATH
:
1031 if (al
->adapted_request
) {
1032 out
= al
->adapted_request
->urlpath
.termedBuf();
1037 case LFT_SERVER_REQ_VERSION
:
1038 if (al
->adapted_request
) {
1039 snprintf(tmp
, sizeof(tmp
), "%d.%d",
1040 (int) al
->adapted_request
->http_ver
.major
,
1041 (int) al
->adapted_request
->http_ver
.minor
);
1046 case LFT_CLIENT_REQUEST_SIZE_TOTAL
:
1047 outoff
= al
->http
.clientRequestSz
.messageTotal();
1051 case LFT_CLIENT_REQUEST_SIZE_HEADERS
:
1052 outoff
= al
->http
.clientRequestSz
.header
;
1056 /*case LFT_REQUEST_SIZE_BODY: */
1057 /*case LFT_REQUEST_SIZE_BODY_NO_TE: */
1059 case LFT_ADAPTED_REPLY_SIZE_TOTAL
:
1060 outoff
= al
->http
.clientReplySz
.messageTotal();
1064 case LFT_REPLY_HIGHOFFSET
:
1065 outoff
= al
->cache
.highOffset
;
1071 case LFT_REPLY_OBJECTSIZE
:
1072 outoff
= al
->cache
.objectSize
;
1078 case LFT_ADAPTED_REPLY_SIZE_HEADERS
:
1079 outint
= al
->http
.clientReplySz
.header
;
1083 /*case LFT_REPLY_SIZE_BODY: */
1084 /*case LFT_REPLY_SIZE_BODY_NO_TE: */
1086 case LFT_CLIENT_IO_SIZE_TOTAL
:
1087 outint
= al
->http
.clientRequestSz
.messageTotal() + al
->http
.clientReplySz
.messageTotal();
1090 /*case LFT_SERVER_IO_SIZE_TOTAL: */
1094 out
= al
->request
->tag
.termedBuf();
1102 out
= al
->request
->extacl_log
.termedBuf();
1108 case LFT_SEQUENCE_NUMBER
:
1109 outoff
= logSequenceNumber
;
1114 case LFT_SSL_BUMP_MODE
: {
1115 const Ssl::BumpMode mode
= static_cast<Ssl::BumpMode
>(al
->ssl
.bumpMode
);
1116 // for Ssl::bumpEnd, Ssl::bumpMode() returns NULL and we log '-'
1117 out
= Ssl::bumpMode(mode
);
1121 case LFT_SSL_USER_CERT_SUBJECT
:
1122 if (X509
*cert
= al
->cache
.sslClientCert
.get()) {
1123 if (X509_NAME
*subject
= X509_get_subject_name(cert
)) {
1124 X509_NAME_oneline(subject
, tmp
, sizeof(tmp
));
1130 case LFT_SSL_USER_CERT_ISSUER
:
1131 if (X509
*cert
= al
->cache
.sslClientCert
.get()) {
1132 if (X509_NAME
*issuer
= X509_get_issuer_name(cert
)) {
1133 X509_NAME_oneline(issuer
, tmp
, sizeof(tmp
));
1138 case LFT_SSL_CLIENT_SNI
:
1139 if (al
->request
&& al
->request
->clientConnectionManager
.valid()) {
1140 if (Ssl::ServerBump
* srvBump
= al
->request
->clientConnectionManager
->serverBump()) {
1141 if (!srvBump
->clientSni
.isEmpty())
1142 out
= srvBump
->clientSni
.c_str();
1148 case LFT_REQUEST_URLGROUP_OLD_2X
:
1149 assert(LFT_REQUEST_URLGROUP_OLD_2X
== 0); // should never happen.
1152 tmp
[0] = fmt
->data
.header
.separator
;
1154 if (fmt
->data
.header
.header
&& *fmt
->data
.header
.header
) {
1155 const char *separator
= tmp
;
1157 Adaptation::History::Pointer ah
= al
->request
? al
->request
->adaptHistory() : Adaptation::History::Pointer();
1158 if (ah
!= NULL
&& ah
->metaHeaders
!= NULL
) {
1159 if (const char *meta
= ah
->metaHeaders
->find(fmt
->data
.header
.header
, separator
))
1163 if (al
->notes
!= NULL
) {
1164 if (const char *note
= al
->notes
->find(fmt
->data
.header
.header
, separator
)) {
1166 sb
.append(separator
);
1170 out
= sb
.termedBuf();
1173 // if no argument given use default "\r\n" as notes separator
1174 const char *separator
= fmt
->data
.string
? tmp
: "\r\n";
1176 Adaptation::History::Pointer ah
= al
->request
? al
->request
->adaptHistory() : Adaptation::History::Pointer();
1177 if (ah
!= NULL
&& ah
->metaHeaders
!= NULL
&& !ah
->metaHeaders
->empty())
1178 sb
.append(ah
->metaHeaders
->toString(separator
));
1180 if (al
->notes
!= NULL
&& !al
->notes
->empty())
1181 sb
.append(al
->notes
->toString(separator
));
1183 out
= sb
.termedBuf();
1188 case LFT_CREDENTIALS
:
1190 if (al
->request
&& al
->request
->auth_user_request
!= NULL
)
1191 out
= strOrNull(al
->request
->auth_user_request
->credentialsStr());
1200 // XXX: external_acl_type format tokens which are not output by logformat.
1201 // They are listed here because the switch requires
1202 // every ByteCode_t to be explicitly enumerated.
1203 // But do not output due to lack of access to the values.
1204 case LFT_EXT_ACL_USER_CERT_RAW
:
1205 case LFT_EXT_ACL_USER_CERTCHAIN_RAW
:
1206 case LFT_EXT_ACL_USER_CERT
:
1207 case LFT_EXT_ACL_USER_CA_CERT
:
1208 case LFT_EXT_ACL_CLIENT_EUI48
:
1209 case LFT_EXT_ACL_CLIENT_EUI64
:
1210 case LFT_EXT_ACL_NAME
:
1211 case LFT_EXT_ACL_DATA
:
1216 snprintf(tmp
, sizeof(tmp
), "%0*" PRId64
, fmt
->zero
&& fmt
->widthMin
>= 0 ? fmt
->widthMin
: 0, outoff
);
1220 snprintf(tmp
, sizeof(tmp
), "%0*ld", fmt
->zero
&& fmt
->widthMin
>= 0 ? fmt
->widthMin
: 0, outint
);
1225 if (quote
|| fmt
->quote
!= LOG_QUOTE_NONE
) {
1226 char *newout
= NULL
;
1229 switch (fmt
->quote
) {
1231 case LOG_QUOTE_NONE
:
1232 newout
= rfc1738_escape_unescaped(out
);
1235 case LOG_QUOTE_QUOTES
: {
1236 size_t out_len
= static_cast<size_t>(strlen(out
)) * 2 + 1;
1237 if (out_len
>= sizeof(tmp
)) {
1238 newout
= (char *)xmalloc(out_len
);
1242 log_quoted_string(out
, newout
);
1246 case LOG_QUOTE_MIMEBLOB
:
1247 newout
= QuoteMimeBlob(out
);
1252 newout
= rfc1738_escape(out
);
1269 // enforce width limits if configured
1270 const bool haveMaxWidth
= fmt
->widthMax
>=0 && !doint
&& !dooff
&& !fmt
->divisor
;
1271 if (haveMaxWidth
|| fmt
->widthMin
) {
1272 const int minWidth
= fmt
->widthMin
>= 0 ?
1274 const int maxWidth
= haveMaxWidth
?
1275 fmt
->widthMax
: strlen(out
);
1278 mb
.Printf("%-*.*s", minWidth
, maxWidth
, out
);
1280 mb
.Printf("%*.*s", minWidth
, maxWidth
, out
);
1282 mb
.append(out
, strlen(out
));