ErrorDetailManager.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2019 The Squid Software Foundation and contributors
3  *
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.
7  */
8 
9 #include "squid.h"
10 #include "ErrorDetail.h"
11 #include "ErrorDetailManager.h"
12 #include "errorpage.h"
14 #include "mime_header.h"
15 
17 {
19 }
20 
22 {
24 }
25 
26 namespace Ssl
27 {
28 
31 {
32 public:
33  explicit ErrorDetailFile(ErrorDetailsList::Pointer const details): TemplateFile("error-details.txt", ERR_NONE) {
34  theDetails = details;
35  }
36 
37 private:
39  virtual bool parse() override;
40 };
41 }// namespace Ssl
42 
43 /******************/
44 bool
46 {
47  const ErrorDetails::const_iterator it = theList.find(value);
48  if (it != theList.end()) {
49  entry.error_no = it->second.error_no;
50  entry.name = it->second.name;
51  entry.detail = it->second.detail;
52  entry.descr = it->second.descr;
53  return true;
54  }
55  return false;
56 }
57 
58 const char *
60 {
61  const ErrorDetails::const_iterator it = theList.find(value);
62  if (it != theList.end()) {
63  return it->second.descr.termedBuf();
64  }
65 
66  return NULL;
67 }
68 
69 const char *
71 {
72  const ErrorDetails::const_iterator it = theList.find(value);
73  if (it != theList.end()) {
74  return it->second.detail.termedBuf();
75  }
76 
77  return NULL;
78 }
79 
80 Ssl::ErrorDetailsManager *Ssl::ErrorDetailsManager::TheDetailsManager = NULL;
81 
83 {
84  if (!TheDetailsManager)
85  TheDetailsManager = new Ssl::ErrorDetailsManager;
86 
87  assert(TheDetailsManager);
88  return *TheDetailsManager;
89 }
90 
92 {
93  delete TheDetailsManager;
94  TheDetailsManager = NULL;
95 }
96 
98 {
99  theDefaultErrorDetails = new ErrorDetailsList();
100  ErrorDetailFile detailTmpl(theDefaultErrorDetails);
101  detailTmpl.loadDefault();
102 }
103 
105 {
106  Cache::iterator it;
107  it = cache.find(lang);
108  if (it != cache.end()) {
109  debugs(83, 8, HERE << "Found template details in cache for language: " << lang);
110  return it->second;
111  }
112 
113  return NULL;
114 }
115 
117 {
118  const char *lang = errorDetails->errLanguage.termedBuf();
119  assert(lang);
120  if (cache.find(lang) == cache.end())
121  cache[lang] = errorDetails;
122 }
123 
124 bool
126 {
127 #if USE_ERR_LOCALES
128  String hdr;
129  if (request != NULL && request->header.getList(Http::HdrType::ACCEPT_LANGUAGE, &hdr)) {
130  ErrorDetailsList::Pointer errDetails = NULL;
131  //Try to retrieve from cache
132  size_t pos = 0;
133  char lang[256];
134  // Get the first ellement of the Accept-Language header
135  strHdrAcptLangGetItem(hdr, lang, 256, pos);
136  errDetails = getCachedDetails(lang); // search in cache
137 
138  if (!errDetails) { // Else try to load from disk
139  debugs(83, 8, HERE << "Creating new ErrDetailList to read from disk");
140  errDetails = new ErrorDetailsList();
141  ErrorDetailFile detailTmpl(errDetails);
142  if (detailTmpl.loadFor(request.getRaw())) {
143  if (detailTmpl.language()) {
144  debugs(83, 8, HERE << "Found details on disk for language " << detailTmpl.language());
145  errDetails->errLanguage = detailTmpl.language();
146  cacheDetails(errDetails);
147  }
148  }
149  }
150 
151  if (errDetails != NULL && errDetails->getRecord(value, entry))
152  return true;
153  }
154 #endif
155 
156  // else try the default
157  if (theDefaultErrorDetails->getRecord(value, entry)) {
158  debugs(83, 8, HERE << "Found default details record for error: " << GetErrorName(value));
159  return true;
160  }
161 
162  return false;
163 }
164 
165 const char *
167 {
168  return theDefaultErrorDetails->getErrorDescr(value);
169 }
170 
171 const char *
173 {
174  return theDefaultErrorDetails->getErrorDetail(value);
175 }
176 
177 // Use HttpHeaders parser to parse error-details.txt files
179 {
180 public:
182 };
183 
184 //The end of an error detrail entry is a double "\n". The headersEnd
185 // functions can detect it
186 inline size_t detailEntryEnd(const char *s, size_t len) {return headersEnd(s, len);}
187 
188 bool
190 {
191  if (!theDetails)
192  return false;
193 
194  auto buf = template_;
195  buf.append("\n\n"); // ensure detailEntryEnd() finds the last entry
196 
197  while (const auto size = detailEntryEnd(buf.rawContent(), buf.length())) {
198  auto *s = buf.c_str();
199  const auto e = s + size;
200 
201  //ignore spaces, new lines and comment lines (starting with #) at the beggining
202  for (; (*s == '\n' || *s == ' ' || *s == '\t' || *s == '#') && s < e; ++s) {
203  if (*s == '#')
204  while (s<e && *s != '\n')
205  ++s; // skip untill the end of line
206  }
207 
208  if ( s != e) {
209  DetailEntryParser parser;
210  Http::ContentLengthInterpreter interpreter;
211  // no applyStatusCodeRules() -- error templates lack HTTP status code
212  if (!parser.parse(s, e - s, interpreter)) {
213  debugs(83, DBG_IMPORTANT, HERE <<
214  "WARNING! parse error on:" << s);
215  return false;
216  }
217 
218  const String errorName = parser.getByName("name");
219  if (!errorName.size()) {
220  debugs(83, DBG_IMPORTANT, HERE <<
221  "WARNING! invalid or no error detail name on:" << s);
222  return false;
223  }
224 
225  Security::ErrorCode ssl_error = Ssl::GetErrorCode(errorName.termedBuf());
226  if (ssl_error != SSL_ERROR_NONE) {
227 
228  if (theDetails->getErrorDetail(ssl_error)) {
229  debugs(83, DBG_IMPORTANT, HERE <<
230  "WARNING! duplicate entry: " << errorName);
231  return false;
232  }
233 
234  ErrorDetailEntry &entry = theDetails->theList[ssl_error];
235  entry.error_no = ssl_error;
236  entry.name = errorName;
237  String tmp = parser.getByName("detail");
238  const int detailsParseOk = httpHeaderParseQuotedString(tmp.termedBuf(), tmp.size(), &entry.detail);
239  tmp = parser.getByName("descr");
240  const int descrParseOk = httpHeaderParseQuotedString(tmp.termedBuf(), tmp.size(), &entry.descr);
241  // TODO: Validate "descr" and "detail" field values.
242 
243  if (!detailsParseOk || !descrParseOk) {
244  debugs(83, DBG_IMPORTANT, HERE <<
245  "WARNING! missing important field for detail error: " << errorName);
246  return false;
247  }
248 
249  } else if (!Ssl::ErrorIsOptional(errorName.termedBuf())) {
250  debugs(83, DBG_IMPORTANT, HERE <<
251  "WARNING! invalid error detail name: " << errorName);
252  return false;
253  }
254 
255  }// else {only spaces and black lines; just ignore}
256 
257  buf.consume(size);
258  }
259  debugs(83, 9, Raw("unparsed data", buf.rawContent(), buf.length()));
260  return true;
261 }
262 
ErrorDetailsList::Pointer theDetails
#define assert(EX)
Definition: assert.h:17
String detail
for error page D macro expansion; may contain macros
bool getRecord(Security::ErrorCode value, ErrorDetailEntry &entry)
int httpHeaderParseQuotedString(const char *start, const int len, String *val)
const char * GetErrorName(Security::ErrorCode value)
The string representation of the TLS error "value".
Definition: ErrorDetail.cc:393
static void Shutdown()
reset the ErrorDetailsManager instance
String getByName(const SBuf &name) const
Definition: HttpHeader.cc:888
static ErrorDetailsManager & GetInstance()
Instance class.
String getList(Http::HdrType id) const
Definition: HttpHeader.cc:828
struct _request * request(char *urlin)
Definition: tcp-banger2.c:291
Security::ErrorCode GetErrorCode(const char *name)
The Security::ErrorCode code of the error described by "name".
Definition: ErrorDetail.cc:346
void cacheDetails(ErrorDetailsList::Pointer &errorDetails)
cache the given error details list.
bool ErrorIsOptional(const char *name)
Definition: ErrorDetail.cc:406
const char * getDefaultErrorDetail(Security::ErrorCode value)
the default error details for a given error
ErrorDetailFile(ErrorDetailsList::Pointer const details)
bool getErrorDetail(Security::ErrorCode value, const HttpRequest::Pointer &request, ErrorDetailEntry &entry)
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:124
#define DBG_IMPORTANT
Definition: Debug.h:46
int parse(const char *header_start, size_t len, Http::ContentLengthInterpreter &interpreter)
Definition: HttpHeader.cc:370
int ErrorCode
Squid defined error code (<0), an error code returned by X.509 API, or SSL_ERROR_NONE.
Definition: forward.h:91
const char * getErrorDetail(Security::ErrorCode value)
an error details for an error if exist in list.
void loadDefault()
Definition: errorpage.cc:351
size_t detailEntryEnd(const char *s, size_t len)
char const * termedBuf() const
Definition: SquidString.h:91
int unsigned int const char *desc STUB void int len
Definition: stub_fd.cc:20
void const char * buf
Definition: stub_helper.cc:16
std::ostream & HERE(std::ostream &s)
Definition: Debug.h:153
virtual bool parse() override
post-process the loaded template
HttpHeader header
Definition: Message.h:75
void errorDetailClean()
Security::ErrorCode error_no
The SSL error code.
String descr
short error description (for use in debug messages or error pages)
ErrorDetailsList::Pointer getCachedDetails(const char *lang)
Return cached error details list for a given language if exist.
Definition: Xaction.cc:47
void errorDetailInitialize()
const char * getDefaultErrorDescr(Security::ErrorCode value)
the default error description for a given error
C * getRaw() const
Definition: RefCount.h:74
bool strHdrAcptLangGetItem(const String &hdr, char *lang, int langLen, size_t &pos)
Definition: errorpage.cc:460
bool loadFor(const HttpRequest *request)
Definition: errorpage.cc:514
const char * language()
The language used for the template.
Definition: errorpage.h:316
Definition: Debug.h:184
String name
a name for the error
size_t headersEnd(const char *mime, size_t l, bool &containsObsFold)
Definition: mime_header.cc:16
manages error detail templates
size_type size() const
Definition: SquidString.h:72
SBuf template_
raw template contents
Definition: errorpage.h:336
#define NULL
Definition: types.h:166
int size
Definition: ModDevPoll.cc:77
const char * getErrorDescr(Security::ErrorCode value)
an error description for an error if exist in list.

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors