57#if !defined(DEFAULT_SQUID_ERROR_DIR)
61#define DEFAULT_SQUID_ERROR_DIR DEFAULT_SQUID_DATA_DIR"/errors"
127 std::ostream &
print(std::ostream &)
const;
139static inline std::ostream &
142 return context.
print(os);
168 "<div id=\"footer\">\n"
169 "Generated %T by %h (%s)\n"
179 "unexpected client disconnect"
187 "request start timedout"
191 "request parse timedout"
195 "relay server response"
225 const char *
text() {
return template_.c_str(); }
229 template_ =
"Internal Error: Missing Template ";
238 int tmp = (
int)anErr;
247 return (
int)anErr - (
int)anErr2;
277 static const SBuf builtIn(
"built-in");
278 ImportStaticErrorText(i,
text, builtIn);
288 ImportStaticErrorText(i, errTmpl.
text(), errTmpl.
filename);
300 ImportStaticErrorText(i, errTmpl.
text(), errTmpl.
filename);
405 snprintf(path,
sizeof(path),
"%s/%s/%s",
413 if ( strlen(lang) == 2) {
416 debugs(4,2,
"wildcard fallback errors not coded yet.");
447 template_.append(buf, len);
474 while (pos < hdr.
size()) {
487 bool invalid_byte =
false;
489 while (pos < hdr.
size() && hdr[pos] !=
';' && hdr[pos] !=
',' && !
xisspace(hdr[pos]) && dt < (lang + (langLen -1)) ) {
491#if USE_HTTP_VIOLATIONS
500 if (*dt !=
'-' && *dt !=
'*' && (*dt <
'a' || *dt >
'z') )
510 while (pos < hdr.
size() && hdr[pos] !=
',')
513 if (pos < hdr.
size() && hdr[pos] ==
',')
516 debugs(4, 9,
"STATE: lang=" << lang <<
", pos=" << pos <<
", buf='" << ((pos < hdr.
size()) ? hdr.
substr(pos,hdr.
size()) :
"") <<
"'");
519 if (*lang !=
'\0' && !invalid_byte)
540 debugs(4, 6,
"Testing Header: '" << hdr <<
"'");
545 if (lang[0] ==
'*' && lang[1] ==
'\0') {
546 debugs(4, 6,
"Found language '" << lang <<
"'. Using configured default.");
550 debugs(4, 6,
"Found language '" << lang <<
"', testing for available template");
572 cfgLocation(aCfgLocation),
573 page_redirect(static_cast<
Http::StatusCode>(atoi(page_name)))
575 const char *filenameOrUri =
nullptr;
577 if (
const char *statusCodeEnd = strchr(
page_name,
':'))
578 filenameOrUri = statusCodeEnd + 1;
584 const auto looksLikeUrl = [](
const char *
const name) {
return name && strchr(name,
':'); };
589 if (looksLikeUrl(filenameOrUri))
602 const auto info =
this;
618 else if (info->page_redirect < 200 || info->page_redirect > 599) {
622 }
else if ( info->page_redirect < 300 && looksLikeUrl(filenameOrUri)) {
626 }
else if (info->page_redirect >= 300 && info->page_redirect <= 399 && !looksLikeUrl(filenameOrUri)) {
630 }
else if (info->page_redirect >= 400 && looksLikeUrl(filenameOrUri)) {
642 for (
int i = 0; i <
ERR_MAX; ++i) {
679 return "ERR_UNKNOWN";
721 debugs(4, 3,
"constructed, this=" <<
static_cast<void*
>(
this) <<
' ' << *
this);
736 debugs(4, 3,
"constructed, this=" <<
static_cast<void*
>(
this) <<
" relaying " << *
this);
744 debugs(4, 4,
"storing " << err <<
" in " << *entry);
746 if (
const auto &request = err->
request) {
747 if (
const auto &bodyPipe = request->body_pipe) {
765 bodyPipe->enableAutoConsumption();
784 debugs(4, 2,
"RSTing this reply");
796 debugs(4, 3, conn <<
", err=" << err);
825 debugs(4, 3,
"errorSendComplete: callback");
828 debugs(4, 3,
"errorSendComplete: comm_close");
838 debugs(4, 7,
"destructing, this=" <<
static_cast<void*
>(
this));
859 out <<
"?subject=" <<
869 body <<
"ClientIP: " <<
src_addr <<
"\r\n";
883 body <<
"DNS ErrMsg: " << *
dnsError <<
"\r\n";
888 body <<
"HTTP Request:\r\n";
898 body <<
"FTP Request: " <<
ftp.request <<
"\r\n";
900 body <<
"FTP Reply: " <<
ftp.reply <<
"\r\n";
912#define CVT_BUF_SZ 512
927 if (*logformat !=
'%')
928 throw TexcHere(
"logformat expressions that do not start with % are not supported");
934 const auto closure = logformat + logformatLen;
936 throw TexcHere(
"Missing closing brace (})");
938 build.
input = closure + 1;
945 const auto remainingSize = strlen(build.
input);
947 build.
input += remainingSize;
954 const char *p =
nullptr;
956 int no_urlescape = 0;
964 const auto letter = build.
input[1];
990 if (building_deny_info_url)
break;
999 if (building_deny_info_url)
break;
1009 const auto compiledDetail =
compileBody(rawDetail.c_str(),
false);
1010 mb.
append(compiledDetail.rawContent(), compiledDetail.length());
1014 mb.
append(
"[No Error Detail]", 17);
1025 mb.
append(
"[No Error]", 10);
1029 if (building_deny_info_url)
break;
1038 if (building_deny_info_url)
break;
1047 if (building_deny_info_url)
break;
1050 mb.
append(
ftp.listing->content(),
ftp.listing->contentSize());
1052 }
else if (
ftp.server_msg) {
1067 }
else if (!building_deny_info_url)
1068 p =
"[unknown host]";
1078 else if (!building_deny_info_url)
1083 if (building_deny_info_url)
break;
1089 if (building_deny_info_url)
break;
1094 p =
"[not available]";
1098 if (building_deny_info_url)
break;
1103 p =
"[not available]";
1113 }
else if (!building_deny_info_url)
1114 p =
"[unknown method]";
1118 if (!building_deny_info_url)
1123 if (!p && !building_deny_info_url)
1124 p =
"[not available]";
1130 }
else if (!building_deny_info_url) {
1131 p =
"[unknown port]";
1139 }
else if (!building_deny_info_url) {
1140 p =
"[unknown protocol]";
1145 if (building_deny_info_url) {
1162 if (building_deny_info_url) {
1168 debugs(0,
DBG_CRITICAL,
"WARNING: deny_info now accepts coded tags. Use %u to get the full URL instead of %s");
1174 if (building_deny_info_url) {
1183 mb.
append(signature.rawContent(), signature.length());
1207 else if (!building_deny_info_url)
1217 else if (!building_deny_info_url)
1224 else if (!building_deny_info_url)
1229 if (building_deny_info_url)
break;
1239 mb.
append(brief.rawContent(), brief.length());
1240 }
else if (!building_deny_info_url) {
1241 p =
"[Unknown Error Code]";
1246 if (building_deny_info_url)
break;
1249 else if (
ftp.cwd_msg)
1256 if (building_deny_info_url)
break;
1270 if (building_deny_info_url)
1279 if (building_deny_info_url)
1281 else if (letter !=
';')
1297 debugs(4, 3,
"%" << (letter ? letter :
'?') <<
" --> '" << p <<
"'" );
1302 if (building_deny_info_url && !no_urlescape)
1316 (void)
compile(urlTemplate,
true,
true);
1357 rep->
setHeaders(status,
nullptr,
"text/html;charset=utf-8", 0, 0, -1);
1360 auto location =
compile(urlTemplate,
true,
true);
1387 static const SBuf acceptLanguage(
"Accept-Language");
1441 debugs(4, 2,
"No existing error page language negotiated for " <<
this <<
". Using default error file.");
1448 return compile(input,
false, allowRecursion);
1459 build.
input = input;
1461 auto blockStart = build.
input;
1462 while (
const auto letter = *build.
input) {
1463 if (letter ==
'%') {
1466 blockStart = build.
input;
1471 blockStart = build.
input;
1492 if (runtime || forceBypass) {
1496 static unsigned int seenErrors = 0;
1499 const auto debugLevel =
1507 debugs(4, debugLevel,
"WARNING: The following configuration error will be fatal in future Squid versions");
1523 return os <<
"[error page " <<
page_id <<
"]";
1533 printLocation(os) <<
": " << msg <<
" near ";
1536 const size_t maxContextLength = 15;
1537 if (strlen(errorLocation) > maxContextLength) {
1538 os.write(errorLocation, maxContextLength);
1541 os << errorLocation;
1547 if (std::current_exception())
#define Assure(condition)
CommCbFunPtrCallT< Dialer > * commCbCall(int debugSection, int debugLevel, const char *callName, const Dialer &dialer)
void IOCB(const Comm::ConnectionPointer &conn, char *, size_t size, Comm::Flag flag, int xerrno, void *data)
const char * err_type_str[]
const Ip::Address * FindListeningPortAddress(const HttpRequest *callerRequest, const AccessLogEntry *ale)
RawPointerT< Pointer > RawPointer(const char *label, const Pointer &ptr)
convenience wrapper for creating RawPointerT<> objects
std::ostream & CurrentException(std::ostream &os)
prints active (i.e., thrown but not yet handled) exception
#define TexcHere(msg)
legacy convenience macro; it is not difficult to type Here() now
const char * urlCanonicalFakeHttps(const HttpRequest *request)
#define CBDATA_CLASS_INIT(type)
void updateError(const Error &)
sets (or updates the already stored) transaction error as needed
AnyP::UriScheme const & getScheme() const
SBuf & absolutePath() const
RFC 3986 section 4.2 relative reference called 'absolute-path'.
void port(const Port p)
reset authority port subcomponent
void host(const char *src)
static SBuf Encode(const SBuf &, const CharacterSet &expected)
std::ostream manipulator to print containers as flat lists
auto & delimitedBy(const char *const d)
a c-string to print between consecutive items (if any). Caller must ensure lifetime.
char const * denyMessage(char const *const default_message=nullptr) const
char const * username() const
static const CharacterSet & RFC3986_UNRESERVED()
allowed URI characters that do not have a reserved purpose, RFC 3986
virtual SBuf verbose(const HttpRequestPointer &) const =0
virtual SBuf brief() const =0
an error page created from admin-configurable metadata (e.g. deny_info)
const char * uri
admin-configured HTTP Location header value for redirection responses
ErrorDynamicPageInfo(ErrorDynamicPageInfo &&)=delete
Http::StatusCode page_redirect
admin-configured HTTP status code
SBuf cfgLocation
deny_info directive position in squid.conf (for reporting)
ErrorDynamicPageInfo(const int anId, const char *aName, const SBuf &aCfgLocation)
int id
error_text[] index for response body (unused in redirection responses)
const char * filename
admin-configured name for the error page template (custom or standard)
void setDefault() override
recover from loadDefault() failure to load or parse() a template
const char * text()
The template text data read from disk.
ErrorPageFile(const char *name, const err_type code)
pretty-prints error page/deny_info building error
std::ostream & printLocation(std::ostream &os) const
print() helper to report where the error was found
std::ostream & print(std::ostream &) const
reports error details (for admin-visible exceptions and debugging)
BuildErrorPrinter(const SBuf &anInputLocation, int aPage, const char *aMsg, const char *anErrorLocation)
const SBuf & inputLocation
const char * errorLocation
state and parameters shared by several ErrorState::compile*() methods
bool allowRecursion
whether top-level compile() calls are OK
bool building_deny_info_url
whether we compile deny_info URI
const char * input
template bytes that need to be compiled
SBuf output
compilation result
static ErrorState * NewForwarding(err_type, HttpRequestPointer &, const AccessLogEntryPointer &)
Creates a general request forwarding error with the right http_status.
SBuf compile(const char *input, bool building_deny_info_url, bool allowRecursion)
void validate()
ensures that a future BuildHttpReply() is likely to succeed
void compileLegacyCode(Build &build)
compile a single-letter code like D
void noteBuildError_(const char *msg, const char *errorLocation, bool forceBypass)
AccessLogEntryPointer ale
transaction details (or nil)
std::optional< SBuf > dnsError
DNS lookup error message.
void bypassBuildErrorXXX(const char *const msg, const char *const errorLocation)
ErrorDetail::Pointer detail
void compileLogformatCode(Build &build)
compile @Squid{code} sequence containing a single logformat code
Auth::UserRequest::Pointer auth_user_request
SBuf inputLocation
the source of the error template (for reporting purposes)
static const SBuf LogformatMagic
marks each embedded logformat entry
HttpRequestPointer request
SBuf compileBody(const char *text, bool allowRecursion)
HttpReply * BuildHttpReply(void)
struct ErrorState::@47 ftp
SBuf buildBody()
locates the right error page template for this error and compiles it
HttpReplyPointer response_
Http::StatusCode httpStatus
void noteBuildError(const char *const msg, const char *const errorLocation)
void update(const Error &)
if necessary, stores the given error information (if any)
an error page (or a part of an error page) with hard-coded template text
const char * text
a string literal containing the error template
err_type type
identifies the error (or a special error template part)
char host[SQUIDHOSTNAMELEN]
Comm::ConnectionPointer tcpServer
TCP/IP level details of the last peer/server connection.
void set(const SBuf &newContent)
void setHeaders(Http::StatusCode status, const char *reason, const char *ctype, int64_t clen, time_t lmt, time_t expires)
const SBuf & image() const
void pack(Packable *p, bool maskSensitiveInfo=false) const
Auth::UserRequest::Pointer auth_user_request
Error error
the first transaction problem encountered (or falsy)
AnyP::Uri url
the request URI
const SBuf & effectiveRequestUri() const
RFC 7230 section 5.5 - Effective Request URI.
AnyP::ProtocolVersion http_ver
Http::StatusCode status() const
retrieve the status code for this status line
char * toStr(char *buf, const unsigned int blen, int force=AF_UNSPEC) const
void append(const char *c, int sz) override
void init(mb_size_t szInit, mb_size_t szMax)
char * content()
start of the added data
mb_size_t contentSize() const
available data size
void appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Append operation with printf-style arguments.
SBuf buf()
bytes written so far
const char * rawContent() const
char at(size_type pos) const
size_type length() const
Returns the number of bytes stored in SBuf.
int cmp(const SBuf &S, const size_type n) const
shorthand version for compare()
SBuf & append(const SBuf &S)
int errorLogMissingLanguages
char * errorDefaultLanguage
struct SquidConfig::@90 onoff
void storeErrorResponse(HttpReply *reply)
Store a prepared error response. MemObject locks the reply object.
store_status_t store_status
String substr(size_type from, size_type to) const
char const * termedBuf() const
static ErrorDetail::Pointer NewIfAny(const int errorNo)
virtual void setDefault()
recover from loadDefault() failure to load or parse() a template
bool loadFromFile(const char *path)
SBuf template_
raw template contents
SBuf filename
where the template was loaded from
bool loaded() const
return true if the data loaded from disk without any problem
TemplateFile(const char *name, const err_type code)
bool wasLoaded
True if the template data read from disk without any problem.
bool tryLoadTemplate(const char *lang)
String templateName
The name of the template.
const char * language()
The language used for the template.
virtual bool parse()
post-process the loaded template
err_type templateCode
The internal code for this template.
String errLanguage
The error language of the template.
bool silent
Whether to print error messages on cache.log file or not. It is user defined.
bool loadFor(const HttpRequest *request)
#define debugs(SECTION, LEVEL, CONTENT)
#define EBIT_TEST(flag, bit)
@ ERR_REQUEST_PARSE_TIMEOUT
@ ERR_REQUEST_START_TIMEOUT
static const std::array< HardCodedError, 7 > HardCodedErrors
error messages that cannot be configured/customized externally
static std::ostream & operator<<(std::ostream &os, const ErrorState &err)
compactly prints top-level ErrorState information (for debugging)
err_type errorReservePageId(const char *page_name, const SBuf &cfgLocation)
allocates a new slot for the error page
static IOCB errorSendComplete
#define DEFAULT_SQUID_ERROR_DIR
bool strHdrAcptLangGetItem(const String &hdr, char *lang, int langLen, size_t &pos)
bool strHdrAcptLangGetItem(const String &hdr, char *lang, int langLen, size_t &pos)
int FD_READ_METHOD(int fd, char *buf, int len)
int file_open(const char *path, int mode)
char const * visible_appname_string
const char * external_acl_message
void errorInitialize(void)
void errorSend(const Comm::ConnectionPointer &conn, ErrorState *err)
void errorAppendEntry(StoreEntry *entry, ErrorState *err)
const char * errorPageName(int pageId)
error ID to string
static char ** error_text
static const char * errorFindHardText(err_type type)
static std::vector< ErrorDynamicPageInfo * > ErrorDynamicPages
static err_type & operator++(err_type &anErr)
static int operator-(err_type const &anErr, err_type const &anErr2)
static int errorPageId(const char *page_name)
static int error_page_count
static MemBuf error_stylesheet
char * html_quote(const char *string)
#define MAX_IPSTRLEN
Length of buffer that needs to be allocated to old a null-terminated IP-string.
bool IsConnOpen(const Comm::ConnectionPointer &conn)
void Write(const Comm::ConnectionPointer &conn, const char *buf, int size, AsyncCall::Pointer &callback, FREE *free_func)
static const char * IsDenyInfoUri(const int page_id)
static void ImportStaticErrorText(const int page_id, const char *text, const SBuf &inputLocation)
add error page template to the global index
static void ValidateStaticError(const int page_id, const SBuf &inputLocation)
validate static error page
static std::ostream & operator<<(std::ostream &os, const BuildErrorPrinter &context)
const SBuf & UrlWith2f(HttpRequest *)
AnyP::ProtocolVersion ProtocolVersion()
void errorDetailInitialize()
const char * FormatRfc1123(time_t)
const char * FormatHttpd(time_t)
#define rfc1738_escape_part(x)
SBuf ToSBuf(Args &&... args)
slowly stream-prints all arguments into a freshly allocated SBuf
SBuf text("GET http://resource.com/path HTTP/1.1\r\n" "Host: resource.com\r\n" "Cookie: laijkpk3422r j1noin \r\n" "\r\n")
void wordlistDestroy(wordlist **list)
destroy a wordlist
void wordlistCat(const wordlist *w, MemBuf *mb)
void * xcalloc(size_t n, size_t sz)
const char * xstrerr(int error)