Brian J. Murrell wrote:
On Thu, 2009-10-29 at 23:58 +0100, Henrik Nordstrom wrote:
Either using url_rewrite_program and an url rewriter/redirector helper,
or by using http_access deny + deny_info.
Ahhh. deny_info is interesting. I guess there is no manipulating the
url that caused the deny, i.e. to customize the 302.
So, writing a deny such that if the URL denied was
http://foo.bar.com/some/path/index.hml, I can take the path portion and
do a 302 redirect to http://internal.my.domain.com/<same path as denied
url>.
Perhaps that's going to be left to the domain of redirector helpers.
I got that going a few weeks ago. It's scheduled for 3.2. The patch
should still apply easily to 3.1.
Amos
--
Please be using
Current Stable Squid 2.7.STABLE7 or 3.0.STABLE20
Current Beta Squid 3.1.0.14
=== modified file 'src/errorpage.cc'
--- src/errorpage.cc 2009-08-23 09:30:49 +0000
+++ src/errorpage.cc 2009-09-22 12:45:24 +0000
@@ -595,11 +595,12 @@
#define CVT_BUF_SZ 512
const char *
-ErrorState::Convert(char token)
+ErrorState::Convert(char token, bool url_presentable)
{
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 */
char ntoabuf[MAX_IPSTRLEN];
mb.reset();
@@ -607,37 +608,30 @@
switch (token) {
case 'a':
-
if (request && request->auth_user_request)
p = request->auth_user_request->username();
-
if (!p)
p = "-";
-
break;
case 'B':
p = request ? ftpUrlWith2f(request) : "[no URL]";
-
+ no_urlescape = 1;
break;
case 'c':
p = errorPageName(type);
-
break;
case 'e':
mb.Printf("%d", xerrno);
-
break;
case 'E':
-
if (xerrno)
mb.Printf("(%d) %s", xerrno, strerror(xerrno));
else
mb.Printf("[No Error]");
-
break;
case 'f':
@@ -646,7 +640,6 @@
p = ftp.request;
else
p = "nothing";
-
break;
case 'F':
@@ -655,13 +648,12 @@
p = ftp.reply;
else
p = "nothing";
-
break;
case 'g':
+ if (url_presentable) break;
/* FTP SERVER MESSAGE */
wordlistCat(ftp.server_msg, &mb);
-
break;
case 'h':
@@ -676,12 +668,10 @@
p = request->GetHost();
} else
p = "[unknown host]";
-
break;
case 'i':
mb.Printf("%s", src_addr.NtoA(ntoabuf,MAX_IPSTRLEN));
-
break;
case 'I':
@@ -689,36 +679,34 @@
mb.Printf("%s", request->hier.host);
else
p = "[unknown]";
-
break;
case 'l':
+ if (!url_presentable) break;
mb.append(error_stylesheet.content(), error_stylesheet.contentSize());
do_quote = 0;
break;
case 'L':
+ if (!url_presentable) break;
if (Config.errHtmlText) {
mb.Printf("%s", Config.errHtmlText);
do_quote = 0;
} else
p = "[not available]";
-
break;
case 'm':
+ if (!url_presentable) break;
p = auth_user_request->denyMessage("[not available]");
-
break;
case 'M':
p = request ? RequestMethodStr(request->method) : "[unknown method]";
-
break;
case 'o':
p = external_acl_message ? external_acl_message : "[not available]";
-
break;
case 'p':
@@ -727,7 +715,6 @@
} else {
p = "[unknown port]";
}
-
break;
case 'P':
@@ -735,7 +722,10 @@
break;
case 'R':
-
+ if (url_presentable) {
+ p = (request->urlpath.size() != 0 ? request->urlpath.termedBuf() : "/");
+ break;
+ }
if (NULL != request) {
Packer p;
String urlpath_or_slash;
@@ -757,16 +747,21 @@
} else {
p = "[no request]";
}
-
break;
case 's':
- p = visible_appname_string;
+ /* for backward compatibility we need to maek %s show the full URL. */
+ if (url_presentable) {
+ p = request ? urlCanonical(request) : url ? url : "[no URL]";
+ debugs(0,0, "WARNING: deny_info now accepts coded tags. Use %u to get the full URL instead of %s");
+ }
+ else
+ p = visible_appname_string;
break;
case 'S':
+ if (!url_presentable) break;
/* signature may contain %-escapes, recursion */
-
if (page_id != ERR_SQUID_SIGNATURE) {
const int saved_id = page_id;
page_id = ERR_SQUID_SIGNATURE;
@@ -780,7 +775,6 @@
/* wow, somebody put %S into ERR_SIGNATURE, stop recursion */
p = "[%S]";
}
-
break;
case 't':
@@ -802,46 +796,41 @@
break;
case 'w':
-
if (Config.adminEmail)
mb.Printf("%s", Config.adminEmail);
else
p = "[unknown]";
-
break;
case 'W':
+ if (!url_presentable) break;
if (Config.adminEmail && Config.onoff.emailErrData)
Dump(&mb);
-
break;
case 'z':
+ if (!url_presentable) break;
if (dnsError.size() > 0)
p = dnsError.termedBuf();
else
p = "[unknown]";
-
break;
case 'Z':
+ if (!url_presentable) break;
if (err_msg)
p = err_msg;
else
p = "[unknown]";
-
break;
case '%':
p = "%";
-
break;
default:
mb.Printf("%%%c", token);
-
do_quote = 0;
-
break;
}
@@ -855,9 +844,32 @@
if (do_quote)
p = html_quote(p);
+ if (url_presentable && !no_urlescape)
+ p = rfc1738_escape_part(p);
+
return p;
}
+void
+ErrorState::DenyInfoLocation(const char *name, HttpRequest *request, MemBuf &result)
+{
+ char const *m = name;
+ char const *p = m;
+ char const *t;
+
+ while ((p = strchr(m, '%'))) {
+ result.append(m, p - m); /* copy */
+ t = Convert(*++p, true); /* convert */
+ result.Printf("%s", t); /* copy */
+ m = p + 1; /* advance */
+ }
+
+ if (*m)
+ result.Printf("%s", m); /* copy tail */
+
+ assert((size_t)result.contentSize() == strlen(result.content()));
+}
+
HttpReply *
ErrorState::BuildHttpReply()
{
@@ -871,8 +883,10 @@
rep->setHeaders(version, HTTP_MOVED_TEMPORARILY, NULL, "text/html", 0, 0, -1);
if (request) {
- char *quoted_url = rfc1738_escape_part(urlCanonical(request));
- httpHeaderPutStrf(&rep->header, HDR_LOCATION, name, quoted_url);
+ MemBuf redirect_location;
+ redirect_location.init();
+ DenyInfoLocation(name, request, redirect_location);
+ httpHeaderPutStrf(&rep->header, HDR_LOCATION, "%s", redirect_location.content() );
}
httpHeaderPutStrf(&rep->header, HDR_X_SQUID_ERROR, "%d %s", httpStatus, "Access Denied");
@@ -1048,7 +1062,7 @@
while ((p = strchr(m, '%'))) {
content->append(m, p - m); /* copy */
- t = Convert(*++p); /* convert */
+ t = Convert(*++p, false); /* convert */
content->Printf("%s", t); /* copy */
m = p + 1; /* advance */
}
=== modified file 'src/errorpage.h'
--- src/errorpage.h 2009-07-12 22:56:47 +0000
+++ src/errorpage.h 2009-09-22 11:55:39 +0000
@@ -99,9 +99,21 @@
MemBuf *BuildContent(void);
/**
- * Convert an error template into an error page.
- */
- const char *Convert(char token);
+ * Generates the Location: header value for a deny_info error page
+ * to be used for this error.
+ */
+ void DenyInfoLocation(const char *name, HttpRequest *request, MemBuf &result);
+
+ /**
+ * Map the Error page and deny_info template % codes into textual output.
+ *
+ * Several of the codes produce blocks of non-URL compatible results.
+ * When processing the deny_info location URL they will be skipped.
+ *
+ * \param token The token following % which need to be converted
+ * \param url_presentable URL-encode the the output for deny_info redirect
+ */
+ const char *Convert(char token, bool url_presentable);
/**
* CacheManager / Debug dump of the ErrorState object.