What this does is convert ErrorState object to using the generic
libformat.la parser and macro expansions instead of its own rather
limited custom ones for error pages and deny_info URL creation.
This patch is a [PREVIEW] instead of [PATCH] because of the large
performance issues detailed in NOTES below which I would like to see
fixed before this goes into trunk. Any assistance there would be
welcome. Other than that it appears to be fully working for at least the
default level of build tests and a test page using all the codes appears
to be correct.
Change Summary:
1) register the 1-byte error page macros as libformat codes
2) convert the ErrorState::Convert macro expander to use those codes
instead of char literals
3) extend the libformat to handle several process-wide informational
macros and a human-readabhe RFC1123 time format
4) extend the Format::assemble method to call the adapted
ErrorState::Convert function when it encounters byte codes requiring
ErrorState special handling
5) convert the ErrorState::ConvertText and ErrorState::DenyInfoLocation
methods to use the libformat API to parse and assemble the output page
NOTES:
*a) Several of the error page macros are better served by other
logformat macro expansions. However on some the interaction between
deny_info and ERR_* template usages has required that the
ErrorState::Convert logics be used for now. I am not sure at this poiint
if they should stay in ErrorState long term and be treated like the
Ssl::ErrorDetails macros, or be shifted to libformat.
*b) Doing a whole parse cycle for every error response is very costly.
We are already loading the text page files on every error response. This
adds the un-optimized libformat parser lag on top of that. To avoid this
we really need to add a cache for error page templates and strings, such
that each one is only loaded and parsed once. From that we can more
speedily assemble the expansions final output.
*c) For now AccessLogEntry equired by the libformat API is generated by
ErrorState just before use. Ideally the code creating the ErrorState
should pass it an already filled out ALE object for the transaction.
This way we will get a lot more of the libformat macros filled out.
*d) To manage libformat calling ErrorState::Convert as a method, and
recursive macros saving on AccessLogEntry object creation this adds an
ErrorState* to AccessLogEntry and vice versa. For now creating a
circular referance loop at runtime. The ALE object is "owned" by the
ErrorState so the ErriorState::ale_ is a Pointer, whereas the
AccessLogEntry::errorDetails is a raw-pointer explicitly set/unset only
set when teh AccessLogEntry is in use by ErrorState code, and
unconditionally dropped to avoid circular existence dependencies.
** any assistance making a design to avoid this circular linkage is
welcome.
Amos
=== modified file 'src/AccessLogEntry.h'
--- src/AccessLogEntry.h 2013-03-17 12:19:16 +0000
+++ src/AccessLogEntry.h 2013-04-07 02:39:03 +0000
@@ -48,10 +48,10 @@
#include "ssl/gadgets.h"
#endif
-/* forward decls */
+class ErrorState;
+class CustomLog;
class HttpReply;
class HttpRequest;
-class CustomLog;
class AccessLogEntry: public RefCountable
{
@@ -60,7 +60,7 @@
typedef RefCount<AccessLogEntry> Pointer;
AccessLogEntry() : url(NULL), tcpClient(), reply(NULL), request(NULL),
- adapted_request(NULL) {}
+ adapted_request(NULL), errorDetails(NULL) {}
~AccessLogEntry();
/// Fetch the client IP log string into the given buffer.
@@ -279,6 +279,9 @@
}
icap;
#endif
+
+ /// details of the error page presented to the client (if any)
+ ErrorState *errorDetails;
};
class ACLChecklist;
=== modified file 'src/base/StringArea.h'
--- src/base/StringArea.h 2011-10-05 00:19:46 +0000
+++ src/base/StringArea.h 2013-04-07 02:39:36 +0000
@@ -35,6 +35,7 @@
#if HAVE_CSTRING
#include <cstring>
#endif
+#include <ostream>
/** A char* plus length combination. Useful for temporary storing
* and quickly looking up strings.
@@ -56,6 +57,8 @@
return (theLen < s.theLen || (theLen == s.theLen &&
memcmp(theStart,s.theStart,theLen) < 0)) ;
}
+ void print(std::ostream &os) const { os.write(theStart, theLen); }
+
private:
/// pointed to the externally-managed memory area
const char *theStart;
@@ -63,4 +66,11 @@
size_t theLen;
};
+inline std::ostream &
+operator <<(std::ostream &os, const StringArea &a)
+{
+ a.print(os);
+ return os;
+}
+
#endif /* SQUID_STRINGAREA_H */
=== modified file 'src/errorpage.cc'
--- src/errorpage.cc 2013-03-17 12:19:16 +0000
+++ src/errorpage.cc 2013-04-07 02:39:42 +0000
@@ -31,11 +31,13 @@
*/
#include "squid.h"
#include "cache_cf.h"
+#include "client_side.h"
#include "comm/Connection.h"
#include "comm/Write.h"
#include "disk.h"
#include "err_detail_type.h"
#include "errorpage.h"
+#include "format/Format.h"
#include "ftp.h"
#include "Store.h"
#include "html_quote.h"
@@ -591,7 +593,9 @@
#if USE_SSL
detail(NULL),
#endif
- detailCode(ERR_DETAIL_NONE)
+ detailCode(ERR_DETAIL_NONE),
+ building_deny_info_url(false),
+ allowRecursion(true)
{
memset(&ftp, 0, sizeof(ftp));
@@ -694,6 +698,10 @@
ErrorState::~ErrorState()
{
+ if (ale_ != NULL) {
+ // ensure that the AccessLogEntry object has no reference to us
+ ale_->errorDetails = NULL;
+ }
HTTPMSGUNLOCK(request);
safe_free(redirect_url);
safe_free(url);
@@ -796,7 +804,7 @@
#define CVT_BUF_SZ 512
const char *
-ErrorState::Convert(char token, bool building_deny_info_url, bool
allowRecursion)
+ErrorState::Convert(Format::ByteCode_t token)
{
static MemBuf mb;
const char *p = NULL; /* takes priority over mb if set */
@@ -808,30 +816,7 @@
switch (token) {
- case 'a':
-#if USE_AUTH
- if (request && request->auth_user_request != NULL)
- p = request->auth_user_request->username();
- if (!p)
-#endif
- p = "-";
- break;
-
- case 'b':
- mb.Printf("%d", getMyPort());
- break;
-
- case 'B':
- if (building_deny_info_url) break;
- p = request ? ftpUrlWith2f(request) : "[no URL]";
- break;
-
- case 'c':
- if (building_deny_info_url) break;
- p = errorPageName(type);
- break;
-
- case 'D':
+ case Format::LFT_ERR_PAGE_UD: // '%D'
if (!allowRecursion)
p = "%D"; // if recursion is not allowed, do not convert
#if USE_SSL
@@ -840,7 +825,9 @@
detail->useRequest(request);
const String &errDetail = detail->toString();
if (errDetail.defined()) {
- MemBuf *detail_mb = ConvertText(errDetail.termedBuf(), false);
+ allowRecursion = false;
+ MemBuf *detail_mb = ConvertText(errDetail.termedBuf());
+ allowRecursion = true;
mb.append(detail_mb->content(), detail_mb->contentSize());
delete detail_mb;
do_quote = 0;
@@ -851,18 +838,18 @@
mb.Printf("[No Error Detail]");
break;
- case 'e':
+ case Format::LFT_ERR_PAGE_LE: // '%e'
mb.Printf("%d", xerrno);
break;
- case 'E':
+ case Format::LFT_ERR_PAGE_UE: // '%E'
if (xerrno)
mb.Printf("(%d) %s", xerrno, strerror(xerrno));
else
mb.Printf("[No Error]");
break;
- case 'f':
+ case Format::LFT_ERR_PAGE_LF: // '%f'
if (building_deny_info_url) break;
/* FTP REQUEST LINE */
if (ftp.request)
@@ -871,7 +858,7 @@
p = "nothing";
break;
- case 'F':
+ case Format::LFT_ERR_PAGE_UF: // '%F'
if (building_deny_info_url) break;
/* FTP REPLY LINE */
if (ftp.reply)
@@ -880,7 +867,7 @@
p = "nothing";
break;
- case 'g':
+ case Format::LFT_ERR_PAGE_LG: // '%g'
if (building_deny_info_url) break;
/* FTP SERVER RESPONSE */
if (ftp.listing) {
@@ -891,38 +878,13 @@
}
break;
- case 'h':
- mb.Printf("%s", getMyHostname());
- break;
-
- case 'H':
- if (request) {
- if (request->hier.host[0] != '\0') // if non-empty string.
- p = request->hier.host;
- else
- p = request->GetHost();
- } else if (!building_deny_info_url)
- p = "[unknown host]";
- break;
-
- case 'i':
- mb.Printf("%s", src_addr.NtoA(ntoabuf,MAX_IPSTRLEN));
- break;
-
- case 'I':
- if (request && request->hier.tcpServer != NULL)
- p = request->hier.tcpServer->remote.NtoA(ntoabuf,MAX_IPSTRLEN);
- else if (!building_deny_info_url)
- p = "[unknown]";
- break;
-
- case 'l':
+ case Format::LFT_ERR_PAGE_LL: // '%l'
if (building_deny_info_url) break;
mb.append(error_stylesheet.content(), error_stylesheet.contentSize());
do_quote = 0;
break;
- case 'L':
+ case Format::LFT_ERR_PAGE_UL: // '%L'
if (building_deny_info_url) break;
if (Config.errHtmlText) {
mb.Printf("%s", Config.errHtmlText);
@@ -931,7 +893,7 @@
p = "[not available]";
break;
- case 'm':
+ case Format::LFT_ERR_PAGE_LM: // '%m'
if (building_deny_info_url) break;
#if USE_AUTH
p = auth_user_request->denyMessage("[not available]");
@@ -940,28 +902,13 @@
#endif
break;
- case 'M':
- if (request)
- p = RequestMethodStr(request->method);
- else if (!building_deny_info_url)
- p= "[unknown method]";
- break;
-
- case 'o':
+ case Format::LFT_ERR_PAGE_LO: // '%o'
p = request ? request->extacl_message.termedBuf() :
external_acl_message;
if (!p && !building_deny_info_url)
p = "[not available]";
break;
- case 'p':
- if (request) {
- mb.Printf("%d", (int) request->port);
- } else if (!building_deny_info_url) {
- p = "[unknown port]";
- }
- break;
-
- case 'P':
+ case Format::LFT_ERR_PAGE_UP: // '%P'
if (request) {
p = AnyP::ProtocolType_str[request->protocol];
} else if (!building_deny_info_url) {
@@ -969,7 +916,7 @@
}
break;
- case 'R':
+ case Format::LFT_ERR_PAGE_UR: // '%R'
if (building_deny_info_url) {
p = (request->urlpath.size() != 0 ? request->urlpath.termedBuf() :
"/");
no_urlescape = 1;
@@ -999,7 +946,7 @@
}
break;
- case 's':
+ case Format::LFT_ERR_PAGE_LS: // '%s'
/* for backward compat we make %s show the full URL. Drop this in some
future release. */
if (building_deny_info_url) {
p = request ? urlCanonical(request) : url;
@@ -1008,7 +955,7 @@
p = visible_appname_string;
break;
- case 'S':
+ case Format::LFT_ERR_PAGE_US: // '%S'
if (building_deny_info_url) {
p = visible_appname_string;
break;
@@ -1029,49 +976,14 @@
}
break;
- case 't':
- mb.Printf("%s", Time::FormatHttpd(squid_curtime));
- break;
-
- case 'T':
- mb.Printf("%s", mkrfc1123(squid_curtime));
- break;
-
- case 'U':
- /* Using the fake-https version of canonical so error pages see
https:// */
- /* even when the url-path cannot be shown as more than '*' */
- if (request)
- p = urlCanonicalFakeHttps(request);
- else if (url)
- p = url;
- else if (!building_deny_info_url)
- p = "[no URL]";
- break;
-
- case 'u':
- if (request)
- p = urlCanonical(request);
- else if (url)
- p = url;
- else if (!building_deny_info_url)
- p = "[no URL]";
- break;
-
- case 'w':
- if (Config.adminEmail)
- mb.Printf("%s", Config.adminEmail);
- else if (!building_deny_info_url)
- p = "[unknown]";
- break;
-
- case 'W':
+ case Format::LFT_ERR_PAGE_UW: // '%W'
if (building_deny_info_url) break;
if (Config.adminEmail && Config.onoff.emailErrData)
Dump(&mb);
no_urlescape = 1;
break;
- case 'x':
+ case Format::LFT_ERR_PAGE_LX: // '%x'
#if USE_SSL
if (detail)
mb.Printf("%s", detail->errorName());
@@ -1081,7 +993,7 @@
p = "[Unknown Error Code]";
break;
- case 'z':
+ case Format::LFT_ERR_PAGE_LZ: // '%z'
if (building_deny_info_url) break;
if (dnsError.size() > 0)
p = dnsError.termedBuf();
@@ -1091,7 +1003,7 @@
p = "[unknown]";
break;
- case 'Z':
+ case Format::LFT_ERR_PAGE_UZ: // '%Z'
if (building_deny_info_url) break;
if (err_msg)
p = err_msg;
@@ -1099,13 +1011,7 @@
p = "[unknown]";
break;
- case '%':
- p = "%";
- break;
-
default:
- mb.Printf("%%%c", token);
- do_quote = 0;
break;
}
@@ -1128,24 +1034,27 @@
void
ErrorState::DenyInfoLocation(const char *name, HttpRequest *aRequest, MemBuf
&result)
{
+ building_deny_info_url = true;
+
+ // XXX: make this process much faster by pre-parsing the deny_info pattern
+ // and just assembling the Location: output here.
+
char const *m = name;
- char const *p = m;
- char const *t;
if (m[0] == '3')
m += 4; // skip "3xx:"
- while ((p = strchr(m, '%'))) {
- result.append(m, p - m); /* copy */
- t = Convert(*++p, true, true); /* convert */
- result.Printf("%s", t); /* copy */
- m = p + 1; /* advance */
- }
-
- if (*m)
- result.Printf("%s", m); /* copy tail */
-
- assert((size_t)result.contentSize() == strlen(result.content()));
+ MemBuf *res = ConvertText(m);
+
+ // yuck! steal the res buffer for our output
+ result.buf = res->buf;
+ result.size = res->size;
+ result.capacity = res->capacity;
+ result.max_capacity = res->max_capacity;
+ res->stolen = true; // prevent delete erasing the buffer we stole.
+ delete res;
+
+ building_deny_info_url = false;
}
HttpReply *
@@ -1278,7 +1187,7 @@
debugs(4, 2, HERE << "No existing error page language negotiated for "
<< errorPageName(page_id) << ". Using default error file.");
}
- MemBuf *result = ConvertText(m, true);
+ MemBuf *result = ConvertText(m);
#if USE_ERR_LOCALES
if (localeTmpl)
delete localeTmpl;
@@ -1286,25 +1195,46 @@
return result;
}
-MemBuf *ErrorState::ConvertText(const char *text, bool allowRecursion)
+MemBuf *
+ErrorState::ConvertText(const char *text)
{
+ // parse the text using Format:: parser
+ Format::Format fmt("errorPageTemporary");
+ fmt.parse(text);
+
+ // XXX: if request exists, we might use ALE from
request->lientConnectionManager->http.al ??
+
+ // if we are in a recursive pattern (%D or %S) ALE may already be setup
+ // or if the creator of this ErrorState was kind enough to supply the real
transaction ALE object
+ if (ale_ == NULL) {
+ ale_ = new AccessLogEntry();
+
+ // fill ale_ with all the details Format::assemble() will need to
process error page codes.
+
+ assert(request);
+
+ if (request->auth_user_request != NULL)
+ ale_->cache.authuser = request->auth_user_request->username();
+ // XXX: we only know about one request here.
+ ale_->request = request;
+ HTTPMSGLOCK(request);
+ ale_->adapted_request = request;
+ HTTPMSGLOCK(request);
+ ale_->_private.method_str = RequestMethodStr(request->method);
+ const char *hierHost = (request->hier.host[0] != '\0' ?
request->hier.host : request->GetHost());
+ ale_->hier.note(request->hier.tcpServer, hierHost);
+
+ if (request->clientConnectionManager.valid())
+ ale_->tcpClient =
request->clientConnectionManager->clientConnection;
+
+ ale_->url = (request ? urlCanonicalFakeHttps(request) : url);
+ }
+ ale_->errorDetails = this;
+
+ // build the actual object text
MemBuf *content = new MemBuf;
- const char *p;
- const char *m = text;
- assert(m);
content->init();
-
- while ((p = strchr(m, '%'))) {
- content->append(m, p - m); /* copy */
- const char *t = Convert(*++p, false, allowRecursion); /* convert */
- content->Printf("%s", t); /* copy */
- m = p + 1; /* advance */
- }
-
- if (*m)
- content->Printf("%s", m); /* copy tail */
-
- assert((size_t)content->contentSize() == strlen(content->content()));
+ fmt.assemble(*content, ale_, 0);
return content;
}
=== modified file 'src/errorpage.h'
--- src/errorpage.h 2013-03-16 04:57:43 +0000
+++ src/errorpage.h 2013-04-07 02:39:42 +0000
@@ -34,10 +34,12 @@
#ifndef SQUID_ERRORPAGE_H
#define SQUID_ERRORPAGE_H
+#include "AccessLogEntry.h"
#include "cbdata.h"
#include "comm/forward.h"
#include "err_detail_type.h"
#include "err_type.h"
+#include "format/ByteCode.h"
#include "http/StatusCode.h"
#include "ip/Address.h"
#include "SquidString.h"
@@ -109,6 +111,17 @@
/// set error type-specific detail code
void detailError(int dCode) {detailCode = dCode;}
+ /** \deprecated
+ * Map some Error page and deny_info template % codes into textual output.
+ * Only the LFT_ERR_PAGE_* ones are mapped, others are ignored.
+ *
+ * Several of the codes produce blocks of non-URL compatible results.
+ * When processing the deny_info location URL they will be skipped.
+ *
+ * \param token The token following % which need to be
converted
+ */
+ const char *Convert(Format::ByteCode_t token);
+
private:
/**
* Locates error page template to be used for this error
@@ -120,9 +133,8 @@
* Convert the given template string into textual output
*
* \param text The string to be converted
- * \param allowRecursion Whether to convert codes which output may
contain codes
*/
- MemBuf *ConvertText(const char *text, bool allowRecursion);
+ MemBuf *ConvertText(const char *text);
/**
* Generates the Location: header value for a deny_info error page
@@ -131,18 +143,6 @@
void DenyInfoLocation(const char *name, HttpRequest *request, MemBuf
&result);
/**
- * Map the Error page and deny_info template % codes into textual output.
- *
- * Several of the codes produce blocks of non-URL compatible results.
- * When processing the deny_info location URL they will be skipped.
- *
- * \param token The token following % which need to be
converted
- * \param building_deny_info_url Perform special deny_info actions, such
as URL-encoding and token skipping.
- * \ allowRecursion True if the codes which do recursions should
converted
- */
- const char *Convert(char token, bool building_deny_info_url, bool
allowRecursion);
-
- /**
* CacheManager / Debug dump of the ErrorState object.
* Writes output into the given MemBuf.
\retval 0 successful completion.
@@ -164,7 +164,7 @@
String dnsError; ///< DNS lookup error message
time_t ttl;
- Ip::Address src_addr;
+ Ip::Address src_addr; // client Comm::Connection ??
char *redirect_url;
ERCB *callback;
void *callback_data;
@@ -186,7 +186,17 @@
/// type-specific detail about the transaction error;
/// overwrites xerrno; overwritten by detail, if any.
int detailCode;
+
private:
+ /// Perform special deny_info actions, such as URL-encoding and token
skipping.
+ bool building_deny_info_url;
+
+ /// Whether to convert codes which output may contain codes
+ bool allowRecursion;
+
+ /// an AccessLogEntry we are using to generate output
+ AccessLogEntry::Pointer ale_;
+
CBDATA_CLASS2(ErrorState);
};
=== modified file 'src/format/ByteCode.h'
--- src/format/ByteCode.h 2013-02-11 23:11:12 +0000
+++ src/format/ByteCode.h 2013-04-07 02:39:45 +0000
@@ -136,6 +136,7 @@
LFT_TIME_SUBSECOND,
LFT_TIME_LOCALTIME,
LFT_TIME_GMT,
+ LFT_TIME_GMT_RFC1123,
/* processing time details */
LFT_TIME_TO_HANDLE_REQUEST,
@@ -143,6 +144,12 @@
LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME,
LFT_DNS_WAIT_TIME,
+ /* Squid application details */
+ LFT_SQUID_KID_HOSTNAME,
+ LFT_SQUID_KID_PORT,
+ LFT_SQUID_KID_APPSTRING,
+ LFT_SQUID_KID_ADMINEMAIL,
+
/* Squid internal processing details */
LFT_SQUID_STATUS,
LFT_SQUID_ERROR,
@@ -196,6 +203,26 @@
LFT_SSL_USER_CERT_ISSUER,
#endif
+ /* Squid Error Page special items U=Upper, L=lower cased alphabet codes */
+ LFT_ERR_PAGE_UD,
+ LFT_ERR_PAGE_LE,
+ LFT_ERR_PAGE_UE,
+ LFT_ERR_PAGE_LF,
+ LFT_ERR_PAGE_UF,
+ LFT_ERR_PAGE_LG,
+ LFT_ERR_PAGE_LL,
+ LFT_ERR_PAGE_UL,
+ LFT_ERR_PAGE_LM,
+ LFT_ERR_PAGE_LO,
+ LFT_ERR_PAGE_UP,
+ LFT_ERR_PAGE_UR,
+ LFT_ERR_PAGE_LS,
+ LFT_ERR_PAGE_US,
+ LFT_ERR_PAGE_UW,
+ LFT_ERR_PAGE_LX,
+ LFT_ERR_PAGE_LZ,
+ LFT_ERR_PAGE_UZ,
+
LFT_NOTE,
LFT_PERCENT /* special string cases for escaped
chars */
} ByteCode_t;
=== modified file 'src/format/Format.cc'
--- src/format/Format.cc 2013-03-16 04:57:43 +0000
+++ src/format/Format.cc 2013-04-07 02:39:45 +0000
@@ -9,11 +9,14 @@
#include "format/Quoting.h"
#include "format/Token.h"
#include "fqdncache.h"
+#include "globals.h"
#include "HttpRequest.h"
#include "MemBuf.h"
#include "rfc1738.h"
+#include "SquidConfig.h"
#include "SquidTime.h"
#include "Store.h"
+#include "tools.h"
#include "URL.h"
#if USE_SSL
#include "ssl/ErrorDetail.h"
@@ -442,7 +445,7 @@
break;
case LFT_TIME_LOCALTIME:
-
+ case LFT_TIME_GMT_RFC1123:
case LFT_TIME_GMT: {
const char *spec;
@@ -453,6 +456,12 @@
if (!spec)
spec = "%d/%b/%Y:%H:%M:%S %z";
t = localtime(&squid_curtime);
+
+ } else if (fmt->type == LFT_TIME_GMT_RFC1123) {
+ if (!spec)
+ spec = "%a, %d %b %Y %H:%M:%S GMT";
+ t = gmtime(&squid_curtime);
+
} else {
if (!spec)
spec = "%d/%b/%Y:%H:%M:%S";
@@ -819,6 +828,23 @@
// or internal error messages).
break;
+ case LFT_SQUID_KID_HOSTNAME:
+ out = getMyHostname();
+ break;
+
+ case LFT_SQUID_KID_PORT:
+ outint = getMyPort();
+ doint = 1;
+ break;
+
+ case LFT_SQUID_KID_APPSTRING:
+ out = visible_appname_string;
+ break;
+
+ case LFT_SQUID_KID_ADMINEMAIL:
+ out = Config.adminEmail;
+ break;
+
case LFT_SQUID_STATUS:
if (al->http.timedout || al->http.aborted) {
snprintf(tmp, sizeof(tmp), "%s%s", LogTags_str[al->cache.code],
@@ -860,6 +886,31 @@
}
break;
+ case LFT_ERR_PAGE_UD:
+ case LFT_ERR_PAGE_LE:
+ case LFT_ERR_PAGE_UE:
+ case LFT_ERR_PAGE_LF:
+ case LFT_ERR_PAGE_UF:
+ case LFT_ERR_PAGE_LG:
+ case LFT_ERR_PAGE_LL:
+ case LFT_ERR_PAGE_UL:
+ case LFT_ERR_PAGE_LM:
+ case LFT_ERR_PAGE_LO:
+ case LFT_ERR_PAGE_UP:
+ case LFT_ERR_PAGE_UR:
+ case LFT_ERR_PAGE_LS:
+ case LFT_ERR_PAGE_US:
+ case LFT_ERR_PAGE_UW:
+ case LFT_ERR_PAGE_LX:
+ case LFT_ERR_PAGE_LZ:
+ case LFT_ERR_PAGE_UZ:
+ // NP: these code types are used only by the ErrorState page
generator
+ // for backward compatibility use the old code to generate the
display output
+ if (al->errorDetails) {
+ out = al->errorDetails->Convert(fmt->type);
+ }
+ break;
+
case LFT_SQUID_HIERARCHY:
if (al->hier.ping.timedout)
mb.append("TIMEOUT_", 8);
=== modified file 'src/format/Token.cc'
--- src/format/Token.cc 2013-02-11 23:11:12 +0000
+++ src/format/Token.cc 2013-04-07 02:39:46 +0000
@@ -1,4 +1,5 @@
#include "squid.h"
+#include "base/StringArea.h"
#include "format/Config.h"
#include "format/Token.h"
#include "format/TokenTableEntry.h"
@@ -31,6 +32,46 @@
{"%", LFT_PERCENT},
+ // 1-byte Tokens used by the Error page templates
+
+ // these ones map easily ..
+ {"a", LFT_USER_LOGIN},
+ {"b", LFT_SQUID_KID_PORT},
+ {"B", LFT_SERVER_REQ_URI},
+ {"c", LFT_SQUID_ERROR},
+ /*{"d", LFT_TIME_TO_HANDLE_REQUEST},*/
+ {"h", LFT_SQUID_KID_HOSTNAME},
+ {"H", LFT_SERVER_FQDN_OR_PEER_NAME},
+ {"i", LFT_CLIENT_IP_ADDRESS},
+ {"I", LFT_SERVER_IP_ADDRESS},
+ {"M", LFT_REQUEST_METHOD},
+ {"p", LFT_SERVER_PORT},
+ {"t", LFT_TIME_LOCALTIME},
+ {"T", LFT_TIME_GMT_RFC1123},
+ {"u", LFT_CLIENT_REQ_URI},
+ {"U", LFT_REQUEST_URI},
+ {"w", LFT_SQUID_KID_ADMINEMAIL},
+
+ // NP: this bunch are specific to the ErrorState object generator
+ {"D", LFT_ERR_PAGE_UD},
+ {"e", LFT_ERR_PAGE_LE},
+ {"E", LFT_ERR_PAGE_UE},
+ {"f", LFT_ERR_PAGE_LF},
+ {"F", LFT_ERR_PAGE_UF},
+ {"g", LFT_ERR_PAGE_LG},
+ {"l", LFT_ERR_PAGE_LL},
+ {"L", LFT_ERR_PAGE_UL},
+ {"m", LFT_ERR_PAGE_LM},
+ {"o", LFT_ERR_PAGE_LO},
+ {"P", LFT_ERR_PAGE_UP},
+ {"R", LFT_ERR_PAGE_UR},
+ {"s", LFT_ERR_PAGE_LS},
+ {"S", LFT_ERR_PAGE_US},
+ {"W", LFT_ERR_PAGE_UW},
+ {"x", LFT_ERR_PAGE_LX},
+ {"z", LFT_ERR_PAGE_LZ},
+ {"Z", LFT_ERR_PAGE_UZ},
+
{NULL, LFT_NONE} /* this must be last */
};
@@ -373,7 +414,12 @@
}
if (type == LFT_NONE) {
- fatalf("Can't parse configuration token: '%s'\n", def);
+ debugs(46, 3, "Can't parse configuration token: '" <<
StringArea(def,min(strlen(def), static_cast<size_t>(10))) << "'");
+ // NP: unknown token found. Assume it should have been %% instead of %.
+ if (def[0] == '%') {
+ type = LFT_PERCENT;
+ ++cur;
+ }
}
if (*cur == ' ') {