/[hydra]/hydra/src/response.c
ViewVC logotype

Contents of /hydra/src/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.4 - (show annotations)
Wed Sep 25 10:42:48 2002 UTC (21 years, 6 months ago) by nmav
Branch: MAIN
Changes since 1.3: +3 -3 lines
File MIME type: text/plain
*** empty log message ***

1 /*
2 * Boa, an http server
3 * Copyright (C) 1995 Paul Phillips <paulp@go2net.com>
4 * Some changes Copyright (C) 1996 Larry Doolittle <ldoolitt@boa.org>
5 * Some changes Copyright (C) 1996-99 Jon Nelson <jnelson@boa.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 1, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 */
22
23 /* $Id: response.c,v 1.3 2002/09/23 12:48:59 nmav Exp $*/
24
25 #include "boa.h"
26
27 #define HTML "text/html; charset=ISO-8859-1"
28 #define CRLF "\r\n"
29
30 void print_content_type(request * req)
31 {
32 req_write(req, "Content-Type: ");
33 req_write(req, get_mime_type(req->request_uri));
34 req_write(req, "\r\n");
35 }
36
37 void print_content_length(request * req)
38 {
39 char buf[22];
40
41 simple_itoa( (req->range_stop)-(req->range_start), buf);
42 req_write(req, "Content-Length: ");
43 req_write(req, buf);
44 req_write(req, "\r\n");
45 }
46
47 void print_content_range(request * req)
48 {
49 char start[22];
50 char stop[22];
51 char total[22];
52 char buf[22*3 + 5];
53
54 req_write(req, "Content-Range: bytes ");
55
56 simple_itoa( req->range_stop, stop);
57 simple_itoa( req->range_start, start);
58 simple_itoa( req->filesize, total);
59
60 sprintf( buf, "%s-%s/%s\r\n", start, stop, total);
61 req_write(req, buf);
62 }
63
64 void print_last_modified(request * req)
65 {
66 char lm[] = "Last-Modified: "
67 " " "\r\n";
68 rfc822_time_buf(lm + 15, req->last_modified);
69 req_write(req, lm);
70 }
71
72 void print_ka_phrase(request * req)
73 {
74
75 if (req->kacount > 0 &&
76 req->keepalive == KA_ACTIVE && req->response_status < 500) {
77 char buf[22];
78 req_write(req, "Connection: Keep-Alive\r\nKeep-Alive: timeout=");
79 simple_itoa(ka_timeout, buf);
80 req_write(req, buf);
81 req_write(req, ", max=");
82 simple_itoa(req->kacount, buf);
83 req_write(req, buf);
84 req_write(req, "\r\n");
85 } else
86 req_write(req, "Connection: close\r\n");
87 }
88
89 extern char * version;
90
91 void print_http_headers(request * req)
92 {
93 char date_stuff[] = "Date: "
94 " "
95 "\r\n";
96
97 static char tls_version_stuff[64] = "\0";
98 static char version_stuff[] = "Server: "SERVER_VERSION"\r\n";
99
100 #ifdef ENABLE_SSL
101 if ( tls_version_stuff[0] == 0) {
102 strcpy( tls_version_stuff, "Server: "SERVER_VERSION" GnuTLS/");
103 strcat( tls_version_stuff, gnutls_check_version(NULL));
104 strcat( tls_version_stuff, "\r\n");
105 }
106 #endif
107
108 rfc822_time_buf(date_stuff + 6, 0);
109
110 req_write(req, date_stuff);
111
112 if (!req->secure)
113 req_write(req, version_stuff);
114 else
115 req_write(req, tls_version_stuff);
116
117 req_write(req, "Accept-Ranges: bytes\r\n");
118 print_ka_phrase(req);
119 }
120
121 /* The routines above are only called by the routines below.
122 * The rest of Boa only enters through the routines below.
123 */
124
125 /* R_REQUEST_OK: 200 */
126 void send_r_request_ok(request * req)
127 {
128 req->response_status = R_REQUEST_OK;
129 if (req->simple)
130 return;
131
132 req_write(req, "HTTP/1.0 200 OK\r\n");
133 print_http_headers(req);
134
135 if (!req->is_cgi) {
136 print_content_length(req);
137 print_last_modified(req);
138 print_content_type(req);
139 req_write(req, "\r\n");
140 }
141 }
142
143 /* R_REQUEST_PARTIAL: 206 */
144 void send_r_request_partial(request * req)
145 {
146 req->response_status = R_REQUEST_PARTIAL;
147 if (req->simple)
148 return;
149
150 req_write(req, "HTTP/1.0 206 Partial content\r\n");
151 print_http_headers(req);
152
153 if (!req->is_cgi) {
154 print_content_length(req);
155 print_content_range(req);
156 print_last_modified(req);
157 print_content_type(req);
158 req_write(req, "\r\n");
159 }
160 }
161
162 /* R_MOVED_PERM: 301 */
163 void send_r_moved_perm(request * req, char *url)
164 {
165 SQUASH_KA(req);
166 req->response_status = R_MOVED_PERM;
167 if (!req->simple) {
168 req_write(req, "HTTP/1.0 301 Moved Permanently\r\n");
169 print_http_headers(req);
170 req_write(req, "Content-Type: " HTML "\r\n");
171
172 req_write(req, "Location: ");
173 req_write_escape_http(req, url);
174 req_write(req, "\r\n\r\n");
175 }
176 if (req->method != M_HEAD) {
177 req_write(req,
178 "<HTML><HEAD><TITLE>301 Moved Permanently</TITLE></HEAD>\n"
179 "<BODY>\n<H1>301 Moved</H1>The document has moved\n"
180 "<A HREF=\"");
181 req_write_escape_html(req, url);
182 req_write(req, "\">here</A>.\n</BODY></HTML>\n");
183 }
184 req_flush(req);
185 }
186
187 /* R_MOVED_TEMP: 302 */
188 void send_r_moved_temp(request * req, char *url, char *more_hdr)
189 {
190 SQUASH_KA(req);
191 req->response_status = R_MOVED_TEMP;
192 if (!req->simple) {
193 req_write(req, "HTTP/1.0 302 Moved Temporarily\r\n");
194 print_http_headers(req);
195 req_write(req, "Content-Type: " HTML "\r\n");
196
197 req_write(req, "Location: ");
198 req_write_escape_http(req, url);
199 req_write(req, "\r\n");
200 req_write(req, more_hdr);
201 req_write(req, "\r\n\r\n");
202 }
203 if (req->method != M_HEAD) {
204 req_write(req,
205 "<HTML><HEAD><TITLE>302 Moved Temporarily</TITLE></HEAD>\n"
206 "<BODY>\n<H1>302 Moved</H1>The document has moved\n"
207 "<A HREF=\"");
208 req_write_escape_html(req, url);
209 req_write(req, "\">here</A>.\n</BODY></HTML>\n");
210 }
211 req_flush(req);
212 }
213
214 /* R_NOT_MODIFIED: 304 */
215 void send_r_not_modified(request * req)
216 {
217 SQUASH_KA(req);
218 req->response_status = R_NOT_MODIFIED;
219 req_write(req, "HTTP/1.0 304 Not Modified\r\n");
220 print_http_headers(req);
221 print_content_type(req);
222 req_write(req, "\r\n");
223 req_flush(req);
224 }
225
226 /* R_BAD_REQUEST: 400 */
227 void send_r_bad_request(request * req)
228 {
229 SQUASH_KA(req);
230 req->response_status = R_BAD_REQUEST;
231 if (!req->simple) {
232 req_write(req, "HTTP/1.0 400 Bad Request\r\n");
233 print_http_headers(req);
234 req_write(req, "Content-Type: " HTML "\r\n\r\n"); /* terminate header */
235 }
236 if (req->method != M_HEAD)
237 req_write(req,
238 "<HTML><HEAD><TITLE>400 Bad Request</TITLE></HEAD>\n"
239 "<BODY><H1>400 Bad Request</H1>\nYour client has issued "
240 "a malformed or illegal request.\n</BODY></HTML>\n");
241 req_flush(req);
242 }
243
244 /* R_UNAUTHORIZED: 401 */
245 void send_r_unauthorized(request * req, char *realm_name)
246 {
247 SQUASH_KA(req);
248 req->response_status = R_UNAUTHORIZED;
249 if (!req->simple) {
250 req_write(req, "HTTP/1.0 401 Unauthorized\r\n");
251 print_http_headers(req);
252 req_write(req, "WWW-Authenticate: Basic realm=\"");
253 req_write(req, realm_name);
254 req_write(req, "\"\r\n");
255 req_write(req, "Content-Type: " HTML "\r\n\r\n"); /* terminate header */
256 }
257 if (req->method != M_HEAD) {
258 req_write(req,
259 "<HTML><HEAD><TITLE>401 Unauthorized</TITLE></HEAD>\n"
260 "<BODY><H1>401 Unauthorized</H1>\nYour client does not "
261 "have permission to get URL ");
262 req_write_escape_html(req, req->request_uri);
263 req_write(req, " from this server.\n</BODY></HTML>\n");
264 }
265 req_flush(req);
266 }
267
268 /* R_FORBIDDEN: 403 */
269 void send_r_forbidden(request * req)
270 {
271 SQUASH_KA(req);
272 req->response_status = R_FORBIDDEN;
273 if (!req->simple) {
274 req_write(req, "HTTP/1.0 403 Forbidden\r\n");
275 print_http_headers(req);
276 req_write(req, "Content-Type: " HTML "\r\n\r\n"); /* terminate header */
277 }
278 if (req->method != M_HEAD) {
279 req_write(req, "<HTML><HEAD><TITLE>403 Forbidden</TITLE></HEAD>\n"
280 "<BODY><H1>403 Forbidden</H1>\nYour client does not "
281 "have permission to get URL ");
282 req_write_escape_html(req, req->request_uri);
283 req_write(req, " from this server.\n</BODY></HTML>\n");
284 }
285 req_flush(req);
286 }
287
288 /* R_NOT_FOUND: 404 */
289 void send_r_not_found(request * req)
290 {
291 SQUASH_KA(req);
292 req->response_status = R_NOT_FOUND;
293 if (!req->simple) {
294 req_write(req, "HTTP/1.0 404 Not Found\r\n");
295 print_http_headers(req);
296 req_write(req, "Content-Type: " HTML "\r\n\r\n"); /* terminate header */
297 }
298 if (req->method != M_HEAD) {
299 req_write(req, "<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>\n"
300 "<BODY><H1>404 Not Found</H1>\nThe requested URL ");
301 req_write_escape_html(req, req->request_uri);
302 req_write(req, " was not found on this server.\n</BODY></HTML>\n");
303 }
304 req_flush(req);
305 }
306
307 /* R_RANGE_UNSATISFIABLE: 416 */
308 void send_r_range_unsatisfiable(request * req)
309 {
310 req->response_status = R_RANGE_UNSATISFIABLE;
311 if (req->simple)
312 return;
313
314 if (!req->simple) {
315 req_write(req, "HTTP/1.0 416 Range Not Satisfiable\r\n");
316 print_http_headers(req);
317 req_write(req, "Content-Type: " HTML "\r\n\r\n"); /* terminate header */
318 }
319 if (req->method != M_HEAD) {
320 char int1[22], int2[22];
321 char range[45];
322 req_write(req, "<HTML><HEAD><TITLE>416 Range Not Satisfiable</TITLE></HEAD>\n"
323 "<BODY><H1>416 Range Not Satisfiable</H1>\nThe requested range URL ");
324 req_write_escape_html(req, req->request_uri);
325 req_write( req, " had illegal range( ");
326
327 simple_itoa( req->range_start, int1);
328 simple_itoa( req->range_stop, int2);
329 fprintf(stderr, "range: %d-%d\n", req->range_start, req->range_stop);
330 sprintf( range, "%s-%s", int1, int2);
331 req_write(req, range);
332 req_write(req, " ).\n</BODY></HTML>\n");
333 }
334 req_flush(req);
335 }
336
337
338 /* R_ERROR: 500 */
339 void send_r_error(request * req)
340 {
341 SQUASH_KA(req);
342 req->response_status = R_ERROR;
343 if (!req->simple) {
344 req_write(req, "HTTP/1.0 500 Server Error\r\n");
345 print_http_headers(req);
346 req_write(req, "Content-Type: " HTML "\r\n\r\n"); /* terminate header */
347 }
348 if (req->method != M_HEAD) {
349 req_write(req,
350 "<HTML><HEAD><TITLE>500 Server Error</TITLE></HEAD>\n"
351 "<BODY><H1>500 Server Error</H1>\nThe server encountered "
352 "an internal error and could not complete your request.\n"
353 "</BODY></HTML>\n");
354 }
355 req_flush(req);
356 }
357
358 /* R_NOT_IMP: 501 */
359 void send_r_not_implemented(request * req)
360 {
361 SQUASH_KA(req);
362 req->response_status = R_NOT_IMP;
363 if (!req->simple) {
364 req_write(req, "HTTP/1.0 501 Not Implemented\r\n");
365 print_http_headers(req);
366 req_write(req, "Content-Type: " HTML "\r\n\r\n"); /* terminate header */
367 }
368 if (req->method != M_HEAD) {
369 req_write(req,
370 "<HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD>\n"
371 "<BODY><H1>501 Not Implemented</H1>\nPOST to non-script "
372 "is not supported in Boa.\n</BODY></HTML>\n");
373 }
374 req_flush(req);
375 }
376
377 /* R_BAD_GATEWAY: 502 */
378 void send_r_bad_gateway(request * req)
379 {
380 SQUASH_KA(req);
381 req->response_status = R_BAD_GATEWAY;
382 if (!req->simple) {
383 req_write(req, "HTTP/1.0 502 Bad Gateway" CRLF);
384 print_http_headers(req);
385 req_write(req, "Content-Type: " HTML CRLF CRLF); /* terminate header */
386 }
387 if (req->method != M_HEAD) {
388 req_write(req,
389 "<HTML><HEAD><TITLE>502 Bad Gateway</TITLE></HEAD>\n"
390 "<BODY><H1>502 Bad Gateway</H1>\nThe CGI was "
391 "not CGI/1.1 compliant.\n" "</BODY></HTML>\n");
392 }
393 req_flush(req);
394 }
395
396 /* R_SERVICE_UNAVAILABLE: 503 */
397 void send_r_service_unavailable(request * req) /* 503 */
398 {
399 static const char body[] =
400 "<HTML><HEAD><TITLE>503 Service Unavailable</TITLE></HEAD>\n"
401 "<BODY><H1>503 Service Unavailable</H1>\n"
402 "There are too many connections in use right now.\r\n"
403 "Please try again later.\r\n</BODY></HTML>\n";
404 static int _body_len;
405 static char body_len[22];
406
407 if (!_body_len)
408 _body_len = strlen(body);
409 if (!body_len[0])
410 simple_itoa( _body_len, body_len);
411
412 SQUASH_KA(req);
413 req->response_status = R_SERVICE_UNAV;
414 if (!req->simple) {
415 req_write(req, "HTTP/1.0 503 Service Unavailable\r\n");
416 print_http_headers(req);
417 if (body_len) {
418 req_write(req, "Content-Length: ");
419 req_write(req, body_len);
420 req_write(req, "\r\n");
421 }
422 req_write(req, "Content-Type: " HTML "\r\n\r\n"); /* terminate header
423 */
424 }
425 if (req->method != M_HEAD) {
426 req_write(req, body);
427 }
428 req_flush(req);
429 }
430
431
432 /* R_NOT_IMP: 505 */
433 void send_r_bad_version(request * req)
434 {
435 SQUASH_KA(req);
436 req->response_status = R_BAD_VERSION;
437 if (!req->simple) {
438 req_write(req, "HTTP/1.0 505 HTTP Version Not Supported\r\n");
439 print_http_headers(req);
440 req_write(req, "Content-Type: " HTML "\r\n\r\n"); /* terminate header */
441 }
442 if (req->method != M_HEAD) {
443 req_write(req,
444 "<HTML><HEAD><TITLE>505 HTTP Version Not Supported</TITLE></HEAD>\n"
445 "<BODY><H1>505 HTTP Version Not Supported</H1>\nHTTP versions "
446 "other than 0.9 and 1.0 "
447 "are not supported in Boa.\n<p><p>Version encountered: ");
448 req_write(req, req->http_version);
449 req_write(req, "<p><p></BODY></HTML>\n");
450 }
451 req_flush(req);
452 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26