]> git.ipfire.org Git - thirdparty/squid.git/blame - src/errorpage.h
Source Format Enforcement (#532)
[thirdparty/squid.git] / src / errorpage.h
CommitLineData
aa839030 1/*
77b1029d 2 * Copyright (C) 1996-2020 The Squid Software Foundation and contributors
aa839030 3 *
bbc27441
AJ
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
aa839030 7 */
8
bbc27441
AJ
9/* DEBUG: section 04 Error Generation */
10
aa839030 11#ifndef SQUID_ERRORPAGE_H
12#define SQUID_ERRORPAGE_H
13
aa839030 14#include "cbdata.h"
e0d28505 15#include "comm/forward.h"
129fe2a1 16#include "err_detail_type.h"
582c2af2 17#include "err_type.h"
fc94fd66 18#include "http/forward.h"
955394ce 19#include "http/StatusCode.h"
96d89ea0 20#include "ip/Address.h"
7e6eabbc
CT
21#include "log/forward.h"
22#include "sbuf/SBuf.h"
582c2af2 23#include "SquidString.h"
fafe8849 24/* auth/UserRequest.h is empty unless USE_AUTH is defined */
582c2af2 25#include "auth/UserRequest.h"
cb4f4424 26#if USE_OPENSSL
4d16918e
CT
27#include "ssl/ErrorDetail.h"
28#endif
aa839030 29
822c0041
FC
30/// error page callback
31typedef void ERCB(int fd, void *, size_t);
32
63be0a78 33/**
34 \defgroup ErrorPageAPI Error Pages API
35 \ingroup Components
36 \section ErrorPageStringCodes Error Page % codes for text insertion.
37 *
38 \verbatim
39 a - User identity x
ea35939b 40 A - Local listening IP address x
63be0a78 41 B - URL with FTP %2f hack x
42 c - Squid error code x
43 d - seconds elapsed since request received x
4d16918e 44 D - Error details x
63be0a78 45 e - errno x
46 E - strerror() x
47 f - FTP request line x
48 F - FTP reply line x
49 g - FTP server message x
50 h - cache hostname x
51 H - server host name x
52 i - client IP address x
53 I - server IP address x
8e1a6bde 54 l - HREF link for CSS stylesheet inclusion x
63be0a78 55 L - HREF link for more info/contact x
56 M - Request Method x
57 m - Error message returned by auth helper x
58 o - Message returned external acl helper x
59 p - URL port # x
60 P - Protocol x
61 R - Full HTTP Request x
62 S - squid signature from ERR_SIGNATURE x
63 s - caching proxy software with version x
64 t - local time x
65 T - UTC x
66 U - URL without password x
67 u - URL with password x
68 w - cachemgr email address x
69 W - error data (to be included in the mailto links)
e4a8468d 70 x - error name x
63be0a78 71 z - dns server error message x
72 Z - Preformatted error message x
73 \endverbatim
7e6eabbc
CT
74 *
75 * Plus logformat %codes embedded using @Squid{%logformat_code} syntax.
63be0a78 76 */
77
c70281f8 78class MemBuf;
28d505bc 79class StoreEntry;
5fb9646e 80class wordlist;
9554bbf2 81
7e6eabbc
CT
82namespace ErrorPage {
83
84class Build;
85
86} // namespace ErrorPage
87
63be0a78 88/// \ingroup ErrorPageAPI
aa839030 89class ErrorState
90{
5c2f68b7
AJ
91 CBDATA_CLASS(ErrorState);
92
c70281f8 93public:
f5e17947 94 /// creates an error of type other than ERR_RELAY_REMOTE
7e6eabbc 95 ErrorState(err_type type, Http::StatusCode, HttpRequest * request, const AccessLogEntryPointer &al);
fc94fd66 96 ErrorState() = delete; // not implemented.
f5e17947
CT
97
98 /// creates an ERR_RELAY_REMOTE error
99 ErrorState(HttpRequest * request, HttpReply *);
100
913524f0
AJ
101 ~ErrorState();
102
a23223bf 103 /// Creates a general request forwarding error with the right http_status.
7e6eabbc 104 static ErrorState *NewForwarding(err_type, HttpRequestPointer &, const AccessLogEntryPointer &);
a23223bf 105
c70281f8
AJ
106 /**
107 * Allocates and initializes an error response
108 */
109 HttpReply *BuildHttpReply(void);
110
7a957a93 111 /// set error type-specific detail code
38450a50 112 void detailError(int dCode) {detailCode = dCode;}
129fe2a1 113
7e6eabbc
CT
114 /// ensures that a future BuildHttpReply() is likely to succeed
115 void validate();
c70281f8 116
7e6eabbc
CT
117 /// the source of the error template (for reporting purposes)
118 SBuf inputLocation;
15b02e9a 119
7e6eabbc
CT
120private:
121 typedef ErrorPage::Build Build;
122
f5e17947
CT
123 /// initializations shared by public constructors
124 explicit ErrorState(err_type type);
125
7e6eabbc
CT
126 /// locates the right error page template for this error and compiles it
127 SBuf buildBody();
128
129 /// compiles error page or error detail template (i.e. anything but deny_url)
130 /// \param input the template text to be compiled
131 /// \param allowRecursion whether to compile %codes which produce %codes
132 SBuf compileBody(const char *text, bool allowRecursion);
133
134 /// compile a single-letter %code like %D
135 void compileLegacyCode(Build &build);
136
137 /// compile @Squid{%code} sequence containing a single logformat %code
138 void compileLogformatCode(Build &build);
139
140 /// replaces all legacy and logformat %codes in the given input
141 /// \param input the template text to be converted
142 /// \param building_deny_info_url whether input is a deny_info URL parameter
143 /// \param allowRecursion whether to compile %codes which produce %codes
144 /// \returns the given input with all %codes substituted
145 SBuf compile(const char *input, bool building_deny_info_url, bool allowRecursion);
146
147 /// React to a compile() error, throwing if buildContext allows.
148 /// \param msg description of what went wrong
149 /// \param near approximate start of the problematic input
150 void noteBuildError(const char *msg, const char *near) {
151 noteBuildError_(msg, near, false);
152 }
153
154 /// Note a compile() error but do not throw for backwards
155 /// compatibility with older configurations that may have such errors.
156 /// Should eventually be replaced with noteBuildError().
157 /// \param msg description of what went wrong
158 /// \param near approximate start of the problematic input
159 void bypassBuildErrorXXX(const char *msg, const char *near) {
160 noteBuildError_(msg, near, true);
161 }
c70281f8
AJ
162
163 /**
164 * CacheManager / Debug dump of the ErrorState object.
165 * Writes output into the given MemBuf.
166 \retval 0 successful completion.
167 */
168 int Dump(MemBuf * mb);
2cc81f1f 169
170public:
fc94fd66
AJ
171 err_type type = ERR_NONE;
172 int page_id = ERR_NONE;
173 char *err_language = nullptr;
a75bf5d9 174 Http::StatusCode httpStatus = Http::scNone;
2f1431ea 175#if USE_AUTH
c7baff40 176 Auth::UserRequest::Pointer auth_user_request;
2f1431ea 177#endif
4c7c97f3 178 HttpRequestPointer request;
fc94fd66
AJ
179 char *url = nullptr;
180 int xerrno = 0;
181 unsigned short port = 0;
3ff65596 182 String dnsError; ///< DNS lookup error message
fc94fd66 183 time_t ttl = 0;
aa839030 184
b7ac5457 185 Ip::Address src_addr;
fc94fd66 186 char *redirect_url = nullptr;
aa839030 187 ERCB *callback;
fc94fd66 188 void *callback_data = nullptr;
aa839030 189
26ac0430 190 struct {
fc94fd66
AJ
191 wordlist *server_msg = nullptr;
192 char *request = nullptr;
193 char *reply = nullptr;
194 char *cwd_msg = nullptr;
195 MemBuf *listing = nullptr;
3d0ac046 196 } ftp;
aa839030 197
fc94fd66
AJ
198 char *request_hdrs = nullptr;
199 char *err_msg = nullptr; /* Preformatted error message from the cache */
2cc81f1f 200
7e6eabbc
CT
201 AccessLogEntryPointer ale; ///< transaction details (or nil)
202
cb4f4424 203#if USE_OPENSSL
fc94fd66 204 Ssl::ErrorDetail *detail = nullptr;
4d16918e 205#endif
129fe2a1
CT
206 /// type-specific detail about the transaction error;
207 /// overwrites xerrno; overwritten by detail, if any.
fc94fd66 208 int detailCode = ERR_DETAIL_NONE;
7e6eabbc 209
f5e17947
CT
210 HttpReplyPointer response_;
211
7e6eabbc
CT
212private:
213 void noteBuildError_(const char *msg, const char *near, const bool forceBypass);
214
215 static const SBuf LogformatMagic; ///< marks each embedded logformat entry
aa839030 216};
217
63be0a78 218/**
219 \ingroup ErrorPageAPI
220 *
221 * This function finds the error messages formats, and stores
222 * them in error_text[]
223 *
224 \par Global effects:
225 * error_text[] - is modified
226 */
d9c252f2 227void errorInitialize(void);
63be0a78 228
229/// \ingroup ErrorPageAPI
d9c252f2 230void errorClean(void);
63be0a78 231
63be0a78 232/**
27774cee 233 * \ingroup ErrorPageAPI
63be0a78 234 *
235 * This function generates a error page from the info contained
236 * by err and then sends it to the client.
237 * The callback function errorSendComplete() is called after
e0d28505 238 * the page has been written to the client (clientConn).
63be0a78 239 * errorSendComplete() deallocates err. We need to add
240 * err to the cbdata because comm_write() requires it
241 * for all callback data pointers.
242 *
243 \note normally errorSend() should only be called from
244 * routines in ssl.c and pass.c, where we don't have any
245 * StoreEntry's. In client_side.c we must allocate a StoreEntry
246 * for errors and use errorAppendEntry() to account for
247 * persistent/pipeline connections.
248 *
1b76e6c1
AJ
249 \param clientConn socket where page object is to be written
250 \param err This object is destroyed after use in this function.
63be0a78 251 */
d9c252f2 252void errorSend(const Comm::ConnectionPointer &conn, ErrorState *err);
63be0a78 253
254/**
255 \ingroup ErrorPageAPI
256 *
257 * This function generates a error page from the info contained
258 * by err and then stores the text in the specified store
259 * entry.
260 * This function should only be called by "server
261 * side routines" which need to communicate errors to the
262 * client side. It should also be called from client_side.c
263 * because we now support persistent connections, and
264 * cannot assume that we can immediately write to the socket
265 * for an error.
266 *
267 \param entry ??
268 \param err This object is destroyed after use in this function.
269 */
d9c252f2 270void errorAppendEntry(StoreEntry *entry, ErrorState *err);
63be0a78 271
7e6eabbc
CT
272/// allocates a new slot for the error page
273err_type errorReservePageId(const char *page_name, const SBuf &cfgLocation);
aa839030 274
d9c252f2 275const char *errorPageName(int pageId); ///< error ID to string
aa839030 276
02259ff8
CT
277/**
278 \ingroup ErrorPageAPI
279 *
280 * loads text templates used for error pages and details;
281 * supports translation of templates
282 */
dc49061a
A
283class TemplateFile
284{
02259ff8 285public:
8ff2520a 286 TemplateFile(const char *name, const err_type code);
dc49061a 287 virtual ~TemplateFile() {}
02259ff8
CT
288
289 /// return true if the data loaded from disk without any problem
290 bool loaded() const {return wasLoaded;}
291
292 /**
293 * Load the page_name template from a file which probably exist at:
294 * (a) admin specified custom directory (error_directory)
295 * (b) default language translation directory (error_default_language)
296 * (c) English sub-directory where errors should ALWAYS exist
7e6eabbc 297 * If all of the above fail, setDefault() is called.
02259ff8 298 */
7e6eabbc 299 void loadDefault();
02259ff8
CT
300
301 /**
302 * Load an error template for a given HTTP request. This function examines the
303 * Accept-Language header and select the first available template. If the default
304 * template selected (eg because of a "Accept-Language: *"), or not available
305 * template found this function return false.
306 */
b248c2a3 307 bool loadFor(const HttpRequest *request);
02259ff8
CT
308
309 /**
310 * Load the file given by "path". It uses the "parse()" method.
311 * On success return true and sets the "defined" member
312 */
313 bool loadFromFile(const char *path);
314
315 /// The language used for the template
316 const char *language() {return errLanguage.termedBuf();}
317
7e6eabbc
CT
318 SBuf filename; ///< where the template was loaded from
319
02259ff8
CT
320 bool silent; ///< Whether to print error messages on cache.log file or not. It is user defined.
321
322protected:
7e6eabbc
CT
323 /// post-process the loaded template
324 virtual bool parse() { return true; }
325
326 /// recover from loadDefault() failure to load or parse() a template
327 virtual void setDefault() {}
02259ff8
CT
328
329 /**
330 * Try to load the "page_name" template for a given language "lang"
331 * from squid errors directory
332 \return true on success false otherwise
333 */
334 bool tryLoadTemplate(const char *lang);
335
7e6eabbc 336 SBuf template_; ///< raw template contents
02259ff8
CT
337 bool wasLoaded; ///< True if the template data read from disk without any problem
338 String errLanguage; ///< The error language of the template.
339 String templateName; ///< The name of the template
8ff2520a 340 err_type templateCode; ///< The internal code for this template.
02259ff8
CT
341};
342
343/**
344 * Parses the Accept-Language header value and return one language item on
345 * each call.
a32e7644
AJ
346 * Will ignore any whitespace, q-values, and detectably invalid language
347 * codes in the header.
348 *
02259ff8 349 * \param hdr is the Accept-Language header value
a32e7644 350 * \param lang a buffer to store parsed language code in
02259ff8 351 * \param langlen the length of the lang buffer
a32e7644
AJ
352 * \param pos is used to store the offset state of parsing. Must be "0" on first call.
353 * Will be altered to point at the start of next field-value.
354 * \return true if something looking like a language token has been placed in lang, false otherwise
02259ff8
CT
355 */
356bool strHdrAcptLangGetItem(const String &hdr, char *lang, int langLen, size_t &pos);
a32e7644 357
aa839030 358#endif /* SQUID_ERRORPAGE_H */
f53969cc 359