]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/errorpage.cc
Merge form trunk
[thirdparty/squid.git] / src / errorpage.cc
index 9df2866897703b71395741bc2c871c3a0b3fafbb..80d0ae344dfb09806e05dc7b3aca3116edebf1b1 100644 (file)
@@ -1,8 +1,7 @@
-
 /*
  * $Id$
  *
- * DEBUG: section     Error Generation
+ * DEBUG: section 04    Error Generation
  * AUTHOR: Duane Wessels
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
  */
 #include "config.h"
 
-#include "errorpage.h"
 #include "auth/UserRequest.h"
-#include "SquidTime.h"
-#include "Store.h"
+#include "comm/Connection.h"
+#include "err_detail_type.h"
+#include "errorpage.h"
+#include "fde.h"
+#include "html_quote.h"
 #include "HttpReply.h"
 #include "HttpRequest.h"
-#include "MemObject.h"
-#include "fde.h"
 #include "MemBuf.h"
+#include "MemObject.h"
 #include "rfc1738.h"
+#include "SquidTime.h"
+#include "Store.h"
 #include "URLScheme.h"
 #include "wordlist.h"
 
@@ -369,7 +371,7 @@ errorReservePageId(const char *page_name)
 }
 
 /// \ingroup ErrorPageInternal
-static const char *
+const char *
 errorPageName(int pageId)
 {
     if (pageId >= ERR_NONE && pageId < ERR_MAX)                /* common case */
@@ -393,6 +395,7 @@ errorCon(err_type type, http_status status, HttpRequest * request)
     if (request != NULL) {
         err->request = HTTPMSGLOCK(request);
         err->src_addr = request->client_addr;
+        request->detailError(type, ERR_DETAIL_NONE);
     }
 
     return err;
@@ -440,26 +443,26 @@ errorAppendEntry(StoreEntry * entry, ErrorState * err)
 }
 
 void
-errorSend(int fd, ErrorState * err)
+errorSend(const Comm::ConnectionPointer &conn, ErrorState * err)
 {
     HttpReply *rep;
-    debugs(4, 3, "errorSend: FD " << fd << ", err=" << err);
-    assert(fd >= 0);
+    debugs(4, 3, HERE << conn << ", err=" << err);
+    assert(Comm::IsConnOpen(conn));
     /*
      * ugh, this is how we make sure error codes get back to
      * the client side for logging and error tracking.
      */
 
     if (err->request)
-        err->request->errType = err->type;
+        err->request->detailError(err->type, err->xerrno);
 
     /* moved in front of errorBuildBuf @?@ */
     err->flags.flag_cbdata = 1;
 
     rep = err->BuildHttpReply();
-
-    comm_write_mbuf(fd, rep->pack(), errorSendComplete, err);
-
+    MemBuf *mb = rep->pack();
+    comm_write_mbuf(conn, mb, errorSendComplete, err);
+    delete mb;
     delete rep;
 }
 
@@ -473,18 +476,18 @@ errorSend(int fd, ErrorState * err)
  *     closing the FD, otherwise we do it ourselves.
  */
 static void
-errorSendComplete(int fd, char *bufnotused, size_t size, comm_err_t errflag, int xerrno, void *data)
+errorSendComplete(const Comm::ConnectionPointer &conn, char *bufnotused, size_t size, comm_err_t errflag, int xerrno, void *data)
 {
     ErrorState *err = static_cast<ErrorState *>(data);
-    debugs(4, 3, "errorSendComplete: FD " << fd << ", size=" << size);
+    debugs(4, 3, HERE << conn << ", size=" << size);
 
     if (errflag != COMM_ERR_CLOSING) {
         if (err->callback) {
             debugs(4, 3, "errorSendComplete: callback");
-            err->callback(fd, err->callback_data, size);
+            err->callback(conn->fd, err->callback_data, size);
         } else {
-            comm_close(fd);
             debugs(4, 3, "errorSendComplete: comm_close");
+            conn->close();
         }
     }
 
@@ -501,7 +504,7 @@ errorStateFree(ErrorState * err)
     wordlistDestroy(&err->ftp.server_msg);
     safe_free(err->ftp.request);
     safe_free(err->ftp.reply);
-    AUTHUSERREQUESTUNLOCK(err->auth_user_request, "errstate");
+    err->auth_user_request = NULL;
     safe_free(err->err_msg);
 #if USE_ERR_LOCALES
     if (err->err_language != Config.errorDefaultLanguage)
@@ -596,12 +599,12 @@ ErrorState::Dump(MemBuf * mb)
 #define CVT_BUF_SZ 512
 
 const char *
-ErrorState::Convert(char token, bool url_presentable)
+ErrorState::Convert(char token, bool building_deny_info_url)
 {
     static MemBuf mb;
     const char *p = NULL;      /* takes priority over mb if set */
     int do_quote = 1;
-    int no_urlescape = 1;       /* item is NOT to be further URL-encoded */
+    int no_urlescape = 0;       /* if true then item is NOT to be further URL-encoded */
     char ntoabuf[MAX_IPSTRLEN];
 
     mb.reset();
@@ -609,20 +612,19 @@ ErrorState::Convert(char token, bool url_presentable)
     switch (token) {
 
     case 'a':
-        if (request && request->auth_user_request)
+        if (request && request->auth_user_request != NULL)
             p = request->auth_user_request->username();
         if (!p)
             p = "-";
         break;
 
     case 'B':
-        if (url_presentable) break;
+        if (building_deny_info_url) break;
         p = request ? ftpUrlWith2f(request) : "[no URL]";
-        no_urlescape = 1;
         break;
 
     case 'c':
-        if (url_presentable) break;
+        if (building_deny_info_url) break;
         p = errorPageName(type);
         break;
 
@@ -638,7 +640,7 @@ ErrorState::Convert(char token, bool url_presentable)
         break;
 
     case 'f':
-        if (url_presentable) break;
+        if (building_deny_info_url) break;
         /* FTP REQUEST LINE */
         if (ftp.request)
             p = ftp.request;
@@ -647,7 +649,7 @@ ErrorState::Convert(char token, bool url_presentable)
         break;
 
     case 'F':
-        if (url_presentable) break;
+        if (building_deny_info_url) break;
         /* FTP REPLY LINE */
         if (ftp.request)
             p = ftp.reply;
@@ -656,7 +658,7 @@ ErrorState::Convert(char token, bool url_presentable)
         break;
 
     case 'g':
-        if (url_presentable) break;
+        if (building_deny_info_url) break;
         /* FTP SERVER MESSAGE */
         if (ftp.server_msg)
             wordlistCat(ftp.server_msg, &mb);
@@ -676,7 +678,7 @@ ErrorState::Convert(char token, bool url_presentable)
                 p = request->hier.host;
             else
                 p = request->GetHost();
-        } else if (!url_presentable)
+        } else if (!building_deny_info_url)
             p = "[unknown host]";
         break;
 
@@ -687,54 +689,61 @@ ErrorState::Convert(char token, bool url_presentable)
     case 'I':
         if (request && request->hier.host[0] != '\0') // if non-empty string
             mb.Printf("%s", request->hier.host);
-        else if (!url_presentable)
+        else if (!building_deny_info_url)
             p = "[unknown]";
         break;
 
     case 'l':
-        if (url_presentable) break;
+        if (building_deny_info_url) break;
         mb.append(error_stylesheet.content(), error_stylesheet.contentSize());
         do_quote = 0;
         break;
 
     case 'L':
-        if (url_presentable) break;
+        if (building_deny_info_url) break;
         if (Config.errHtmlText) {
             mb.Printf("%s", Config.errHtmlText);
             do_quote = 0;
-        } else if (!url_presentable)
+        } else
             p = "[not available]";
         break;
 
     case 'm':
-        if (url_presentable) break;
+        if (building_deny_info_url) break;
         p = auth_user_request->denyMessage("[not available]");
         break;
 
     case 'M':
-        p = request ? RequestMethodStr(request->method) : "[unknown method]";
+        if (request)
+            p = RequestMethodStr(request->method);
+        else if (!building_deny_info_url)
+            p= "[unknown method]";
         break;
 
     case 'o':
         p = request ? request->extacl_message.termedBuf() : external_acl_message;
-        if (!p)
+        if (!p && !building_deny_info_url)
             p = "[not available]";
         break;
 
     case 'p':
         if (request) {
             mb.Printf("%d", (int) request->port);
-        } else if (!url_presentable) {
+        } else if (!building_deny_info_url) {
             p = "[unknown port]";
         }
         break;
 
     case 'P':
-        p = request ? ProtocolStr[request->protocol] : "[unknown protocol]";
+        if (request) {
+            p = ProtocolStr[request->protocol];
+        } else if (!building_deny_info_url) {
+            p = "[unknown protocol]";
+        }
         break;
 
     case 'R':
-        if (url_presentable) {
+        if (building_deny_info_url) {
             p = (request->urlpath.size() != 0 ? request->urlpath.termedBuf() : "/");
             break;
         }
@@ -763,7 +772,7 @@ ErrorState::Convert(char token, bool url_presentable)
 
     case 's':
         /* for backward compat we make %s show the full URL. Drop this in some future release. */
-        if (url_presentable) {
+        if (building_deny_info_url) {
             p = request ? urlCanonical(request) : url;
             debugs(0,0, "WARNING: deny_info now accepts coded tags. Use %u to get the full URL instead of %s");
         } else
@@ -771,7 +780,10 @@ ErrorState::Convert(char token, bool url_presentable)
         break;
 
     case 'S':
-        if (url_presentable) break;
+        if (building_deny_info_url) {
+            p = visible_appname_string;
+            break;
+        }
         /* signature may contain %-escapes, recursion */
         if (page_id != ERR_SQUID_SIGNATURE) {
             const int saved_id = page_id;
@@ -799,28 +811,39 @@ ErrorState::Convert(char token, bool url_presentable)
     case 'U':
         /* Using the fake-https version of canonical so error pages see https:// */
         /* even when the url-path cannot be shown as more than '*' */
-        p = request ? urlCanonicalFakeHttps(request) : url ? url : "[no URL]";
+        if (request)
+            p = urlCanonicalFakeHttps(request);
+        else if (url)
+            p = url;
+        else if (!building_deny_info_url)
+            p = "[no URL]";
         break;
 
     case 'u':
-        p = request ? urlCanonical(request) : url ? url : "[no URL]";
+        if (request)
+            p = urlCanonical(request);
+        else if (url)
+            p = url;
+        else if (!building_deny_info_url)
+            p = "[no URL]";
         break;
 
     case 'w':
         if (Config.adminEmail)
             mb.Printf("%s", Config.adminEmail);
-        else if (!url_presentable)
+        else if (!building_deny_info_url)
             p = "[unknown]";
         break;
 
     case 'W':
-        if (url_presentable) break;
+        if (building_deny_info_url) break;
         if (Config.adminEmail && Config.onoff.emailErrData)
             Dump(&mb);
+        no_urlescape = 1;
         break;
 
     case 'z':
-        if (url_presentable) break;
+        if (building_deny_info_url) break;
         if (dnsError.size() > 0)
             p = dnsError.termedBuf();
         else if (ftp.cwd_msg)
@@ -830,7 +853,7 @@ ErrorState::Convert(char token, bool url_presentable)
         break;
 
     case 'Z':
-        if (url_presentable) break;
+        if (building_deny_info_url) break;
         if (err_msg)
             p = err_msg;
         else
@@ -857,7 +880,7 @@ ErrorState::Convert(char token, bool url_presentable)
     if (do_quote)
         p = html_quote(p);
 
-    if (url_presentable && !no_urlescape)
+    if (building_deny_info_url && !no_urlescape)
         p = rfc1738_escape_part(p);
 
     return p;
@@ -995,7 +1018,7 @@ ErrorState::BuildContent()
             bool invalid_byte = false;
             while (pos < hdr.size() && hdr[pos] != ';' && hdr[pos] != ',' && !xisspace(hdr[pos]) && dt < (dir+256) ) {
                 if (!invalid_byte) {
-#if HTTP_VIOLATIONS
+#if USE_HTTP_VIOLATIONS
                     // if accepting violations we may as well accept some broken browsers
                     //  which may send us the right code, wrong ISO formatting.
                     if (hdr[pos] == '_')