+/*
+ * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
#include "squid.h"
#include "ErrorDetail.h"
-#include "errorpage.h"
#include "ErrorDetailManager.h"
+#include "errorpage.h"
+#include "http/ContentLengthInterpreter.h"
#include "mime_header.h"
void Ssl::errorDetailInitialize()
{
public:
explicit ErrorDetailFile(ErrorDetailsList::Pointer const details): TemplateFile("error-details.txt", ERR_NONE) {
- buf.init();
theDetails = details;
}
private:
- MemBuf buf;
ErrorDetailsList::Pointer theDetails;
- virtual bool parse(const char *buf, int len, bool eof);
+ virtual bool parse() override;
};
}// namespace Ssl
/******************/
bool
-Ssl::ErrorDetailsList::getRecord(Ssl::ssl_error_t value, ErrorDetailEntry &entry)
+Ssl::ErrorDetailsList::getRecord(Security::ErrorCode value, ErrorDetailEntry &entry)
{
const ErrorDetails::const_iterator it = theList.find(value);
if (it != theList.end()) {
}
const char *
-Ssl::ErrorDetailsList::getErrorDescr(Ssl::ssl_error_t value)
+Ssl::ErrorDetailsList::getErrorDescr(Security::ErrorCode value)
{
const ErrorDetails::const_iterator it = theList.find(value);
if (it != theList.end()) {
}
const char *
-Ssl::ErrorDetailsList::getErrorDetail(Ssl::ssl_error_t value)
+Ssl::ErrorDetailsList::getErrorDetail(Security::ErrorCode value)
{
const ErrorDetails::const_iterator it = theList.find(value);
if (it != theList.end()) {
}
bool
-Ssl::ErrorDetailsManager::getErrorDetail(Ssl::ssl_error_t value, HttpRequest *request, ErrorDetailEntry &entry)
+Ssl::ErrorDetailsManager::getErrorDetail(Security::ErrorCode value, const HttpRequest::Pointer &request, ErrorDetailEntry &entry)
{
#if USE_ERR_LOCALES
String hdr;
- if (request && request->header.getList(HDR_ACCEPT_LANGUAGE, &hdr)) {
+ if (request != NULL && request->header.getList(Http::HdrType::ACCEPT_LANGUAGE, &hdr)) {
ErrorDetailsList::Pointer errDetails = NULL;
//Try to retrieve from cache
size_t pos = 0;
debugs(83, 8, HERE << "Creating new ErrDetailList to read from disk");
errDetails = new ErrorDetailsList();
ErrorDetailFile detailTmpl(errDetails);
- if (detailTmpl.loadFor(request)) {
+ if (detailTmpl.loadFor(request.getRaw())) {
if (detailTmpl.language()) {
debugs(83, 8, HERE << "Found details on disk for language " << detailTmpl.language());
errDetails->errLanguage = detailTmpl.language();
}
const char *
-Ssl::ErrorDetailsManager::getDefaultErrorDescr(Ssl::ssl_error_t value)
+Ssl::ErrorDetailsManager::getDefaultErrorDescr(Security::ErrorCode value)
{
return theDefaultErrorDetails->getErrorDescr(value);
}
const char *
-Ssl::ErrorDetailsManager::getDefaultErrorDetail(Ssl::ssl_error_t value)
+Ssl::ErrorDetailsManager::getDefaultErrorDetail(Security::ErrorCode value)
{
return theDefaultErrorDetails->getErrorDetail(value);
}
inline size_t detailEntryEnd(const char *s, size_t len) {return headersEnd(s, len);}
bool
-Ssl::ErrorDetailFile::parse(const char *buffer, int len, bool eof)
+Ssl::ErrorDetailFile::parse()
{
if (!theDetails)
return false;
- if (len) {
- buf.append(buffer, len);
- }
-
- if (eof)
- buf.append("\n\n", 1);
+ auto buf = template_;
+ buf.append("\n\n"); // ensure detailEntryEnd() finds the last entry
- while (size_t size = detailEntryEnd(buf.content(), buf.contentSize())) {
- const char *e = buf.content() + size;
+ while (const auto size = detailEntryEnd(buf.rawContent(), buf.length())) {
+ auto *s = buf.c_str();
+ const auto e = s + size;
- //ignore spaces, new lines and comment lines (starting with #) at the beggining
- const char *s;
- for (s = buf.content(); (*s == '\n' || *s == ' ' || *s == '\t' || *s == '#') && s < e; ++s) {
+ //ignore spaces, new lines and comment lines (starting with #) at the beginning
+ for (; (*s == '\n' || *s == ' ' || *s == '\t' || *s == '#') && s < e; ++s) {
if (*s == '#')
while (s<e && *s != '\n')
- ++s; // skip untill the end of line
+ ++s; // skip until the end of line
}
if ( s != e) {
DetailEntryParser parser;
- if (!parser.parse(s, e)) {
+ Http::ContentLengthInterpreter interpreter;
+ // no applyStatusCodeRules() -- error templates lack HTTP status code
+ if (!parser.parse(s, e - s, interpreter)) {
debugs(83, DBG_IMPORTANT, HERE <<
"WARNING! parse error on:" << s);
return false;
return false;
}
- Ssl::ssl_error_t ssl_error = Ssl::GetErrorCode(errorName.termedBuf());
- if (ssl_error == SSL_ERROR_NONE) {
- debugs(83, DBG_IMPORTANT, HERE <<
- "WARNING! invalid error detail name: " << errorName);
- return false;
- }
+ Security::ErrorCode ssl_error = Ssl::GetErrorCode(errorName.termedBuf());
+ if (ssl_error != SSL_ERROR_NONE) {
- if (theDetails->getErrorDetail(ssl_error)) {
- debugs(83, DBG_IMPORTANT, HERE <<
- "WARNING! duplicate entry: " << errorName);
- return false;
- }
+ if (theDetails->getErrorDetail(ssl_error)) {
+ debugs(83, DBG_IMPORTANT, HERE <<
+ "WARNING! duplicate entry: " << errorName);
+ return false;
+ }
- ErrorDetailEntry &entry = theDetails->theList[ssl_error];
- entry.error_no = ssl_error;
- entry.name = errorName;
- String tmp = parser.getByName("detail");
- httpHeaderParseQuotedString(tmp.termedBuf(), tmp.size(), &entry.detail);
- tmp = parser.getByName("descr");
- httpHeaderParseQuotedString(tmp.termedBuf(), tmp.size(), &entry.descr);
- bool parseOK = entry.descr.defined() && entry.detail.defined();
+ ErrorDetailEntry &entry = theDetails->theList[ssl_error];
+ entry.error_no = ssl_error;
+ entry.name = errorName;
+ String tmp = parser.getByName("detail");
+ const int detailsParseOk = httpHeaderParseQuotedString(tmp.termedBuf(), tmp.size(), &entry.detail);
+ tmp = parser.getByName("descr");
+ const int descrParseOk = httpHeaderParseQuotedString(tmp.termedBuf(), tmp.size(), &entry.descr);
+ // TODO: Validate "descr" and "detail" field values.
+
+ if (!detailsParseOk || !descrParseOk) {
+ debugs(83, DBG_IMPORTANT, HERE <<
+ "WARNING! missing important field for detail error: " << errorName);
+ return false;
+ }
- if (!parseOK) {
+ } else if (!Ssl::ErrorIsOptional(errorName.termedBuf())) {
debugs(83, DBG_IMPORTANT, HERE <<
- "WARNING! missing imporant field for detail error: " << errorName);
+ "WARNING! invalid error detail name: " << errorName);
return false;
}
+
}// else {only spaces and black lines; just ignore}
buf.consume(size);
}
- debugs(83, 9, HERE << " Remain size: " << buf.contentSize() << " Content: " << buf.content());
+ debugs(83, 9, Raw("unparsed data", buf.rawContent(), buf.length()));
return true;
}
+