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

Contents of /hydra/src/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.10 - (show annotations)
Sun Sep 29 12:02:57 2002 UTC (21 years, 6 months ago) by nmav
Branch: MAIN
Changes since 1.9: +7 -6 lines
File MIME type: text/plain
Moved the ETag generation, to a function.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26