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

Contents of /hydra/src/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.12 - (show annotations)
Mon Sep 30 17:16:54 2002 UTC (21 years, 6 months ago) by nmav
Branch: MAIN
Changes since 1.11: +4 -17 lines
File MIME type: text/plain
Added support for multiple HIC threads.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26