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;
587 if (filenameOrUri && strchr(filenameOrUri,
':'))
600 const auto info =
this;
616 else if (info->page_redirect < 200 || info->page_redirect > 599) {
620 }
else if ( info->page_redirect < 300 && strchr(&(
page_name[4]),
':')) {
624 }
else if (info->page_redirect >= 300 && info->page_redirect <= 399 && !strchr(&(
page_name[4]),
':')) {
628 }
else if (info->page_redirect >= 400 && strchr(&(
page_name[4]),
':')) {
640 for (
int i = 0; i <
ERR_MAX; ++i) {
677 return "ERR_UNKNOWN";
719 debugs(4, 3,
"constructed, this=" <<
static_cast<void*
>(
this) <<
' ' << *
this);
734 debugs(4, 3,
"constructed, this=" <<
static_cast<void*
>(
this) <<
" relaying " << *
this);
742 debugs(4, 4,
"storing " << err <<
" in " << *entry);
744 if (
const auto &request = err->
request) {
745 if (
const auto &bodyPipe = request->body_pipe) {
763 bodyPipe->enableAutoConsumption();
782 debugs(4, 2,
"RSTing this reply");
794 debugs(4, 3, conn <<
", err=" << err);
823 debugs(4, 3,
"errorSendComplete: callback");
826 debugs(4, 3,
"errorSendComplete: comm_close");
836 debugs(4, 7,
"destructing, this=" <<
static_cast<void*
>(
this));
857 out <<
"?subject=" <<
867 body <<
"ClientIP: " <<
src_addr <<
"\r\n";
881 body <<
"DNS ErrMsg: " << *
dnsError <<
"\r\n";
886 body <<
"HTTP Request:\r\n";
896 body <<
"FTP Request: " <<
ftp.request <<
"\r\n";
898 body <<
"FTP Reply: " <<
ftp.reply <<
"\r\n";
910#define CVT_BUF_SZ 512
925 if (*logformat !=
'%')
926 throw TexcHere(
"logformat expressions that do not start with % are not supported");
932 const auto closure = logformat + logformatLen;
934 throw TexcHere(
"Missing closing brace (})");
936 build.
input = closure + 1;
943 const auto remainingSize = strlen(build.
input);
945 build.
input += remainingSize;
952 const char *p =
nullptr;
954 int no_urlescape = 0;
961 const auto letter = build.
input[1];
987 if (building_deny_info_url)
break;
996 if (building_deny_info_url)
break;
1006 const auto compiledDetail =
compileBody(rawDetail.c_str(),
false);
1007 mb.
append(compiledDetail.rawContent(), compiledDetail.length());
1011 mb.
append(
"[No Error Detail]", 17);
1022 mb.
append(
"[No Error]", 10);
1026 if (building_deny_info_url)
break;
1035 if (building_deny_info_url)
break;
1044 if (building_deny_info_url)
break;
1047 mb.
append(
ftp.listing->content(),
ftp.listing->contentSize());
1049 }
else if (
ftp.server_msg) {
1064 }
else if (!building_deny_info_url)
1065 p =
"[unknown host]";
1075 else if (!building_deny_info_url)
1080 if (building_deny_info_url)
break;
1086 if (building_deny_info_url)
break;
1091 p =
"[not available]";
1095 if (building_deny_info_url)
break;
1100 p =
"[not available]";
1110 }
else if (!building_deny_info_url)
1111 p =
"[unknown method]";
1115 if (!building_deny_info_url)
1120 if (!p && !building_deny_info_url)
1121 p =
"[not available]";
1127 }
else if (!building_deny_info_url) {
1128 p =
"[unknown port]";
1136 }
else if (!building_deny_info_url) {
1137 p =
"[unknown protocol]";
1142 if (building_deny_info_url) {
1159 if (building_deny_info_url) {
1165 debugs(0,
DBG_CRITICAL,
"WARNING: deny_info now accepts coded tags. Use %u to get the full URL instead of %s");
1171 if (building_deny_info_url) {
1180 mb.
append(signature.rawContent(), signature.length());
1204 else if (!building_deny_info_url)
1214 else if (!building_deny_info_url)
1221 else if (!building_deny_info_url)
1226 if (building_deny_info_url)
break;
1236 mb.
append(brief.rawContent(), brief.length());
1237 }
else if (!building_deny_info_url) {
1238 p =
"[Unknown Error Code]";
1243 if (building_deny_info_url)
break;
1246 else if (
ftp.cwd_msg)
1253 if (building_deny_info_url)
break;
1265 if (building_deny_info_url)
1267 else if (letter !=
';')
1281 debugs(4, 3,
"%" << letter <<
" --> '" << p <<
"'" );
1286 if (building_deny_info_url && !no_urlescape)
1298 (void)
compile(urlTemplate,
true,
true);
1339 rep->
setHeaders(status,
nullptr,
"text/html;charset=utf-8", 0, 0, -1);
1342 auto location =
compile(urlTemplate,
true,
true);
1369 static const SBuf acceptLanguage(
"Accept-Language");
1423 debugs(4, 2,
"No existing error page language negotiated for " <<
this <<
". Using default error file.");
1430 return compile(input,
false, allowRecursion);
1441 build.
input = input;
1443 auto blockStart = build.
input;
1444 while (
const auto letter = *build.
input) {
1445 if (letter ==
'%') {
1448 blockStart = build.
input;
1453 blockStart = build.
input;
1474 if (runtime || forceBypass) {
1478 static unsigned int seenErrors = 0;
1481 const auto debugLevel =
1489 debugs(4, debugLevel,
"WARNING: The following configuration error will be fatal in future Squid versions");
1505 return os <<
"[error page " <<
page_id <<
"]";
1515 printLocation(os) <<
": " << msg <<
" near ";
1518 const size_t maxContextLength = 15;
1519 if (strlen(errorLocation) > maxContextLength) {
1520 os.write(errorLocation, maxContextLength);
1523 os << errorLocation;
1529 if (std::current_exception())
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)