]> git.ipfire.org Git - thirdparty/squid.git/blame - src/errorpage.cc
just in case
[thirdparty/squid.git] / src / errorpage.cc
CommitLineData
4a9a952e 1
30a4f2a8 2/*
59ea0962 3 * $Id: errorpage.cc,v 1.80 1997/10/21 03:33:41 wessels Exp $
30a4f2a8 4 *
5 * DEBUG: section 4 Error Generation
6 * AUTHOR: Duane Wessels
7 *
42c04c16 8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
30a4f2a8 9 * --------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by
14 * the National Science Foundation.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 *
30 */
1e74c110 31
44a47c6e 32#include "squid.h"
1e74c110 33
9b312a19 34const char *err_string[] =
1e74c110 35{
9b312a19 36 "ERR_NONE",
37 "ERR_READ_TIMEOUT",
38 "ERR_LIFETIME_EXP",
9b312a19 39 "ERR_READ_ERROR",
40 "ERR_WRITE_ERROR",
41 "ERR_CLIENT_ABORT",
42 "ERR_CONNECT_FAIL",
43 "ERR_INVALID_REQ",
44 "ERR_UNSUP_REQ",
45 "ERR_INVALID_URL",
46 "ERR_SOCKET_FAILURE",
47 "ERR_DNS_FAIL",
9b312a19 48 "ERR_CANNOT_FORWARD",
49 "ERR_NO_RELAY",
9b312a19 50 "ERR_ZERO_SIZE_OBJECT",
51 "ERR_FTP_DISABLED",
9b312a19 52 "ERR_ACCESS_DENIED",
53 "ERR_MAX"
1e74c110 54};
55
9b312a19 56static char *error_text[ERR_MAX];
57
58static void errorStateFree _PARAMS((ErrorState * err));
59static char *errorConvert _PARAMS((char token, ErrorState * err));
60static char *errorBuildBuf _PARAMS((ErrorState * err, int *len));
61static CWCB errorSendComplete;
1e74c110 62
b8d8561b 63void
0673c0ba 64errorInitialize(void)
fa966b74 65{
9b312a19 66 err_type i;
67 int fd;
68 char path[MAXPATHLEN];
69 struct stat sb;
70 assert(sizeof(err_string) == (ERR_MAX + 1) * 4);
71 for (i = ERR_NONE + 1; i < ERR_MAX; i++) {
72 snprintf(path, MAXPATHLEN, "%s/%s",
73 Config.errorDirectory, err_string[i]);
74 fd = file_open(path, O_RDONLY, NULL, NULL);
75 if (fd < 0) {
76 debug(4, 0) ("errorInitialize: %s: %s\n", path, xstrerror());
77 fatal("Failed to open error text file");
78 }
79 if (fstat(fd, &sb) < 0)
80 fatal_dump("stat() failed on error text file");
81 safe_free(error_text[i]);
59ea0962 82 error_text[i] = xcalloc(sb.st_size+1, 1);
9b312a19 83 if (read(fd, error_text[i], sb.st_size) != sb.st_size)
84 fatal_dump("failed to fully read error text file");
85 file_close(fd);
1e74c110 86 }
6eb42cae 87}
88
9b312a19 89static void
90errorStateFree(ErrorState * err)
6eb42cae 91{
9b312a19 92 requestUnlink(err->request);
93 safe_free(err->redirect_url);
94 safe_free(err->url);
95 cbdataFree(err);
1e74c110 96}
8213067d 97
2658f489 98#define CVT_BUF_SZ 512
9b312a19 99static char *
100errorConvert(char token, ErrorState * err)
8213067d 101{
9b312a19 102 char *p = NULL;
2658f489 103 request_t *r = err->request;
104 static char buf[CVT_BUF_SZ];
9b312a19 105 switch (token) {
106 case 'U':
2658f489 107 p = r ? urlCanonicalClean(r) : err->url;
9b312a19 108 break;
2658f489 109 case 'H':
110 p = r ? r->host : "[unknown host]";
111 break;
112 case 'p':
113 if (r) {
437e2060 114 snprintf(buf, CVT_BUF_SZ, "%d", (int) r->port);
115 p = buf;
2658f489 116 } else {
437e2060 117 p = "[unknown port]";
2658f489 118 }
119 break;
120 case 'P':
121 p = r ? (char *) ProtocolStr[r->protocol] : "[unkown protocol]";
122 break;
123 case 'M':
124 p = r ? (char *) RequestMethodStr[r->method] : "[unkown method]";
125 break;
126 case 'z':
127 p = err->dnsserver_msg;
128 break;
042461c3 129 case 'e':
130 snprintf(buf, CVT_BUF_SZ, "%d", err->errno);
56878878 131 p = buf;
042461c3 132 break;
133 case 'E':
8350fe9b 134 snprintf(buf, CVT_BUF_SZ, "(%d) %s", err->errno, strerror(err->errno));
ceab4c00 135 p = buf;
03d7b07f 136 break;
137 case 'w':
ceab4c00 138 if (Config.adminEmail) {
139 snprintf(buf, CVT_BUF_SZ, "%s", Config.adminEmail);
140 p = buf;
141 } else
142 p = "UNKNOWN";
03d7b07f 143 break;
144 case 'h':
145 snprintf(buf, CVT_BUF_SZ, "%s", getMyHostname());
ceab4c00 146 p = buf;
042461c3 147 break;
2658f489 148/*
56878878 149 * e - errno x
150 * E - strerror() x
437e2060 151 * t - local time
152 * T - UTC
153 * c - Squid error code
154 * I - server IP address
155 * i - client IP address
156 * L - HREF link for more info/contact
56878878 157 * w - cachemgr email address x
158 * h - cache hostname x
437e2060 159 * d - seconds elapsed since request received
56878878 160 * p - URL port # x
437e2060 161 */
9b312a19 162 default:
163 p = "%UNKNOWN%";
164 break;
165 }
166 if (p == NULL)
167 p = "<NULL>";
e102ebda 168 debug(4, 3) ("errorConvert: %%%c --> '%s'\n", token, p);
9b312a19 169 return p;
8213067d 170}
e381a13d 171
9b312a19 172static char *
173errorBuildBuf(ErrorState * err, int *len)
e381a13d 174{
9b312a19 175 LOCAL_ARRAY(char, buf, ERROR_BUF_SZ);
176 LOCAL_ARRAY(char, content, ERROR_BUF_SZ);
177 char *hdr;
178 int clen;
179 int tlen;
180 char *m;
b8b780a4 181 char *mx;
9b312a19 182 char *p;
183 char *t;
184 assert(err != NULL);
185 assert(err->type > ERR_NONE && err->type < ERR_MAX);
b8b780a4 186 mx = m = xstrdup(error_text[err->type]);
9b312a19 187 clen = 0;
188 while ((p = strchr(m, '%'))) {
189 *p = '\0'; /* terminate */
190 xstrncpy(content + clen, m, ERROR_BUF_SZ - clen); /* copy */
191 clen += (p - m); /* advance */
192 if (clen >= ERROR_BUF_SZ)
193 break;
194 p++;
195 m = p + 1;
196 t = errorConvert(*p, err); /* convert */
197 xstrncpy(content + clen, t, ERROR_BUF_SZ - clen); /* copy */
198 clen += strlen(t); /* advance */
199 if (clen >= ERROR_BUF_SZ)
200 break;
201 }
202 if (clen < ERROR_BUF_SZ && m != NULL) {
203 xstrncpy(content + clen, m, ERROR_BUF_SZ - clen);
204 clen += strlen(m);
205 }
206 if (clen >= ERROR_BUF_SZ) {
207 clen = ERROR_BUF_SZ - 1;
208 *(content + clen) = '\0';
209 }
210 assert(clen == strlen(content));
211 hdr = httpReplyHeader((double) 1.0,
212 err->http_status,
b8d8561b 213 "text/html",
9b312a19 214 clen,
437e2060 215 0, /* no LMT for error pages */
9b312a19 216 squid_curtime);
217 tlen = snprintf(buf, ERROR_BUF_SZ, "%s\r\n%s", hdr, content);
218 if (len)
219 *len = tlen;
b8b780a4 220 xfree(mx);
9b312a19 221 return buf;
e381a13d 222}
e81957b7 223
9b312a19 224void
225errorSend(int fd, ErrorState * err)
e81957b7 226{
9b312a19 227 char *buf;
228 int len;
6a54c60e 229 debug(4, 3) ("errorSend: FD %d, err=%p\n", fd, err);
9b312a19 230 assert(fd >= 0);
231 buf = errorBuildBuf(err, &len);
232 cbdataAdd(err);
233 cbdataLock(err);
234 comm_write(fd, xstrdup(buf), len, errorSendComplete, err, xfree);
e81957b7 235}
0a21bd84 236
237void
b716a8ad 238errorAppendEntry(StoreEntry * entry, ErrorState * err)
9b312a19 239{
240 char *buf;
e3f80962 241 MemObject *mem = entry->mem_obj;
9b312a19 242 int len;
243 assert(entry->store_status == STORE_PENDING);
244 buf = errorBuildBuf(err, &len);
245 storeAppend(entry, buf, len);
e3f80962 246 if (mem)
247 mem->reply->code = err->http_status;
9b312a19 248}
249
250static void
251errorSendComplete(int fd, char *buf, int size, int errflag, void *data)
0a21bd84 252{
9b312a19 253 ErrorState *err = data;
6a54c60e 254 debug(4, 3) ("errorSendComplete: FD %d, size=%d\n", fd, size);
9b312a19 255 if (err->callback)
256 err->callback(fd, err->callback_data, size);
257 cbdataUnlock(err);
258 errorStateFree(err);
1b9cbc64 259 comm_close(fd);
0a21bd84 260}