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

Annotation of /hydra/src/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.17 - (hide annotations)
Wed Jan 22 07:51:50 2003 UTC (21 years, 2 months ago) by nmav
Branch: MAIN
CVS Tags: hydra_0_1_6_without_hic, hydra_0_1_7, hydra_0_1_6, hydra_0_1_4, hydra_0_1_8, HEAD
Changes since 1.16: +419 -441 lines
File MIME type: text/plain
merged changes from 0.1.x branch.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26