/*
- * Copyright (C) 1996-2018 The Squid Software Foundation and contributors
+ * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
*
* Squid software is distributed under GPLv2+ license and includes
* contributions from numerous individuals and organizations.
#include "cbdata.h"
#include "comm/forward.h"
-#include "err_detail_type.h"
-#include "err_type.h"
+#include "error/Detail.h"
+#include "error/forward.h"
#include "http/forward.h"
#include "http/StatusCode.h"
#include "ip/Address.h"
+#include "log/forward.h"
+#include "sbuf/SBuf.h"
#include "SquidString.h"
/* auth/UserRequest.h is empty unless USE_AUTH is defined */
#include "auth/UserRequest.h"
-#if USE_OPENSSL
-#include "ssl/ErrorDetail.h"
-#endif
/// error page callback
typedef void ERCB(int fd, void *, size_t);
z - dns server error message x
Z - Preformatted error message x
\endverbatim
+ *
+ * Plus logformat %codes embedded using @Squid{%logformat_code} syntax.
*/
class MemBuf;
class StoreEntry;
class wordlist;
+namespace ErrorPage {
+
+class Build;
+
+} // namespace ErrorPage
+
/// \ingroup ErrorPageAPI
class ErrorState
{
CBDATA_CLASS(ErrorState);
public:
- ErrorState(err_type type, Http::StatusCode, HttpRequest * request);
+ /// creates an error of type other than ERR_RELAY_REMOTE
+ ErrorState(err_type type, Http::StatusCode, HttpRequest * request, const AccessLogEntryPointer &al);
ErrorState() = delete; // not implemented.
+
+ /// creates an ERR_RELAY_REMOTE error
+ ErrorState(HttpRequest * request, HttpReply *);
+
~ErrorState();
/// Creates a general request forwarding error with the right http_status.
- static ErrorState *NewForwarding(err_type, HttpRequestPointer &);
+ static ErrorState *NewForwarding(err_type, HttpRequestPointer &, const AccessLogEntryPointer &);
/**
* Allocates and initializes an error response
HttpReply *BuildHttpReply(void);
/// set error type-specific detail code
- void detailError(int dCode) {detailCode = dCode;}
+ void detailError(const ErrorDetail::Pointer &dCode) { detail = dCode; }
-private:
- /**
- * Locates error page template to be used for this error
- * and constructs the HTML page content from it.
- */
- MemBuf *BuildContent(void);
+ /// ensures that a future BuildHttpReply() is likely to succeed
+ void validate();
- /**
- * 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);
-
- /**
- * Generates the Location: header value for a deny_info error page
- * to be used for this error.
- */
- void DenyInfoLocation(const char *name, HttpRequest *request, MemBuf &result);
+ /// the source of the error template (for reporting purposes)
+ SBuf inputLocation;
- /**
- * 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);
+private:
+ typedef ErrorPage::Build Build;
+
+ /// initializations shared by public constructors
+ explicit ErrorState(err_type type);
+
+ /// locates the right error page template for this error and compiles it
+ SBuf buildBody();
+
+ /// compiles error page or error detail template (i.e. anything but deny_url)
+ /// \param input the template text to be compiled
+ /// \param allowRecursion whether to compile %codes which produce %codes
+ SBuf compileBody(const char *text, bool allowRecursion);
+
+ /// compile a single-letter %code like %D
+ void compileLegacyCode(Build &build);
+
+ /// compile @Squid{%code} sequence containing a single logformat %code
+ void compileLogformatCode(Build &build);
+
+ /// replaces all legacy and logformat %codes in the given input
+ /// \param input the template text to be converted
+ /// \param building_deny_info_url whether input is a deny_info URL parameter
+ /// \param allowRecursion whether to compile %codes which produce %codes
+ /// \returns the given input with all %codes substituted
+ SBuf compile(const char *input, bool building_deny_info_url, bool allowRecursion);
+
+ /// React to a compile() error, throwing if buildContext allows.
+ /// \param msg description of what went wrong
+ /// \param near approximate start of the problematic input
+ void noteBuildError(const char *msg, const char *near) {
+ noteBuildError_(msg, near, false);
+ }
+
+ /// Note a compile() error but do not throw for backwards
+ /// compatibility with older configurations that may have such errors.
+ /// Should eventually be replaced with noteBuildError().
+ /// \param msg description of what went wrong
+ /// \param near approximate start of the problematic input
+ void bypassBuildErrorXXX(const char *msg, const char *near) {
+ noteBuildError_(msg, near, true);
+ }
/**
* CacheManager / Debug dump of the ErrorState object.
err_type type = ERR_NONE;
int page_id = ERR_NONE;
char *err_language = nullptr;
- Http::StatusCode httpStatus;
+ Http::StatusCode httpStatus = Http::scNone;
#if USE_AUTH
Auth::UserRequest::Pointer auth_user_request;
#endif
char *request_hdrs = nullptr;
char *err_msg = nullptr; /* Preformatted error message from the cache */
-#if USE_OPENSSL
- Ssl::ErrorDetail *detail = nullptr;
-#endif
+ AccessLogEntryPointer ale; ///< transaction details (or nil)
+
+ // TODO: Replace type, xerrno and detail with Error while adding a virtual
+ // Error::Detail::sysError() method to extract errno in detailError().
/// type-specific detail about the transaction error;
- /// overwrites xerrno; overwritten by detail, if any.
- int detailCode = ERR_DETAIL_NONE;
+ /// overwrites xerrno;
+ ErrorDetail::Pointer detail;
+
+ HttpReplyPointer response_;
+
+private:
+ void noteBuildError_(const char *msg, const char *near, const bool forceBypass);
+
+ static const SBuf LogformatMagic; ///< marks each embedded logformat entry
};
/**
*/
void errorAppendEntry(StoreEntry *entry, ErrorState *err);
-/// \ingroup ErrorPageAPI
-err_type errorReservePageId(const char *page_name);
+/// allocates a new slot for the error page
+err_type errorReservePageId(const char *page_name, const SBuf &cfgLocation);
const char *errorPageName(int pageId); ///< error ID to string
* (a) admin specified custom directory (error_directory)
* (b) default language translation directory (error_default_language)
* (c) English sub-directory where errors should ALWAYS exist
+ * If all of the above fail, setDefault() is called.
*/
- bool loadDefault();
+ void loadDefault();
/**
* Load an error template for a given HTTP request. This function examines the
/// The language used for the template
const char *language() {return errLanguage.termedBuf();}
+ SBuf filename; ///< where the template was loaded from
+
bool silent; ///< Whether to print error messages on cache.log file or not. It is user defined.
protected:
- /// Used to parse (if parsing required) the template data .
- virtual bool parse(const char *buf, int len, bool eof) = 0;
+ /// post-process the loaded template
+ virtual bool parse() { return true; }
+
+ /// recover from loadDefault() failure to load or parse() a template
+ virtual void setDefault() {}
/**
* Try to load the "page_name" template for a given language "lang"
*/
bool tryLoadTemplate(const char *lang);
+ SBuf template_; ///< raw template contents
bool wasLoaded; ///< True if the template data read from disk without any problem
String errLanguage; ///< The error language of the template.
String templateName; ///< The name of the template
*/
bool strHdrAcptLangGetItem(const String &hdr, char *lang, int langLen, size_t &pos);
+std::ostream &operator <<(std::ostream &, const ErrorState *);
+
#endif /* SQUID_ERRORPAGE_H */