ErrorDetailManager.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2018 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  buf.init();
35  theDetails = details;
36  }
37 
38 private:
41  virtual bool parse(const char *buf, int len, bool eof);
42 };
43 }// namespace Ssl
44 
45 /******************/
46 bool
48 {
49  const ErrorDetails::const_iterator it = theList.find(value);
50  if (it != theList.end()) {
51  entry.error_no = it->second.error_no;
52  entry.name = it->second.name;
53  entry.detail = it->second.detail;
54  entry.descr = it->second.descr;
55  return true;
56  }
57  return false;
58 }
59 
60 const char *
62 {
63  const ErrorDetails::const_iterator it = theList.find(value);
64  if (it != theList.end()) {
65  return it->second.descr.termedBuf();
66  }
67 
68  return NULL;
69 }
70 
71 const char *
73 {
74  const ErrorDetails::const_iterator it = theList.find(value);
75  if (it != theList.end()) {
76  return it->second.detail.termedBuf();
77  }
78 
79  return NULL;
80 }
81 
82 Ssl::ErrorDetailsManager *Ssl::ErrorDetailsManager::TheDetailsManager = NULL;
83 
85 {
86  if (!TheDetailsManager)
87  TheDetailsManager = new Ssl::ErrorDetailsManager;
88 
89  assert(TheDetailsManager);
90  return *TheDetailsManager;
91 }
92 
94 {
95  delete TheDetailsManager;
96  TheDetailsManager = NULL;
97 }
98 
100 {
101  theDefaultErrorDetails = new ErrorDetailsList();
102  ErrorDetailFile detailTmpl(theDefaultErrorDetails);
103  detailTmpl.loadDefault();
104 }
105 
107 {
108  Cache::iterator it;
109  it = cache.find(lang);
110  if (it != cache.end()) {
111  debugs(83, 8, HERE << "Found template details in cache for language: " << lang);
112  return it->second;
113  }
114 
115  return NULL;
116 }
117 
119 {
120  const char *lang = errorDetails->errLanguage.termedBuf();
121  assert(lang);
122  if (cache.find(lang) == cache.end())
123  cache[lang] = errorDetails;
124 }
125 
126 bool
128 {
129 #if USE_ERR_LOCALES
130  String hdr;
131  if (request != NULL && request->header.getList(Http::HdrType::ACCEPT_LANGUAGE, &hdr)) {
132  ErrorDetailsList::Pointer errDetails = NULL;
133  //Try to retrieve from cache
134  size_t pos = 0;
135  char lang[256];
136  // Get the first ellement of the Accept-Language header
137  strHdrAcptLangGetItem(hdr, lang, 256, pos);
138  errDetails = getCachedDetails(lang); // search in cache
139 
140  if (!errDetails) { // Else try to load from disk
141  debugs(83, 8, HERE << "Creating new ErrDetailList to read from disk");
142  errDetails = new ErrorDetailsList();
143  ErrorDetailFile detailTmpl(errDetails);
144  if (detailTmpl.loadFor(request.getRaw())) {
145  if (detailTmpl.language()) {
146  debugs(83, 8, HERE << "Found details on disk for language " << detailTmpl.language());
147  errDetails->errLanguage = detailTmpl.language();
148  cacheDetails(errDetails);
149  }
150  }
151  }
152 
153  if (errDetails != NULL && errDetails->getRecord(value, entry))
154  return true;
155  }
156 #endif
157 
158  // else try the default
159  if (theDefaultErrorDetails->getRecord(value, entry)) {
160  debugs(83, 8, HERE << "Found default details record for error: " << GetErrorName(value));
161  return true;
162  }
163 
164  return false;
165 }
166 
167 const char *
169 {
170  return theDefaultErrorDetails->getErrorDescr(value);
171 }
172 
173 const char *
175 {
176  return theDefaultErrorDetails->getErrorDetail(value);
177 }
178 
179 // Use HttpHeaders parser to parse error-details.txt files
181 {
182 public:
184 };
185 
186 //The end of an error detrail entry is a double "\n". The headersEnd
187 // functions can detect it
188 inline size_t detailEntryEnd(const char *s, size_t len) {return headersEnd(s, len);}
189 
190 bool
191 Ssl::ErrorDetailFile::parse(const char *buffer, int len, bool eof)
192 {
193  if (!theDetails)
194  return false;
195 
196  if (len) {
197  buf.append(buffer, len);
198  }
199 
200  if (eof)
201  buf.append("\n\n", 1);
202 
203  while (size_t size = detailEntryEnd(buf.content(), buf.contentSize())) {
204  const char *e = buf.content() + size;
205 
206  //ignore spaces, new lines and comment lines (starting with #) at the beggining
207  const char *s;
208  for (s = buf.content(); (*s == '\n' || *s == ' ' || *s == '\t' || *s == '#') && s < e; ++s) {
209  if (*s == '#')
210  while (s<e && *s != '\n')
211  ++s; // skip untill the end of line
212  }
213 
214  if ( s != e) {
215  DetailEntryParser parser;
216  Http::ContentLengthInterpreter interpreter;
217  // no applyStatusCodeRules() -- error templates lack HTTP status code
218  if (!parser.parse(s, e - s, interpreter)) {
219  debugs(83, DBG_IMPORTANT, HERE <<
220  "WARNING! parse error on:" << s);
221  return false;
222  }
223 
224  const String errorName = parser.getByName("name");
225  if (!errorName.size()) {
226  debugs(83, DBG_IMPORTANT, HERE <<
227  "WARNING! invalid or no error detail name on:" << s);
228  return false;
229  }
230 
231  Security::ErrorCode ssl_error = Ssl::GetErrorCode(errorName.termedBuf());
232  if (ssl_error != SSL_ERROR_NONE) {
233 
234  if (theDetails->getErrorDetail(ssl_error)) {
235  debugs(83, DBG_IMPORTANT, HERE <<
236  "WARNING! duplicate entry: " << errorName);
237  return false;
238  }
239 
240  ErrorDetailEntry &entry = theDetails->theList[ssl_error];
241  entry.error_no = ssl_error;
242  entry.name = errorName;
243  String tmp = parser.getByName("detail");
244  const int detailsParseOk = httpHeaderParseQuotedString(tmp.termedBuf(), tmp.size(), &entry.detail);
245  tmp = parser.getByName("descr");
246  const int descrParseOk = httpHeaderParseQuotedString(tmp.termedBuf(), tmp.size(), &entry.descr);
247 
248  if (!detailsParseOk || !descrParseOk) {
249  debugs(83, DBG_IMPORTANT, HERE <<
250  "WARNING! missing important field for detail error: " << errorName);
251  return false;
252  }
253 
254  } else if (!Ssl::ErrorIsOptional(errorName.termedBuf())) {
255  debugs(83, DBG_IMPORTANT, HERE <<
256  "WARNING! invalid error detail name: " << errorName);
257  return false;
258  }
259 
260  }// else {only spaces and black lines; just ignore}
261 
262  buf.consume(size);
263  }
264  debugs(83, 9, HERE << " Remain size: " << buf.contentSize() << " Content: " << buf.content());
265  return true;
266 }
267 
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:392
static void Shutdown()
reset the ErrorDetailsManager instance
static ErrorDetailsManager & GetInstance()
Instance class.
struct _request * request(char *urlin)
Definition: tcp-banger2.c:291
virtual bool parse(const char *buf, int len, bool eof)
Used to parse (if parsing required) the template data .
Security::ErrorCode GetErrorCode(const char *name)
The Security::ErrorCode code of the error described by "name".
Definition: ErrorDetail.cc:345
String getByName(const SBuf &name) const
Definition: HttpHeader.cc:888
size_type size() const
Definition: SquidString.h:72
void cacheDetails(ErrorDetailsList::Pointer &errorDetails)
cache the given error details list.
bool ErrorIsOptional(const char *name)
Definition: ErrorDetail.cc:405
void init(mb_size_t szInit, mb_size_t szMax)
Definition: MemBuf.cc:96
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
ErrorDetails theList
The list of error details entries.
#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:115
char const * termedBuf() const
Definition: SquidString.h:91
String getList(Http::HdrType id) const
Definition: HttpHeader.cc:828
const char * getErrorDetail(Security::ErrorCode value)
an error details for an error if exist in list.
size_t detailEntryEnd(const char *s, size_t len)
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
bool loadDefault()
Definition: errorpage.cc:257
HttpHeader header
Definition: Message.h:74
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.
void errorDetailInitialize()
const char * getDefaultErrorDescr(Security::ErrorCode value)
the default error description for a given error
Definition: MemBuf.h:23
bool strHdrAcptLangGetItem(const String &hdr, char *lang, int langLen, size_t &pos)
Definition: errorpage.cc:360
bool loadFor(const HttpRequest *request)
Definition: errorpage.cc:414
const char * language()
The language used for the template.
Definition: errorpage.h:275
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
C * getRaw() const
Definition: RefCount.h:74
#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