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

Annotation of /hydra/src/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (hide annotations)
Mon Sep 23 12:48:59 2002 UTC (21 years, 6 months ago) by nmav
Branch: MAIN
CVS Tags: BOAS_WITH_RANGES_AND_CGI
Changes since 1.2: +71 -3 lines
File MIME type: text/plain
Added limited support for HTTP/1.1 ranges.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26