]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/ssl/ErrorDetailManager.cc
2 #include "ErrorDetail.h"
3 #include "ErrorDetailManager.h"
5 #include "mime_header.h"
7 void Ssl::errorDetailInitialize()
9 Ssl::ErrorDetailsManager::GetInstance();
12 void Ssl::errorDetailClean()
14 Ssl::ErrorDetailsManager::Shutdown();
20 /// manages error detail templates
21 class ErrorDetailFile
: public TemplateFile
24 explicit ErrorDetailFile(ErrorDetailsList::Pointer
const details
): TemplateFile("error-details.txt", ERR_NONE
) {
31 ErrorDetailsList::Pointer theDetails
;
32 virtual bool parse(const char *buf
, int len
, bool eof
);
38 Ssl::ErrorDetailsList::getRecord(Ssl::ssl_error_t value
, ErrorDetailEntry
&entry
)
40 const ErrorDetails::const_iterator it
= theList
.find(value
);
41 if (it
!= theList
.end()) {
42 entry
.error_no
= it
->second
.error_no
;
43 entry
.name
= it
->second
.name
;
44 entry
.detail
= it
->second
.detail
;
45 entry
.descr
= it
->second
.descr
;
52 Ssl::ErrorDetailsList::getErrorDescr(Ssl::ssl_error_t value
)
54 const ErrorDetails::const_iterator it
= theList
.find(value
);
55 if (it
!= theList
.end()) {
56 return it
->second
.descr
.termedBuf();
63 Ssl::ErrorDetailsList::getErrorDetail(Ssl::ssl_error_t value
)
65 const ErrorDetails::const_iterator it
= theList
.find(value
);
66 if (it
!= theList
.end()) {
67 return it
->second
.detail
.termedBuf();
73 Ssl::ErrorDetailsManager
*Ssl::ErrorDetailsManager::TheDetailsManager
= NULL
;
75 Ssl::ErrorDetailsManager
&Ssl::ErrorDetailsManager::GetInstance()
77 if (!TheDetailsManager
)
78 TheDetailsManager
= new Ssl::ErrorDetailsManager
;
80 assert(TheDetailsManager
);
81 return *TheDetailsManager
;
84 void Ssl::ErrorDetailsManager::Shutdown()
86 delete TheDetailsManager
;
87 TheDetailsManager
= NULL
;
90 Ssl::ErrorDetailsManager::ErrorDetailsManager()
92 theDefaultErrorDetails
= new ErrorDetailsList();
93 ErrorDetailFile
detailTmpl(theDefaultErrorDetails
);
94 detailTmpl
.loadDefault();
97 Ssl::ErrorDetailsList::Pointer
Ssl::ErrorDetailsManager::getCachedDetails(const char *lang
)
100 it
= cache
.find(lang
);
101 if (it
!= cache
.end()) {
102 debugs(83, 8, HERE
<< "Found template details in cache for language: " << lang
);
109 void Ssl::ErrorDetailsManager::cacheDetails(ErrorDetailsList::Pointer
&errorDetails
)
111 const char *lang
= errorDetails
->errLanguage
.termedBuf();
113 if (cache
.find(lang
) == cache
.end())
114 cache
[lang
] = errorDetails
;
118 Ssl::ErrorDetailsManager::getErrorDetail(Ssl::ssl_error_t value
, const HttpRequest::Pointer
&request
, ErrorDetailEntry
&entry
)
122 if (request
!= NULL
&& request
->header
.getList(HDR_ACCEPT_LANGUAGE
, &hdr
)) {
123 ErrorDetailsList::Pointer errDetails
= NULL
;
124 //Try to retrieve from cache
127 // Get the first ellement of the Accept-Language header
128 strHdrAcptLangGetItem(hdr
, lang
, 256, pos
);
129 errDetails
= getCachedDetails(lang
); // search in cache
131 if (!errDetails
) { // Else try to load from disk
132 debugs(83, 8, HERE
<< "Creating new ErrDetailList to read from disk");
133 errDetails
= new ErrorDetailsList();
134 ErrorDetailFile
detailTmpl(errDetails
);
135 if (detailTmpl
.loadFor(request
.getRaw())) {
136 if (detailTmpl
.language()) {
137 debugs(83, 8, HERE
<< "Found details on disk for language " << detailTmpl
.language());
138 errDetails
->errLanguage
= detailTmpl
.language();
139 cacheDetails(errDetails
);
144 if (errDetails
!= NULL
&& errDetails
->getRecord(value
, entry
))
149 // else try the default
150 if (theDefaultErrorDetails
->getRecord(value
, entry
)) {
151 debugs(83, 8, HERE
<< "Found default details record for error: " << GetErrorName(value
));
159 Ssl::ErrorDetailsManager::getDefaultErrorDescr(Ssl::ssl_error_t value
)
161 return theDefaultErrorDetails
->getErrorDescr(value
);
165 Ssl::ErrorDetailsManager::getDefaultErrorDetail(Ssl::ssl_error_t value
)
167 return theDefaultErrorDetails
->getErrorDetail(value
);
170 // Use HttpHeaders parser to parse error-details.txt files
171 class DetailEntryParser
: public HttpHeader
174 DetailEntryParser():HttpHeader(hoErrorDetail
) {}
177 //The end of an error detrail entry is a double "\n". The headersEnd
178 // functions can detect it
179 inline size_t detailEntryEnd(const char *s
, size_t len
) {return headersEnd(s
, len
);}
182 Ssl::ErrorDetailFile::parse(const char *buffer
, int len
, bool eof
)
188 buf
.append(buffer
, len
);
192 buf
.append("\n\n", 1);
194 while (size_t size
= detailEntryEnd(buf
.content(), buf
.contentSize())) {
195 const char *e
= buf
.content() + size
;
197 //ignore spaces, new lines and comment lines (starting with #) at the beggining
199 for (s
= buf
.content(); (*s
== '\n' || *s
== ' ' || *s
== '\t' || *s
== '#') && s
< e
; ++s
) {
201 while (s
<e
&& *s
!= '\n')
202 ++s
; // skip untill the end of line
206 DetailEntryParser parser
;
207 if (!parser
.parse(s
, e
)) {
208 debugs(83, DBG_IMPORTANT
, HERE
<<
209 "WARNING! parse error on:" << s
);
213 const String errorName
= parser
.getByName("name");
214 if (!errorName
.size()) {
215 debugs(83, DBG_IMPORTANT
, HERE
<<
216 "WARNING! invalid or no error detail name on:" << s
);
220 Ssl::ssl_error_t ssl_error
= Ssl::GetErrorCode(errorName
.termedBuf());
221 if (ssl_error
!= SSL_ERROR_NONE
) {
223 if (theDetails
->getErrorDetail(ssl_error
)) {
224 debugs(83, DBG_IMPORTANT
, HERE
<<
225 "WARNING! duplicate entry: " << errorName
);
229 ErrorDetailEntry
&entry
= theDetails
->theList
[ssl_error
];
230 entry
.error_no
= ssl_error
;
231 entry
.name
= errorName
;
232 String tmp
= parser
.getByName("detail");
233 const int detailsParseOk
= httpHeaderParseQuotedString(tmp
.termedBuf(), tmp
.size(), &entry
.detail
);
234 tmp
= parser
.getByName("descr");
235 const int descrParseOk
= httpHeaderParseQuotedString(tmp
.termedBuf(), tmp
.size(), &entry
.descr
);
237 if (!detailsParseOk
|| !descrParseOk
) {
238 debugs(83, DBG_IMPORTANT
, HERE
<<
239 "WARNING! missing important field for detail error: " << errorName
);
243 } else if (!Ssl::ErrorIsOptional(errorName
.termedBuf())) {
244 debugs(83, DBG_IMPORTANT
, HERE
<<
245 "WARNING! invalid error detail name: " << errorName
);
249 }// else {only spaces and black lines; just ignore}
253 debugs(83, 9, HERE
<< " Remain size: " << buf
.contentSize() << " Content: " << buf
.content());