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

Contents of /hydra/src/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.8 - (show annotations)
Sat Sep 28 16:32:37 2002 UTC (21 years, 6 months ago) by nmav
Branch: MAIN
CVS Tags: hydra_0_0_3
Changes since 1.7: +5 -5 lines
File MIME type: text/plain
In sighup and sigterm, the HIC thread is terminated as well.

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.7 2002/09/28 10:05:00 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_ka_phrase(request * req)
70 {
71
72 if (req->kacount > 0 &&
73 req->keepalive == KA_ACTIVE && req->response_status < 500) {
74 char buf[22];
75 req_write(req, "Connection: Keep-Alive\r\nKeep-Alive: timeout=");
76 simple_itoa(ka_timeout, buf);
77 req_write(req, buf);
78 req_write(req, ", max=");
79 simple_itoa(req->kacount, buf);
80 req_write(req, buf);
81 req_write(req, "\r\n");
82 } else
83 req_write(req, "Connection: close\r\n");
84 }
85
86 extern char * version;
87
88 void print_http_headers(request * req)
89 {
90 char date_stuff[] = "Date: "
91 " "
92 "\r\n";
93
94 static char tls_version_stuff[64] = "\0";
95 static char version_stuff[] = "Server: "SERVER_NAME"/"SERVER_VERSION"\r\n";
96
97 #ifdef ENABLE_SSL
98 if ( tls_version_stuff[0] == 0) {
99 strcpy( tls_version_stuff, "Server: "SERVER_NAME"/"SERVER_VERSION" GnuTLS/");
100 strcat( tls_version_stuff, gnutls_check_version(NULL));
101 strcat( tls_version_stuff, "\r\n");
102 }
103 #endif
104
105 rfc822_time_buf(date_stuff + 6, 0);
106
107 req_write(req, date_stuff);
108
109 if (!req->secure)
110 req_write(req, version_stuff);
111 else
112 req_write(req, tls_version_stuff);
113
114 req_write(req, "Accept-Ranges: bytes\r\n");
115 print_ka_phrase(req);
116 }
117
118 /* The routines above are only called by the routines below.
119 * The rest of Hydra only enters through the routines below.
120 */
121
122 /* R_REQUEST_OK: 200 */
123 void send_r_request_ok(request * req)
124 {
125 req->response_status = R_REQUEST_OK;
126 if (req->simple)
127 return;
128
129 req_write(req, HTTP_VERSION" 200 OK\r\n");
130 print_http_headers(req);
131
132 if (!req->is_cgi) {
133 print_content_length(req);
134 print_last_modified(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 req_write(req, "\r\n");
220 req_flush(req);
221 }
222
223 /* R_BAD_REQUEST: 400 */
224 void send_r_bad_request(request * req)
225 {
226 SQUASH_KA(req);
227 req->response_status = R_BAD_REQUEST;
228 if (!req->simple) {
229 req_write(req, HTTP_VERSION" 400 Bad Request\r\n");
230 print_http_headers(req);
231 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
232 }
233 if (req->method != M_HEAD)
234 req_write(req,
235 "<HTML><HEAD><TITLE>400 Bad Request</TITLE></HEAD>\n"
236 "<BODY><H1>400 Bad Request</H1>\nYour client has issued "
237 "a malformed or illegal request.\n</BODY></HTML>\n");
238 req_flush(req);
239 }
240
241 /* R_UNAUTHORIZED: 401 */
242 void send_r_unauthorized(request * req, char *realm_name)
243 {
244 SQUASH_KA(req);
245 req->response_status = R_UNAUTHORIZED;
246 if (!req->simple) {
247 req_write(req, HTTP_VERSION" 401 Unauthorized\r\n");
248 print_http_headers(req);
249 req_write(req, "WWW-Authenticate: Basic realm=\"");
250 req_write(req, realm_name);
251 req_write(req, "\"\r\n");
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>401 Unauthorized</TITLE></HEAD>\n"
257 "<BODY><H1>401 Unauthorized</H1>\nYour client does not "
258 "have permission to get URL ");
259 req_write_escape_html(req, req->request_uri);
260 req_write(req, " from this server.\n</BODY></HTML>\n");
261 }
262 req_flush(req);
263 }
264
265 /* R_FORBIDDEN: 403 */
266 void send_r_forbidden(request * req)
267 {
268 SQUASH_KA(req);
269 req->response_status = R_FORBIDDEN;
270 if (!req->simple) {
271 req_write(req, HTTP_VERSION" 403 Forbidden\r\n");
272 print_http_headers(req);
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, "<HTML><HEAD><TITLE>403 Forbidden</TITLE></HEAD>\n"
277 "<BODY><H1>403 Forbidden</H1>\nYour client does not "
278 "have permission to get URL ");
279 req_write_escape_html(req, req->request_uri);
280 req_write(req, " from this server.\n</BODY></HTML>\n");
281 }
282 req_flush(req);
283 }
284
285 /* R_NOT_FOUND: 404 */
286 void send_r_not_found(request * req)
287 {
288 SQUASH_KA(req);
289 req->response_status = R_NOT_FOUND;
290 if (!req->simple) {
291 req_write(req, HTTP_VERSION" 404 Not Found\r\n");
292 print_http_headers(req);
293 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
294 }
295 if (req->method != M_HEAD) {
296 req_write(req, "<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>\n"
297 "<BODY><H1>404 Not Found</H1>\nThe requested URL ");
298 req_write_escape_html(req, req->request_uri);
299 req_write(req, " was not found on this server.\n</BODY></HTML>\n");
300 }
301 req_flush(req);
302 }
303
304 /* R_RANGE_UNSATISFIABLE: 416 */
305 void send_r_range_unsatisfiable(request * req)
306 {
307 req->response_status = R_RANGE_UNSATISFIABLE;
308 if (req->simple)
309 return;
310
311 if (!req->simple) {
312 req_write(req, HTTP_VERSION" 416 Range Not Satisfiable\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 char int1[22], int2[22];
318 char range[45];
319 req_write(req, "<HTML><HEAD><TITLE>416 Range Not Satisfiable</TITLE></HEAD>\n"
320 "<BODY><H1>416 Range Not Satisfiable</H1>\nThe requested range URL ");
321 req_write_escape_html(req, req->request_uri);
322 req_write( req, " had illegal range( ");
323
324 simple_itoa( req->range_start, int1);
325 simple_itoa( req->range_stop, int2);
326 sprintf( range, "%s-%s", int1, int2);
327 req_write(req, range);
328 req_write(req, " ).\n</BODY></HTML>\n");
329 }
330 req_flush(req);
331 }
332
333
334 /* R_ERROR: 500 */
335 void send_r_error(request * req)
336 {
337 SQUASH_KA(req);
338 req->response_status = R_ERROR;
339 if (!req->simple) {
340 req_write(req, HTTP_VERSION" 500 Server Error\r\n");
341 print_http_headers(req);
342 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
343 }
344 if (req->method != M_HEAD) {
345 req_write(req,
346 "<HTML><HEAD><TITLE>500 Server Error</TITLE></HEAD>\n"
347 "<BODY><H1>500 Server Error</H1>\nThe server encountered "
348 "an internal error and could not complete your request.\n"
349 "</BODY></HTML>\n");
350 }
351 req_flush(req);
352 }
353
354 /* R_NOT_IMP: 501 */
355 void send_r_not_implemented(request * req)
356 {
357 SQUASH_KA(req);
358 req->response_status = R_NOT_IMP;
359 if (!req->simple) {
360 req_write(req, HTTP_VERSION" 501 Not Implemented\r\n");
361 print_http_headers(req);
362 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
363 }
364 if (req->method != M_HEAD) {
365 req_write(req,
366 "<HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD>\n"
367 "<BODY><H1>501 Not Implemented</H1>\nPOST to non-script "
368 "is not supported in Hydra.\n</BODY></HTML>\n");
369 }
370 req_flush(req);
371 }
372
373 /* R_BAD_GATEWAY: 502 */
374 void send_r_bad_gateway(request * req)
375 {
376 SQUASH_KA(req);
377 req->response_status = R_BAD_GATEWAY;
378 if (!req->simple) {
379 req_write(req, HTTP_VERSION" 502 Bad Gateway" CRLF);
380 print_http_headers(req);
381 req_write(req, "Content-Type: " TEXT_HTML CRLF CRLF); /* terminate header */
382 }
383 if (req->method != M_HEAD) {
384 req_write(req,
385 "<HTML><HEAD><TITLE>502 Bad Gateway</TITLE></HEAD>\n"
386 "<BODY><H1>502 Bad Gateway</H1>\nThe CGI was "
387 "not CGI/1.1 compliant.\n" "</BODY></HTML>\n");
388 }
389 req_flush(req);
390 }
391
392 /* R_SERVICE_UNAVAILABLE: 503 */
393 void send_r_service_unavailable(request * req) /* 503 */
394 {
395 static const char body[] =
396 "<HTML><HEAD><TITLE>503 Service Unavailable</TITLE></HEAD>\n"
397 "<BODY><H1>503 Service Unavailable</H1>\n"
398 "There are too many connections in use right now.\r\n"
399 "Please try again later.\r\n</BODY></HTML>\n";
400 static int _body_len;
401 static char body_len[22];
402
403 if (!_body_len)
404 _body_len = strlen(body);
405 if (!body_len[0])
406 simple_itoa( _body_len, body_len);
407
408 SQUASH_KA(req);
409 req->response_status = R_SERVICE_UNAV;
410 if (!req->simple) {
411 req_write(req, HTTP_VERSION" 503 Service Unavailable\r\n");
412 print_http_headers(req);
413 if (body_len) {
414 req_write(req, "Content-Length: ");
415 req_write(req, body_len);
416 req_write(req, "\r\n");
417 }
418 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header
419 */
420 }
421 if (req->method != M_HEAD) {
422 req_write(req, body);
423 }
424 req_flush(req);
425 }
426
427
428 /* R_NOT_IMP: 505 */
429 void send_r_bad_version(request * req)
430 {
431 SQUASH_KA(req);
432 req->response_status = R_BAD_VERSION;
433 if (!req->simple) {
434 req_write(req, HTTP_VERSION" 505 HTTP Version Not Supported\r\n");
435 print_http_headers(req);
436 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
437 }
438 if (req->method != M_HEAD) {
439 req_write(req,
440 "<HTML><HEAD><TITLE>505 HTTP Version Not Supported</TITLE></HEAD>\n"
441 "<BODY><H1>505 HTTP Version Not Supported</H1>\nHTTP versions "
442 "other than 0.9 and 1.0 "
443 "are not supported in Hydra.\n<p><p>Version encountered: ");
444 req_write(req, req->http_version);
445 req_write(req, "<p><p></BODY></HTML>\n");
446 }
447 req_flush(req);
448 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26