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

Contents of /hydra/src/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.14 - (show annotations)
Wed Oct 2 12:43:58 2002 UTC (21 years, 6 months ago) by nmav
Branch: MAIN
CVS Tags: hydra_0_0_6
Changes since 1.13: +8 -4 lines
File MIME type: text/plain
some fixes

1 /*
2 * Hydra, 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.13 2002/09/30 18:18:52 nmav Exp $*/
24
25 #include "boa.h"
26
27 void print_content_type(request * req)
28 {
29 char * mime_type = get_mime_type(req->request_uri);
30
31 if (mime_type != NULL) {
32 req_write(req, "Content-Type: ");
33 req_write(req, mime_type);
34 req_write(req, "\r\n");
35 }
36 }
37
38 void print_content_length(request * req)
39 {
40 char buf[22];
41
42 simple_itoa( (req->range_stop)-(req->range_start), buf);
43 req_write(req, "Content-Length: ");
44 req_write(req, buf);
45 req_write(req, "\r\n");
46 }
47
48 void print_content_range(request * req)
49 {
50 char start[22];
51 char stop[22];
52 char total[22];
53 char buf[22*3 + 5];
54
55 req_write(req, "Content-Range: bytes ");
56
57 simple_itoa( req->range_stop, stop);
58 simple_itoa( req->range_start, start);
59 simple_itoa( req->filesize, total);
60
61 sprintf( buf, "%s-%s/%s\r\n", start, stop, total);
62 req_write(req, buf);
63 }
64
65 void print_last_modified(request * req)
66 {
67 char lm[] = "Last-Modified: "
68 " " "\r\n";
69 rfc822_time_buf(lm + 15, req->last_modified);
70 req_write(req, lm);
71 }
72
73 void print_etag(request * req)
74 {
75 char buffer[sizeof("ETag: \r\n") + MAX_ETAG_LENGTH + 1] = "ETag: ";
76 int len;
77
78 len = 6; /* after "Etag: " */
79 len += create_etag( req->filesize, req->last_modified, &buffer[len]);
80 memcpy( &buffer[len], "\r\n\0", 3);
81
82 req_write(req, buffer);
83 }
84
85 void print_ka_phrase(request * req)
86 {
87
88 if (req->kacount > 0 &&
89 req->keepalive == KA_ACTIVE && req->response_status < 500) {
90 char buf[22];
91 req_write(req, "Connection: Keep-Alive\r\nKeep-Alive: timeout=");
92 simple_itoa(ka_timeout, buf);
93 req_write(req, buf);
94 req_write(req, ", max=");
95 simple_itoa(req->kacount, buf);
96 req_write(req, buf);
97 req_write(req, "\r\n");
98 } else
99 req_write(req, "Connection: close\r\n");
100 }
101
102 void print_http_headers(request * req)
103 {
104 char date_stuff[] = "Date: "
105 " "
106 "\r\n";
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, boa_version);
114 else
115 req_write(req, boa_tls_version);
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 Hydra 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_VERSION" 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_etag(req);
139 print_content_type(req);
140 req_write(req, "\r\n");
141 }
142 }
143
144 /* R_REQUEST_PARTIAL: 206 */
145 void send_r_request_partial(request * req)
146 {
147 req->response_status = R_REQUEST_PARTIAL;
148 if (req->simple)
149 return;
150
151 req_write(req, HTTP_VERSION" 206 Partial content\r\n");
152 print_http_headers(req);
153
154 if (!req->is_cgi) {
155 print_content_length(req);
156 print_content_range(req);
157 print_last_modified(req);
158 print_content_type(req);
159 req_write(req, "\r\n");
160 }
161 }
162
163 /* R_MOVED_PERM: 301 */
164 void send_r_moved_perm(request * req, char *url)
165 {
166 SQUASH_KA(req);
167 req->response_status = R_MOVED_PERM;
168 if (!req->simple) {
169 req_write(req, HTTP_VERSION" 301 Moved Permanently\r\n");
170 print_http_headers(req);
171 req_write(req, "Content-Type: " TEXT_HTML "\r\n");
172
173 req_write(req, "Location: ");
174 req_write_escape_http(req, url);
175 req_write(req, "\r\n\r\n");
176 }
177 if (req->method != M_HEAD) {
178 req_write(req,
179 "<HTML><HEAD><TITLE>301 Moved Permanently</TITLE></HEAD>\n"
180 "<BODY>\n<H1>301 Moved</H1>The document has moved\n"
181 "<A HREF=\"");
182 req_write_escape_html(req, url);
183 req_write(req, "\">here</A>.\n</BODY></HTML>\n");
184 }
185 req_flush(req);
186 }
187
188 /* R_MOVED_TEMP: 302 */
189 void send_r_moved_temp(request * req, char *url, char *more_hdr)
190 {
191 SQUASH_KA(req);
192 req->response_status = R_MOVED_TEMP;
193 if (!req->simple) {
194 req_write(req, HTTP_VERSION" 302 Moved Temporarily\r\n");
195 print_http_headers(req);
196 req_write(req, "Content-Type: " TEXT_HTML "\r\n");
197
198 req_write(req, "Location: ");
199 req_write_escape_http(req, url);
200 req_write(req, "\r\n");
201 req_write(req, more_hdr);
202 req_write(req, "\r\n\r\n");
203 }
204 if (req->method != M_HEAD) {
205 req_write(req,
206 "<HTML><HEAD><TITLE>302 Moved Temporarily</TITLE></HEAD>\n"
207 "<BODY>\n<H1>302 Moved</H1>The document has moved\n"
208 "<A HREF=\"");
209 req_write_escape_html(req, url);
210 req_write(req, "\">here</A>.\n</BODY></HTML>\n");
211 }
212 req_flush(req);
213 }
214
215 /* R_NOT_MODIFIED: 304 */
216 void send_r_not_modified(request * req)
217 {
218 SQUASH_KA(req);
219 req->response_status = R_NOT_MODIFIED;
220 req_write(req, HTTP_VERSION" 304 Not Modified\r\n");
221 print_http_headers(req);
222 print_content_type(req);
223 print_etag(req);
224 req_write(req, "\r\n");
225 req_flush(req);
226 }
227
228 /* R_BAD_REQUEST: 400 */
229 void send_r_bad_request(request * req)
230 {
231 SQUASH_KA(req);
232 req->response_status = R_BAD_REQUEST;
233 if (!req->simple) {
234 req_write(req, HTTP_VERSION" 400 Bad Request\r\n");
235 print_http_headers(req);
236 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
237 }
238 if (req->method != M_HEAD)
239 req_write(req,
240 "<HTML><HEAD><TITLE>400 Bad Request</TITLE></HEAD>\n"
241 "<BODY><H1>400 Bad Request</H1>\nYour client has issued "
242 "a malformed or illegal request.\n</BODY></HTML>\n");
243 req_flush(req);
244 }
245
246 /* R_UNAUTHORIZED: 401 */
247 void send_r_unauthorized(request * req, char *realm_name)
248 {
249 SQUASH_KA(req);
250 req->response_status = R_UNAUTHORIZED;
251 if (!req->simple) {
252 req_write(req, HTTP_VERSION" 401 Unauthorized\r\n");
253 print_http_headers(req);
254 req_write(req, "WWW-Authenticate: Basic realm=\"");
255 req_write(req, realm_name);
256 req_write(req, "\"\r\n");
257 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
258 }
259 if (req->method != M_HEAD) {
260 req_write(req,
261 "<HTML><HEAD><TITLE>401 Unauthorized</TITLE></HEAD>\n"
262 "<BODY><H1>401 Unauthorized</H1>\nYour client does not "
263 "have permission to get URL ");
264 req_write_escape_html(req, req->request_uri);
265 req_write(req, " from this server.\n</BODY></HTML>\n");
266 }
267 req_flush(req);
268 }
269
270 /* R_FORBIDDEN: 403 */
271 void send_r_forbidden(request * req)
272 {
273 SQUASH_KA(req);
274 req->response_status = R_FORBIDDEN;
275 if (!req->simple) {
276 req_write(req, HTTP_VERSION" 403 Forbidden\r\n");
277 print_http_headers(req);
278 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
279 }
280 if (req->method != M_HEAD) {
281 req_write(req, "<HTML><HEAD><TITLE>403 Forbidden</TITLE></HEAD>\n"
282 "<BODY><H1>403 Forbidden</H1>\nYour client does not "
283 "have permission to get URL ");
284 req_write_escape_html(req, req->request_uri);
285 req_write(req, " from this server.\n</BODY></HTML>\n");
286 }
287 req_flush(req);
288 }
289
290 /* R_NOT_FOUND: 404 */
291 void send_r_not_found(request * req)
292 {
293 SQUASH_KA(req);
294 req->response_status = R_NOT_FOUND;
295 if (!req->simple) {
296 req_write(req, HTTP_VERSION" 404 Not Found\r\n");
297 print_http_headers(req);
298 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
299 }
300 if (req->method != M_HEAD) {
301 req_write(req, "<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>\n"
302 "<BODY><H1>404 Not Found</H1>\nThe requested URL ");
303 req_write_escape_html(req, req->request_uri);
304 req_write(req, " was not found on this server.\n</BODY></HTML>\n");
305 }
306 req_flush(req);
307 }
308
309 /* R_PRECONDITION_FAILED: 412 */
310 void send_r_precondition_failed(request * req)
311 {
312 req->response_status = R_PRECONDITION_FAILED;
313 if (req->simple)
314 return;
315
316 if (!req->simple) {
317 req_write(req, HTTP_VERSION" 412 Precondition Failed\r\n");
318 print_http_headers(req);
319 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
320 }
321 if (req->method != M_HEAD) {
322 req_write(req, "<HTML><HEAD><TITLE>412 Precondition Failed</TITLE></HEAD>\n"
323 "<BODY><H1>412 Precondition failed</H1>\n");
324
325 req_write(req, "</BODY></HTML>\n");
326 }
327 req_flush(req);
328 }
329
330 /* R_RANGE_UNSATISFIABLE: 416 */
331 void send_r_range_unsatisfiable(request * req)
332 {
333 req->response_status = R_RANGE_UNSATISFIABLE;
334 if (req->simple)
335 return;
336
337 if (!req->simple) {
338 req_write(req, HTTP_VERSION" 416 Range Not Satisfiable\r\n");
339 print_http_headers(req);
340 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
341 }
342 if (req->method != M_HEAD) {
343 char int1[22], int2[22];
344 char range[45];
345 req_write(req, "<HTML><HEAD><TITLE>416 Range Not Satisfiable</TITLE></HEAD>\n"
346 "<BODY><H1>416 Range Not Satisfiable</H1>\nThe requested range URL ");
347 req_write_escape_html(req, req->request_uri);
348 req_write( req, " had illegal range( ");
349
350 simple_itoa( req->range_start, int1);
351 simple_itoa( req->range_stop, int2);
352 sprintf( range, "%s-%s", int1, int2);
353 req_write(req, range);
354 req_write(req, " ).\n</BODY></HTML>\n");
355 }
356 req_flush(req);
357 }
358
359 /* R_ERROR: 500 */
360 void send_r_error(request * req)
361 {
362 SQUASH_KA(req);
363 req->response_status = R_ERROR;
364 if (!req->simple) {
365 req_write(req, HTTP_VERSION" 500 Server Error\r\n");
366 print_http_headers(req);
367 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
368 }
369 if (req->method != M_HEAD) {
370 req_write(req,
371 "<HTML><HEAD><TITLE>500 Server Error</TITLE></HEAD>\n"
372 "<BODY><H1>500 Server Error</H1>\nThe server encountered "
373 "an internal error and could not complete your request.\n"
374 "</BODY></HTML>\n");
375 }
376 req_flush(req);
377 }
378
379 /* R_NOT_IMP: 501 */
380 void send_r_not_implemented(request * req)
381 {
382 SQUASH_KA(req);
383 req->response_status = R_NOT_IMP;
384 if (!req->simple) {
385 req_write(req, HTTP_VERSION" 501 Not Implemented\r\n");
386 print_http_headers(req);
387 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
388 }
389 if (req->method != M_HEAD) {
390 req_write(req,
391 "<HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD>\n"
392 "<BODY><H1>501 Not Implemented</H1>\nPOST to non-script "
393 "is not supported in Hydra.\n</BODY></HTML>\n");
394 }
395 req_flush(req);
396 }
397
398 /* R_BAD_GATEWAY: 502 */
399 void send_r_bad_gateway(request * req)
400 {
401 SQUASH_KA(req);
402 req->response_status = R_BAD_GATEWAY;
403 if (!req->simple) {
404 req_write(req, HTTP_VERSION" 502 Bad Gateway" CRLF);
405 print_http_headers(req);
406 req_write(req, "Content-Type: " TEXT_HTML CRLF CRLF); /* terminate header */
407 }
408 if (req->method != M_HEAD) {
409 req_write(req,
410 "<HTML><HEAD><TITLE>502 Bad Gateway</TITLE></HEAD>\n"
411 "<BODY><H1>502 Bad Gateway</H1>\nThe CGI was "
412 "not CGI/1.1 compliant.\n" "</BODY></HTML>\n");
413 }
414 req_flush(req);
415 }
416
417 /* R_SERVICE_UNAVAILABLE: 503 */
418 void send_r_service_unavailable(request * req) /* 503 */
419 {
420 static const char body[] =
421 "<HTML><HEAD><TITLE>503 Service Unavailable</TITLE></HEAD>\n"
422 "<BODY><H1>503 Service Unavailable</H1>\n"
423 "There are too many connections in use right now.\r\n"
424 "Please try again later.\r\n</BODY></HTML>\n";
425 static int _body_len;
426 static char body_len[22];
427
428 if (!_body_len)
429 _body_len = strlen(body);
430 if (!body_len[0])
431 simple_itoa( _body_len, body_len);
432
433 SQUASH_KA(req);
434 req->response_status = R_SERVICE_UNAV;
435 if (!req->simple) {
436 req_write(req, HTTP_VERSION" 503 Service Unavailable\r\n");
437 print_http_headers(req);
438 if (body_len) {
439 req_write(req, "Content-Length: ");
440 req_write(req, body_len);
441 req_write(req, "\r\n");
442 }
443 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header
444 */
445 }
446 if (req->method != M_HEAD) {
447 req_write(req, body);
448 }
449 req_flush(req);
450 }
451
452
453 /* R_NOT_IMP: 505 */
454 void send_r_bad_version(request * req)
455 {
456 SQUASH_KA(req);
457 req->response_status = R_BAD_VERSION;
458 if (!req->simple) {
459 req_write(req, HTTP_VERSION" 505 HTTP Version Not Supported\r\n");
460 print_http_headers(req);
461 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
462 }
463 if (req->method != M_HEAD) {
464 req_write(req,
465 "<HTML><HEAD><TITLE>505 HTTP Version Not Supported</TITLE></HEAD>\n"
466 "<BODY><H1>505 HTTP Version Not Supported</H1>\nHTTP versions "
467 "other than 0.9 and 1.0 "
468 "are not supported in Hydra.\n<p><p>Version encountered: ");
469 req_write(req, req->http_version);
470 req_write(req, "<p><p></BODY></HTML>\n");
471 }
472 req_flush(req);
473 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26