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

Contents of /hydra/src/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.15 - (show annotations)
Sun Oct 6 09:42:50 2002 UTC (21 years, 5 months ago) by nmav
Branch: MAIN
CVS Tags: hydra_0_0_10, hydra_0_0_8, hydra_0_0_9, hydra_0_0_7, hydra_0_1_1, hydra_0_1_0
Branch point for: hydra_0_1_0_patches
Changes since 1.14: +18 -2 lines
File MIME type: text/plain
The headers of HIC-CGIs are now parsed by the server.

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.14 2002/10/02 12:43:58 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_file_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 void send_r_request_cgi_status(request * req, char* status, char* desc)
145 {
146 req->response_status = R_REQUEST_OK;
147 if (req->simple)
148 return;
149
150 req_write(req, HTTP_VERSION" ");
151 req_write(req, status);
152 req_write(req, " ");
153 req_write(req, desc);
154 req_write(req, "\r\n");
155
156 if (!strcmp(status, "200")) print_http_headers(req);
157
158 }
159
160 /* R_REQUEST_PARTIAL: 206 */
161 void send_r_request_partial(request * req)
162 {
163 req->response_status = R_REQUEST_PARTIAL;
164 if (req->simple)
165 return;
166
167 req_write(req, HTTP_VERSION" 206 Partial content\r\n");
168 print_http_headers(req);
169
170 if (!req->is_cgi) {
171 print_content_length(req);
172 print_content_range(req);
173 print_last_modified(req);
174 print_content_type(req);
175 req_write(req, "\r\n");
176 }
177 }
178
179 /* R_MOVED_PERM: 301 */
180 void send_r_moved_perm(request * req, char *url)
181 {
182 SQUASH_KA(req);
183 req->response_status = R_MOVED_PERM;
184 if (!req->simple) {
185 req_write(req, HTTP_VERSION" 301 Moved Permanently\r\n");
186 print_http_headers(req);
187 req_write(req, "Content-Type: " TEXT_HTML "\r\n");
188
189 req_write(req, "Location: ");
190 req_write_escape_http(req, url);
191 req_write(req, "\r\n\r\n");
192 }
193 if (req->method != M_HEAD) {
194 req_write(req,
195 "<HTML><HEAD><TITLE>301 Moved Permanently</TITLE></HEAD>\n"
196 "<BODY>\n<H1>301 Moved</H1>The document has moved\n"
197 "<A HREF=\"");
198 req_write_escape_html(req, url);
199 req_write(req, "\">here</A>.\n</BODY></HTML>\n");
200 }
201 req_flush(req);
202 }
203
204 /* R_MOVED_TEMP: 302 */
205 void send_r_moved_temp(request * req, char *url, char *more_hdr)
206 {
207 SQUASH_KA(req);
208 req->response_status = R_MOVED_TEMP;
209 if (!req->simple) {
210 req_write(req, HTTP_VERSION" 302 Moved Temporarily\r\n");
211 print_http_headers(req);
212 req_write(req, "Content-Type: " TEXT_HTML "\r\n");
213
214 req_write(req, "Location: ");
215 req_write_escape_http(req, url);
216 req_write(req, "\r\n");
217 req_write(req, more_hdr);
218 req_write(req, "\r\n\r\n");
219 }
220 if (req->method != M_HEAD) {
221 req_write(req,
222 "<HTML><HEAD><TITLE>302 Moved Temporarily</TITLE></HEAD>\n"
223 "<BODY>\n<H1>302 Moved</H1>The document has moved\n"
224 "<A HREF=\"");
225 req_write_escape_html(req, url);
226 req_write(req, "\">here</A>.\n</BODY></HTML>\n");
227 }
228 req_flush(req);
229 }
230
231 /* R_NOT_MODIFIED: 304 */
232 void send_r_not_modified(request * req)
233 {
234 SQUASH_KA(req);
235 req->response_status = R_NOT_MODIFIED;
236 req_write(req, HTTP_VERSION" 304 Not Modified\r\n");
237 print_http_headers(req);
238 print_content_type(req);
239 print_etag(req);
240 req_write(req, "\r\n");
241 req_flush(req);
242 }
243
244 /* R_BAD_REQUEST: 400 */
245 void send_r_bad_request(request * req)
246 {
247 SQUASH_KA(req);
248 req->response_status = R_BAD_REQUEST;
249 if (!req->simple) {
250 req_write(req, HTTP_VERSION" 400 Bad Request\r\n");
251 print_http_headers(req);
252 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
253 }
254 if (req->method != M_HEAD)
255 req_write(req,
256 "<HTML><HEAD><TITLE>400 Bad Request</TITLE></HEAD>\n"
257 "<BODY><H1>400 Bad Request</H1>\nYour client has issued "
258 "a malformed or illegal request.\n</BODY></HTML>\n");
259 req_flush(req);
260 }
261
262 /* R_UNAUTHORIZED: 401 */
263 void send_r_unauthorized(request * req, char *realm_name)
264 {
265 SQUASH_KA(req);
266 req->response_status = R_UNAUTHORIZED;
267 if (!req->simple) {
268 req_write(req, HTTP_VERSION" 401 Unauthorized\r\n");
269 print_http_headers(req);
270 req_write(req, "WWW-Authenticate: Basic realm=\"");
271 req_write(req, realm_name);
272 req_write(req, "\"\r\n");
273 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
274 }
275 if (req->method != M_HEAD) {
276 req_write(req,
277 "<HTML><HEAD><TITLE>401 Unauthorized</TITLE></HEAD>\n"
278 "<BODY><H1>401 Unauthorized</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_FORBIDDEN: 403 */
287 void send_r_forbidden(request * req)
288 {
289 SQUASH_KA(req);
290 req->response_status = R_FORBIDDEN;
291 if (!req->simple) {
292 req_write(req, HTTP_VERSION" 403 Forbidden\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>403 Forbidden</TITLE></HEAD>\n"
298 "<BODY><H1>403 Forbidden</H1>\nYour client does not "
299 "have permission to get URL ");
300 req_write_escape_html(req, req->request_uri);
301 req_write(req, " from this server.\n</BODY></HTML>\n");
302 }
303 req_flush(req);
304 }
305
306 /* R_NOT_FOUND: 404 */
307 void send_r_not_found(request * req)
308 {
309 SQUASH_KA(req);
310 req->response_status = R_NOT_FOUND;
311 if (!req->simple) {
312 req_write(req, HTTP_VERSION" 404 Not Found\r\n");
313 print_http_headers(req);
314 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
315 }
316 if (req->method != M_HEAD) {
317 req_write(req, "<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>\n"
318 "<BODY><H1>404 Not Found</H1>\nThe requested URL ");
319 req_write_escape_html(req, req->request_uri);
320 req_write(req, " was not found on this server.\n</BODY></HTML>\n");
321 }
322 req_flush(req);
323 }
324
325 /* R_PRECONDITION_FAILED: 412 */
326 void send_r_precondition_failed(request * req)
327 {
328 req->response_status = R_PRECONDITION_FAILED;
329 if (req->simple)
330 return;
331
332 if (!req->simple) {
333 req_write(req, HTTP_VERSION" 412 Precondition Failed\r\n");
334 print_http_headers(req);
335 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
336 }
337 if (req->method != M_HEAD) {
338 req_write(req, "<HTML><HEAD><TITLE>412 Precondition Failed</TITLE></HEAD>\n"
339 "<BODY><H1>412 Precondition failed</H1>\n");
340
341 req_write(req, "</BODY></HTML>\n");
342 }
343 req_flush(req);
344 }
345
346 /* R_RANGE_UNSATISFIABLE: 416 */
347 void send_r_range_unsatisfiable(request * req)
348 {
349 req->response_status = R_RANGE_UNSATISFIABLE;
350 if (req->simple)
351 return;
352
353 if (!req->simple) {
354 req_write(req, HTTP_VERSION" 416 Range Not Satisfiable\r\n");
355 print_http_headers(req);
356 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
357 }
358 if (req->method != M_HEAD) {
359 char int1[22], int2[22];
360 char range[45];
361 req_write(req, "<HTML><HEAD><TITLE>416 Range Not Satisfiable</TITLE></HEAD>\n"
362 "<BODY><H1>416 Range Not Satisfiable</H1>\nThe requested range URL ");
363 req_write_escape_html(req, req->request_uri);
364 req_write( req, " had illegal range( ");
365
366 simple_itoa( req->range_start, int1);
367 simple_itoa( req->range_stop, int2);
368 sprintf( range, "%s-%s", int1, int2);
369 req_write(req, range);
370 req_write(req, " ).\n</BODY></HTML>\n");
371 }
372 req_flush(req);
373 }
374
375 /* R_ERROR: 500 */
376 void send_r_error(request * req)
377 {
378 SQUASH_KA(req);
379 req->response_status = R_ERROR;
380 if (!req->simple) {
381 req_write(req, HTTP_VERSION" 500 Server Error\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>500 Server Error</TITLE></HEAD>\n"
388 "<BODY><H1>500 Server Error</H1>\nThe server encountered "
389 "an internal error and could not complete your request.\n"
390 "</BODY></HTML>\n");
391 }
392 req_flush(req);
393 }
394
395 /* R_NOT_IMP: 501 */
396 void send_r_not_implemented(request * req)
397 {
398 SQUASH_KA(req);
399 req->response_status = R_NOT_IMP;
400 if (!req->simple) {
401 req_write(req, HTTP_VERSION" 501 Not Implemented\r\n");
402 print_http_headers(req);
403 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
404 }
405 if (req->method != M_HEAD) {
406 req_write(req,
407 "<HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD>\n"
408 "<BODY><H1>501 Not Implemented</H1>\nPOST to non-script "
409 "is not supported in Hydra.\n</BODY></HTML>\n");
410 }
411 req_flush(req);
412 }
413
414 /* R_BAD_GATEWAY: 502 */
415 void send_r_bad_gateway(request * req)
416 {
417 SQUASH_KA(req);
418 req->response_status = R_BAD_GATEWAY;
419 if (!req->simple) {
420 req_write(req, HTTP_VERSION" 502 Bad Gateway" CRLF);
421 print_http_headers(req);
422 req_write(req, "Content-Type: " TEXT_HTML CRLF CRLF); /* terminate header */
423 }
424 if (req->method != M_HEAD) {
425 req_write(req,
426 "<HTML><HEAD><TITLE>502 Bad Gateway</TITLE></HEAD>\n"
427 "<BODY><H1>502 Bad Gateway</H1>\nThe CGI was "
428 "not CGI/1.1 compliant.\n" "</BODY></HTML>\n");
429 }
430 req_flush(req);
431 }
432
433 /* R_SERVICE_UNAVAILABLE: 503 */
434 void send_r_service_unavailable(request * req) /* 503 */
435 {
436 static const char body[] =
437 "<HTML><HEAD><TITLE>503 Service Unavailable</TITLE></HEAD>\n"
438 "<BODY><H1>503 Service Unavailable</H1>\n"
439 "There are too many connections in use right now.\r\n"
440 "Please try again later.\r\n</BODY></HTML>\n";
441 static int _body_len;
442 static char body_len[22];
443
444 if (!_body_len)
445 _body_len = strlen(body);
446 if (!body_len[0])
447 simple_itoa( _body_len, body_len);
448
449 SQUASH_KA(req);
450 req->response_status = R_SERVICE_UNAV;
451 if (!req->simple) {
452 req_write(req, HTTP_VERSION" 503 Service Unavailable\r\n");
453 print_http_headers(req);
454 if (body_len) {
455 req_write(req, "Content-Length: ");
456 req_write(req, body_len);
457 req_write(req, "\r\n");
458 }
459 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header
460 */
461 }
462 if (req->method != M_HEAD) {
463 req_write(req, body);
464 }
465 req_flush(req);
466 }
467
468
469 /* R_NOT_IMP: 505 */
470 void send_r_bad_version(request * req)
471 {
472 SQUASH_KA(req);
473 req->response_status = R_BAD_VERSION;
474 if (!req->simple) {
475 req_write(req, HTTP_VERSION" 505 HTTP Version Not Supported\r\n");
476 print_http_headers(req);
477 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
478 }
479 if (req->method != M_HEAD) {
480 req_write(req,
481 "<HTML><HEAD><TITLE>505 HTTP Version Not Supported</TITLE></HEAD>\n"
482 "<BODY><H1>505 HTTP Version Not Supported</H1>\nHTTP versions "
483 "other than 0.9 and 1.0 "
484 "are not supported in Hydra.\n<p><p>Version encountered: ");
485 req_write(req, req->http_version);
486 req_write(req, "<p><p></BODY></HTML>\n");
487 }
488 req_flush(req);
489 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26