2 #include "AccessLogEntry.h"
3 #include "comm/Connection.h"
4 #include "err_detail_type.h"
6 #include "format/Format.h"
7 #include "format/Quoting.h"
8 #include "format/Token.h"
9 #include "HttpRequest.h"
12 #include "SquidTime.h"
15 #include "ssl/ErrorDetail.h"
19 /// Convert a string to NULL pointer if it is ""
20 #define strOrNull(s) ((s)==NULL||(s)[0]=='\0'?NULL:(s))
22 Format::Format::Format(const char *n
) :
29 Format::Format::~Format()
31 // erase the list without consuming stack space
33 // unlink the next entry for deletion
46 Format::Format::parse(char *def
)
49 Token
*new_lt
, *last_lt
;
50 enum Quoting quote
= LOG_QUOTE_NONE
;
52 debugs(46, 2, HERE
<< "got definition '" << def
<< "'");
55 debugs(46, DBG_IMPORTANT
, "WARNING: existing format for '" << name
<< " " << def
<< "'");
59 /* very inefficent parser, but who cares, this needs to be simple */
60 /* First off, let's tokenize, we'll optimize in a second pass.
61 * A token can either be a %-prefixed sequence (usually a dynamic
62 * token but it can be an escaped sequence), or a string. */
64 eos
= def
+ strlen(def
);
65 format
= new_lt
= last_lt
= new Token
;
66 cur
+= new_lt
->parse(cur
, "e
);
70 last_lt
->next
= new_lt
;
72 cur
+= new_lt
->parse(cur
, "e
);
79 Format::Format::dump(StoreEntry
* entry
, const char *name
)
83 // loop rather than recursing to conserve stack space.
84 for (Format
*format
= this; format
; format
= format
->next
) {
85 debugs(46, 3, HERE
<< "Dumping format definition for " << format
->name
);
86 storeAppendPrintf(entry
, "format %s ", format
->name
);
88 for (Token
*t
= format
->format
; t
; t
= t
->next
) {
89 if (t
->type
== LFT_STRING
)
90 storeAppendPrintf(entry
, "%s", t
->data
.string
);
94 ByteCode_t type
= t
->type
;
102 case LFT_ADAPTATION_LAST_HEADER_ELEM
:
105 case LFT_ICAP_REQ_HEADER_ELEM
:
106 case LFT_ICAP_REP_HEADER_ELEM
:
108 case LFT_REQUEST_HEADER_ELEM
:
109 case LFT_ADAPTED_REQUEST_HEADER_ELEM
:
110 case LFT_REPLY_HEADER_ELEM
:
112 if (t
->data
.header
.separator
!= ',')
113 snprintf(argbuf
, sizeof(argbuf
), "%s:%c%s", t
->data
.header
.header
, t
->data
.header
.separator
, t
->data
.header
.element
);
115 snprintf(argbuf
, sizeof(argbuf
), "%s:%s", t
->data
.header
.header
, t
->data
.header
.element
);
120 case LFT_REQUEST_HEADER_ELEM
:
121 type
= LFT_REQUEST_HEADER_ELEM
; // XXX: remove _ELEM?
123 case LFT_ADAPTED_REQUEST_HEADER_ELEM
:
124 type
= LFT_ADAPTED_REQUEST_HEADER_ELEM
; // XXX: remove _ELEM?
126 case LFT_REPLY_HEADER_ELEM
:
127 type
= LFT_REPLY_HEADER_ELEM
; // XXX: remove _ELEM?
130 case LFT_ADAPTATION_LAST_HEADER_ELEM
:
131 type
= LFT_ADAPTATION_LAST_HEADER
;
135 case LFT_ICAP_REQ_HEADER_ELEM
:
136 type
= LFT_ICAP_REQ_HEADER
;
138 case LFT_ICAP_REP_HEADER_ELEM
:
139 type
= LFT_ICAP_REP_HEADER
;
148 case LFT_REQUEST_ALL_HEADERS
:
149 case LFT_ADAPTED_REQUEST_ALL_HEADERS
:
150 case LFT_REPLY_ALL_HEADERS
:
153 case LFT_ADAPTATION_LAST_ALL_HEADERS
:
156 case LFT_ICAP_REQ_ALL_HEADERS
:
157 case LFT_ICAP_REP_ALL_HEADERS
:
161 case LFT_REQUEST_ALL_HEADERS
:
162 type
= LFT_REQUEST_HEADER
;
164 case LFT_ADAPTED_REQUEST_ALL_HEADERS
:
165 type
= LFT_ADAPTED_REQUEST_HEADER
;
167 case LFT_REPLY_ALL_HEADERS
:
168 type
= LFT_REPLY_HEADER
;
171 case LFT_ADAPTATION_LAST_ALL_HEADERS
:
172 type
= LFT_ADAPTATION_LAST_HEADER
;
176 case LFT_ICAP_REQ_ALL_HEADERS
:
177 type
= LFT_ICAP_REQ_HEADER
;
179 case LFT_ICAP_REP_ALL_HEADERS
:
180 type
= LFT_ICAP_REP_HEADER
;
191 arg
= t
->data
.string
;
196 entry
->append("%", 1);
200 case LOG_QUOTE_QUOTES
:
201 entry
->append("\"", 1);
204 case LOG_QUOTE_MIMEBLOB
:
205 entry
->append("[", 1);
209 entry
->append("#", 1);
213 entry
->append("'", 1);
221 entry
->append("-", 1);
224 entry
->append("0", 1);
226 if (t
->widthMin
>= 0)
227 storeAppendPrintf(entry
, "%d", t
->widthMin
);
229 if (t
->widthMax
>= 0)
230 storeAppendPrintf(entry
, ".%d", t
->widthMax
);
233 storeAppendPrintf(entry
, "{%s}", arg
);
235 storeAppendPrintf(entry
, "%s", t
->label
);
238 entry
->append(" ", 1);
242 entry
->append("\n", 1);
248 log_quoted_string(const char *str
, char *out
)
253 int l
= strcspn(str
, "\"\\\r\n\t");
293 Format::Format::assemble(MemBuf
&mb
, AccessLogEntry
*al
, int logSequenceNumber
) const
298 for (Token
*fmt
= format
; fmt
!= NULL
; fmt
= fmt
->next
) { /* for each token */
299 const char *out
= NULL
;
314 out
= fmt
->data
.string
;
317 case LFT_CLIENT_IP_ADDRESS
:
318 al
->getLogClientIp(tmp
, sizeof(tmp
));
322 case LFT_CLIENT_FQDN
:
323 if (al
->cache
.caddr
.IsAnyAddr()) // e.g., ICAP OPTIONS lack client
326 out
= fqdncache_gethostbyaddr(al
->cache
.caddr
, FQDN_LOOKUP_IF_MISS
);
328 out
= al
->cache
.caddr
.NtoA(tmp
,1024);
333 case LFT_CLIENT_PORT
:
335 outint
= al
->request
->client_addr
.GetPort();
342 // TODO make the ACL checklist have a direct link to any TCP details.
343 if (al
->request
&& al
->request
->clientConnectionManager
.valid() && al
->request
->clientConnectionManager
->clientConnection
!= NULL
) {
344 if (al
->request
->clientConnectionManager
->clientConnection
->remote
.IsIPv4())
345 al
->request
->clientConnectionManager
->clientConnection
->remoteEui48
.encode(tmp
, 1024);
347 al
->request
->clientConnectionManager
->clientConnection
->remoteEui64
.encode(tmp
, 1024);
355 case LFT_SERVER_IP_ADDRESS
:
356 if (al
->hier
.tcpServer
!= NULL
) {
357 out
= al
->hier
.tcpServer
->remote
.NtoA(tmp
,sizeof(tmp
));
361 case LFT_SERVER_FQDN_OR_PEER_NAME
:
365 case LFT_SERVER_PORT
:
366 if (al
->hier
.tcpServer
!= NULL
) {
367 outint
= al
->hier
.tcpServer
->remote
.GetPort();
372 case LFT_LOCAL_LISTENING_IP
: {
373 // avoid logging a dash if we have reliable info
374 const bool interceptedAtKnownPort
= al
->request
?
375 (al
->request
->flags
.spoof_client_ip
||
376 al
->request
->flags
.intercepted
) && al
->cache
.port
:
378 if (interceptedAtKnownPort
) {
379 const bool portAddressConfigured
= !al
->cache
.port
->s
.IsAnyAddr();
380 if (portAddressConfigured
)
381 out
= al
->cache
.port
->s
.NtoA(tmp
, sizeof(tmp
));
382 } else if (al
->tcpClient
!= NULL
)
383 out
= al
->tcpClient
->local
.NtoA(tmp
, sizeof(tmp
));
387 case LFT_CLIENT_LOCAL_IP
:
388 if (al
->tcpClient
!= NULL
) {
389 out
= al
->tcpClient
->local
.NtoA(tmp
,sizeof(tmp
));
393 case LFT_LOCAL_LISTENING_PORT
:
394 if (al
->cache
.port
) {
395 outint
= al
->cache
.port
->s
.GetPort();
400 case LFT_CLIENT_LOCAL_PORT
:
401 if (al
->tcpClient
!= NULL
) {
402 outint
= al
->tcpClient
->local
.GetPort();
407 case LFT_SERVER_LOCAL_IP_OLD_27
:
408 case LFT_SERVER_LOCAL_IP
:
409 if (al
->hier
.tcpServer
!= NULL
) {
410 out
= al
->hier
.tcpServer
->local
.NtoA(tmp
,sizeof(tmp
));
414 case LFT_SERVER_LOCAL_PORT
:
415 if (al
->hier
.tcpServer
!= NULL
) {
416 outint
= al
->hier
.tcpServer
->local
.GetPort();
422 case LFT_TIME_SECONDS_SINCE_EPOCH
:
423 // some platforms store time in 32-bit, some 64-bit...
424 outoff
= static_cast<int64_t>(current_time
.tv_sec
);
428 case LFT_TIME_SUBSECOND
:
429 outint
= current_time
.tv_usec
/ fmt
->divisor
;
434 case LFT_TIME_LOCALTIME
:
440 spec
= fmt
->data
.timespec
;
442 if (fmt
->type
== LFT_TIME_LOCALTIME
) {
444 spec
= "%d/%b/%Y:%H:%M:%S %z";
445 t
= localtime(&squid_curtime
);
448 spec
= "%d/%b/%Y:%H:%M:%S";
450 t
= gmtime(&squid_curtime
);
453 strftime(tmp
, sizeof(tmp
), spec
, t
);
460 case LFT_TIME_TO_HANDLE_REQUEST
:
461 outint
= al
->cache
.msec
;
465 case LFT_PEER_RESPONSE_TIME
:
466 if (al
->hier
.peer_response_time
< 0) {
469 outoff
= al
->hier
.peer_response_time
;
474 case LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME
:
475 if (al
->hier
.total_response_time
< 0) {
478 outoff
= al
->hier
.total_response_time
;
483 case LFT_DNS_WAIT_TIME
:
484 if (al
->request
&& al
->request
->dnsWait
>= 0) {
485 outint
= al
->request
->dnsWait
;
490 case LFT_REQUEST_HEADER
:
493 sb
= al
->request
->header
.getByName(fmt
->data
.header
.header
);
495 out
= sb
.termedBuf();
501 case LFT_ADAPTED_REQUEST_HEADER
:
504 sb
= al
->adapted_request
->header
.getByName(fmt
->data
.header
.header
);
506 out
= sb
.termedBuf();
512 case LFT_REPLY_HEADER
:
514 sb
= al
->reply
->header
.getByName(fmt
->data
.header
.header
);
516 out
= sb
.termedBuf();
523 case LFT_ADAPTATION_SUM_XACT_TIMES
:
525 Adaptation::History::Pointer ah
= al
->request
->adaptHistory();
527 ah
->sumLogString(fmt
->data
.string
, sb
);
528 out
= sb
.termedBuf();
532 case LFT_ADAPTATION_ALL_XACT_TIMES
:
534 Adaptation::History::Pointer ah
= al
->request
->adaptHistory();
536 ah
->allLogString(fmt
->data
.string
, sb
);
537 out
= sb
.termedBuf();
541 case LFT_ADAPTATION_LAST_HEADER
:
543 const Adaptation::History::Pointer ah
= al
->request
->adaptHistory();
544 if (ah
!= NULL
) // XXX: add adapt::<all_h but use lastMeta here
545 sb
= ah
->allMeta
.getByName(fmt
->data
.header
.header
);
548 // XXX: here and elsewhere: move such code inside the if guard
549 out
= sb
.termedBuf();
555 case LFT_ADAPTATION_LAST_HEADER_ELEM
:
557 const Adaptation::History::Pointer ah
= al
->request
->adaptHistory();
558 if (ah
!= NULL
) // XXX: add adapt::<all_h but use lastMeta here
559 sb
= ah
->allMeta
.getByNameListMember(fmt
->data
.header
.header
, fmt
->data
.header
.element
, fmt
->data
.header
.separator
);
562 out
= sb
.termedBuf();
568 case LFT_ADAPTATION_LAST_ALL_HEADERS
:
569 out
= al
->adapt
.last_meta
;
579 out
= al
->icap
.hostAddr
.NtoA(tmp
,1024);
582 case LFT_ICAP_SERV_NAME
:
583 out
= al
->icap
.serviceName
.termedBuf();
586 case LFT_ICAP_REQUEST_URI
:
587 out
= al
->icap
.reqUri
.termedBuf();
590 case LFT_ICAP_REQUEST_METHOD
:
591 out
= Adaptation::Icap::ICAP::methodStr(al
->icap
.reqMethod
);
594 case LFT_ICAP_BYTES_SENT
:
595 outoff
= al
->icap
.bytesSent
;
599 case LFT_ICAP_BYTES_READ
:
600 outoff
= al
->icap
.bytesRead
;
604 case LFT_ICAP_BODY_BYTES_READ
:
605 if (al
->icap
.bodyBytesRead
>= 0) {
606 outoff
= al
->icap
.bodyBytesRead
;
609 // else if icap.bodyBytesRead < 0, we do not have any http data,
610 // so just print a "-" (204 responses etc)
613 case LFT_ICAP_REQ_HEADER
:
614 if (NULL
!= al
->icap
.request
) {
615 sb
= al
->icap
.request
->header
.getByName(fmt
->data
.header
.header
);
616 out
= sb
.termedBuf();
621 case LFT_ICAP_REQ_HEADER_ELEM
:
623 sb
= al
->icap
.request
->header
.getByNameListMember(fmt
->data
.header
.header
, fmt
->data
.header
.element
, fmt
->data
.header
.separator
);
625 out
= sb
.termedBuf();
631 case LFT_ICAP_REQ_ALL_HEADERS
:
632 if (al
->icap
.request
) {
633 HttpHeaderPos pos
= HttpHeaderInitPos
;
634 while (const HttpHeaderEntry
*e
= al
->icap
.request
->header
.getEntry(&pos
)) {
640 out
= sb
.termedBuf();
645 case LFT_ICAP_REP_HEADER
:
646 if (NULL
!= al
->icap
.reply
) {
647 sb
= al
->icap
.reply
->header
.getByName(fmt
->data
.header
.header
);
648 out
= sb
.termedBuf();
653 case LFT_ICAP_REP_HEADER_ELEM
:
654 if (NULL
!= al
->icap
.reply
)
655 sb
= al
->icap
.reply
->header
.getByNameListMember(fmt
->data
.header
.header
, fmt
->data
.header
.element
, fmt
->data
.header
.separator
);
657 out
= sb
.termedBuf();
663 case LFT_ICAP_REP_ALL_HEADERS
:
664 if (al
->icap
.reply
) {
665 HttpHeaderPos pos
= HttpHeaderInitPos
;
666 while (const HttpHeaderEntry
*e
= al
->icap
.reply
->header
.getEntry(&pos
)) {
672 out
= sb
.termedBuf();
677 case LFT_ICAP_TR_RESPONSE_TIME
:
678 outint
= al
->icap
.trTime
;
682 case LFT_ICAP_IO_TIME
:
683 outint
= al
->icap
.ioTime
;
687 case LFT_ICAP_STATUS_CODE
:
688 outint
= al
->icap
.resStatus
;
692 case LFT_ICAP_OUTCOME
:
693 out
= al
->icap
.outcome
;
696 case LFT_ICAP_TOTAL_TIME
:
697 outint
= al
->icap
.processingTime
;
701 case LFT_REQUEST_HEADER_ELEM
:
703 sb
= al
->request
->header
.getByNameListMember(fmt
->data
.header
.header
, fmt
->data
.header
.element
, fmt
->data
.header
.separator
);
705 out
= sb
.termedBuf();
711 case LFT_ADAPTED_REQUEST_HEADER_ELEM
:
712 if (al
->adapted_request
)
713 sb
= al
->adapted_request
->header
.getByNameListMember(fmt
->data
.header
.header
, fmt
->data
.header
.element
, fmt
->data
.header
.separator
);
715 out
= sb
.termedBuf();
721 case LFT_REPLY_HEADER_ELEM
:
723 sb
= al
->reply
->header
.getByNameListMember(fmt
->data
.header
.header
, fmt
->data
.header
.element
, fmt
->data
.header
.separator
);
725 out
= sb
.termedBuf();
731 case LFT_REQUEST_ALL_HEADERS
:
732 out
= al
->headers
.request
;
738 case LFT_ADAPTED_REQUEST_ALL_HEADERS
:
739 out
= al
->headers
.adapted_request
;
745 case LFT_REPLY_ALL_HEADERS
:
746 out
= al
->headers
.reply
;
753 out
= strOrNull(al
->cache
.authuser
);
755 out
= strOrNull(al
->cache
.extuser
);
758 out
= strOrNull(al
->cache
.ssluser
);
761 out
= strOrNull(al
->cache
.rfc931
);
765 out
= strOrNull(al
->cache
.authuser
);
769 out
= strOrNull(al
->cache
.rfc931
);
772 case LFT_USER_EXTERNAL
:
773 out
= strOrNull(al
->cache
.extuser
);
776 /* case LFT_USER_REALM: */
777 /* case LFT_USER_SCHEME: */
779 // the fmt->type can not be LFT_HTTP_SENT_STATUS_CODE_OLD_30
780 // but compiler complains if ommited
781 case LFT_HTTP_SENT_STATUS_CODE_OLD_30
:
782 case LFT_HTTP_SENT_STATUS_CODE
:
783 outint
= al
->http
.code
;
789 case LFT_HTTP_RECEIVED_STATUS_CODE
:
790 if (al
->hier
.peer_reply_status
== HTTP_STATUS_NONE
) {
793 outint
= al
->hier
.peer_reply_status
;
797 /* case LFT_HTTP_STATUS:
798 * out = statusline->text;
802 case LFT_HTTP_BODY_BYTES_READ
:
803 if (al
->hier
.bodyBytesRead
>= 0) {
804 outoff
= al
->hier
.bodyBytesRead
;
807 // else if hier.bodyBytesRead < 0 we did not have any data exchange with
808 // a peer server so just print a "-" (eg requests served from cache,
809 // or internal error messages).
812 case LFT_SQUID_STATUS
:
813 if (al
->http
.timedout
|| al
->http
.aborted
) {
814 snprintf(tmp
, sizeof(tmp
), "%s%s", log_tags
[al
->cache
.code
],
815 al
->http
.statusSfx());
818 out
= log_tags
[al
->cache
.code
];
823 case LFT_SQUID_ERROR
:
824 if (al
->request
&& al
->request
->errType
!= ERR_NONE
)
825 out
= errorPageName(al
->request
->errType
);
828 case LFT_SQUID_ERROR_DETAIL
:
830 if (al
->request
&& al
->request
->errType
== ERR_SECURE_CONNECT_FAIL
) {
831 if (! (out
= Ssl::GetErrorName(al
->request
->errDetail
))) {
832 snprintf(tmp
, sizeof(tmp
), "SSL_ERR=%d", al
->request
->errDetail
);
837 if (al
->request
&& al
->request
->errDetail
!= ERR_DETAIL_NONE
) {
838 if (al
->request
->errDetail
> ERR_DETAIL_START
&&
839 al
->request
->errDetail
< ERR_DETAIL_MAX
)
840 out
= errorDetailName(al
->request
->errDetail
);
842 if (al
->request
->errDetail
>= ERR_DETAIL_EXCEPTION_START
)
843 snprintf(tmp
, sizeof(tmp
), "%s=0x%X",
844 errorDetailName(al
->request
->errDetail
), (uint32_t) al
->request
->errDetail
);
846 snprintf(tmp
, sizeof(tmp
), "%s=%d",
847 errorDetailName(al
->request
->errDetail
), al
->request
->errDetail
);
853 case LFT_SQUID_HIERARCHY
:
854 if (al
->hier
.ping
.timedout
)
855 mb
.append("TIMEOUT_", 8);
857 out
= hier_code_str
[al
->hier
.code
];
862 out
= al
->http
.content_type
;
866 case LFT_CLIENT_REQ_METHOD
:
868 out
= al
->request
->method
.image();
873 case LFT_CLIENT_REQ_URI
:
874 // original client URI
876 out
= urlCanonical(al
->request
);
881 case LFT_REQUEST_URLPATH_OLD_31
:
882 case LFT_CLIENT_REQ_URLPATH
:
884 out
= al
->request
->urlpath
.termedBuf();
889 case LFT_CLIENT_REQ_VERSION
:
891 snprintf(tmp
, sizeof(tmp
), "%d.%d", (int) al
->request
->http_ver
.major
, (int) al
->request
->http_ver
.minor
);
896 case LFT_REQUEST_METHOD
:
897 out
= al
->_private
.method_str
;
900 case LFT_REQUEST_URI
:
904 case LFT_REQUEST_VERSION_OLD_2X
:
905 case LFT_REQUEST_VERSION
:
906 snprintf(tmp
, sizeof(tmp
), "%d.%d", (int) al
->http
.version
.major
, (int) al
->http
.version
.minor
);
910 case LFT_SERVER_REQ_METHOD
:
911 if (al
->adapted_request
) {
912 out
= al
->adapted_request
->method
.image();
917 case LFT_SERVER_REQ_URI
:
918 // adapted request URI sent to server/peer
919 if (al
->adapted_request
) {
920 out
= urlCanonical(al
->adapted_request
);
925 case LFT_SERVER_REQ_URLPATH
:
926 if (al
->adapted_request
) {
927 out
= al
->adapted_request
->urlpath
.termedBuf();
932 case LFT_SERVER_REQ_VERSION
:
933 if (al
->adapted_request
) {
934 snprintf(tmp
, sizeof(tmp
), "%d.%d",
935 (int) al
->adapted_request
->http_ver
.major
,
936 (int) al
->adapted_request
->http_ver
.minor
);
941 case LFT_REQUEST_SIZE_TOTAL
:
942 outoff
= al
->cache
.requestSize
;
946 /*case LFT_REQUEST_SIZE_LINE: */
947 case LFT_REQUEST_SIZE_HEADERS
:
948 outoff
= al
->cache
.requestHeadersSize
;
951 /*case LFT_REQUEST_SIZE_BODY: */
952 /*case LFT_REQUEST_SIZE_BODY_NO_TE: */
954 case LFT_REPLY_SIZE_TOTAL
:
955 outoff
= al
->cache
.replySize
;
959 case LFT_REPLY_HIGHOFFSET
:
960 outoff
= al
->cache
.highOffset
;
966 case LFT_REPLY_OBJECTSIZE
:
967 outoff
= al
->cache
.objectSize
;
973 /*case LFT_REPLY_SIZE_LINE: */
974 case LFT_REPLY_SIZE_HEADERS
:
975 outint
= al
->cache
.replyHeadersSize
;
978 /*case LFT_REPLY_SIZE_BODY: */
979 /*case LFT_REPLY_SIZE_BODY_NO_TE: */
983 out
= al
->request
->tag
.termedBuf();
989 case LFT_IO_SIZE_TOTAL
:
990 outint
= al
->cache
.requestSize
+ al
->cache
.replySize
;
996 out
= al
->request
->extacl_log
.termedBuf();
1002 case LFT_SEQUENCE_NUMBER
:
1003 outoff
= logSequenceNumber
;
1014 snprintf(tmp
, sizeof(tmp
), "%0*" PRId64
, fmt
->zero
&& fmt
->widthMin
>= 0 ? fmt
->widthMin
: 0, outoff
);
1018 snprintf(tmp
, sizeof(tmp
), "%0*ld", fmt
->zero
&& fmt
->widthMin
>= 0 ? fmt
->widthMin
: 0, outint
);
1023 if (quote
|| fmt
->quote
!= LOG_QUOTE_NONE
) {
1024 char *newout
= NULL
;
1027 switch (fmt
->quote
) {
1029 case LOG_QUOTE_NONE
:
1030 newout
= rfc1738_escape_unescaped(out
);
1033 case LOG_QUOTE_QUOTES
: {
1034 size_t out_len
= static_cast<size_t>(strlen(out
)) * 2 + 1;
1035 if (out_len
>= sizeof(tmp
)) {
1036 newout
= (char *)xmalloc(out_len
);
1040 log_quoted_string(out
, newout
);
1044 case LOG_QUOTE_MIMEBLOB
:
1045 newout
= QuoteMimeBlob(out
);
1050 newout
= rfc1738_escape(out
);
1067 // enforce width limits if configured
1068 const bool haveMaxWidth
= fmt
->widthMax
>=0 && !doint
&& !dooff
;
1069 if (haveMaxWidth
|| fmt
->widthMin
) {
1070 const int minWidth
= fmt
->widthMin
>= 0 ?
1072 const int maxWidth
= haveMaxWidth
?
1073 fmt
->widthMax
: strlen(out
);
1076 mb
.Printf("%-*.*s", minWidth
, maxWidth
, out
);
1078 mb
.Printf("%*.*s", minWidth
, maxWidth
, out
);
1080 mb
.append(out
, strlen(out
));