]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/errorpage.h
Source Format Enforcement (#763)
[thirdparty/squid.git] / src / errorpage.h
index ff3e6548ca10460aa301cc94500e3d95d9f7b87c..3218000cdcb229794a51bcf38cf0b1ed72a9a4e3 100644 (file)
@@ -1,51 +1,31 @@
 /*
- * DEBUG: section 04    Error Generation
- * AUTHOR: Duane Wessels
+ * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
  *
- * SQUID Web Proxy Cache          http://www.squid-cache.org/
- * ----------------------------------------------------------
- *
- *  Squid is the result of efforts by numerous individuals from
- *  the Internet community; see the CONTRIBUTORS file for full
- *  details.   Many organizations have provided support for Squid's
- *  development; see the SPONSORS file for full details.  Squid is
- *  Copyrighted (C) 2001 by the Regents of the University of
- *  California; see the COPYRIGHT file for full details.  Squid
- *  incorporates software developed and/or copyrighted by other
- *  sources; see the CREDITS file for full details.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
- *
- * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
+/* DEBUG: section 04    Error Generation */
+
 #ifndef   SQUID_ERRORPAGE_H
 #define   SQUID_ERRORPAGE_H
 
 #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);
 
 /**
  \defgroup ErrorPageAPI Error Pages API
@@ -54,6 +34,7 @@
  *
  \verbatim
    a - User identity                            x
+   A - Local listening IP address               x
    B - URL with FTP %2f hack                    x
    c - Squid error code                         x
    d - seconds elapsed since request received   x
    z - dns server error message                 x
    Z - Preformatted error message               x
  \endverbatim
+ *
+ * Plus logformat %codes embedded using @Squid{%logformat_code} syntax.
  */
 
-class HttpReply;
-class HttpRequest;
 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);
-    ErrorState(); // not implemented.
+    /// 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 type, HttpRequest *request);
+    static ErrorState *NewForwarding(err_type, HttpRequestPointer &, const AccessLogEntryPointer &);
 
     /**
      * Allocates and initializes an error response
@@ -110,40 +106,56 @@ public:
     HttpReply *BuildHttpReply(void);
 
     /// set error type-specific detail code
-    void detailError(int dCode) {detailCode = dCode;}
-
-private:
-    /**
-     * Locates error page template to be used for this error
-     * and constructs the HTML page content from it.
-     */
-    MemBuf *BuildContent(void);
+    void detailError(const ErrorDetail::Pointer &dCode) { detail = dCode; }
 
-    /**
-     * 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);
+    /// ensures that a future BuildHttpReply() is likely to succeed
+    void validate();
 
-    /**
-     * 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.
@@ -153,44 +165,50 @@ private:
     int Dump(MemBuf * mb);
 
 public:
-    err_type type;
-    int page_id;
-    char *err_language;
-    Http::StatusCode httpStatus;
+    err_type type = ERR_NONE;
+    int page_id = ERR_NONE;
+    char *err_language = nullptr;
+    Http::StatusCode httpStatus = Http::scNone;
 #if USE_AUTH
     Auth::UserRequest::Pointer auth_user_request;
 #endif
-    HttpRequest *request;
-    char *url;
-    int xerrno;
-    unsigned short port;
+    HttpRequestPointer request;
+    char *url = nullptr;
+    int xerrno = 0;
+    unsigned short port = 0;
     String dnsError; ///< DNS lookup error message
-    time_t ttl;
+    time_t ttl = 0;
 
     Ip::Address src_addr;
-    char *redirect_url;
+    char *redirect_url = nullptr;
     ERCB *callback;
-    void *callback_data;
+    void *callback_data = nullptr;
 
     struct {
-        wordlist *server_msg;
-        char *request;
-        char *reply;
-        char *cwd_msg;
-        MemBuf *listing;
+        wordlist *server_msg = nullptr;
+        char *request = nullptr;
+        char *reply = nullptr;
+        char *cwd_msg = nullptr;
+        MemBuf *listing = nullptr;
     } ftp;
 
-    char *request_hdrs;
-    char *err_msg; /* Preformatted error message from the cache */
+    char *request_hdrs = nullptr;
+    char *err_msg = nullptr; /* Preformatted error message from the cache */
 
-#if USE_OPENSSL
-    Ssl::ErrorDetail *detail;
-#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;
+    /// overwrites xerrno;
+    ErrorDetail::Pointer detail;
+
+    HttpReplyPointer response_;
+
 private:
-    CBDATA_CLASS2(ErrorState);
+    void noteBuildError_(const char *msg, const char *near, const bool forceBypass);
+
+    static const SBuf LogformatMagic; ///< marks each embedded logformat entry
 };
 
 /**
@@ -247,8 +265,8 @@ void errorSend(const Comm::ConnectionPointer &conn, ErrorState *err);
  */
 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
 
@@ -272,8 +290,9 @@ public:
      *  (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
@@ -292,11 +311,16 @@ public:
     /// 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"
@@ -305,6 +329,7 @@ protected:
      */
     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
@@ -326,4 +351,7 @@ protected:
  */
 bool strHdrAcptLangGetItem(const String &hdr, char *lang, int langLen, size_t &pos);
 
+std::ostream &operator <<(std::ostream &, const ErrorState *);
+
 #endif /* SQUID_ERRORPAGE_H */
+