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

Annotation of /hydra/src/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.14 - (hide annotations)
Wed Oct 2 12:43:58 2002 UTC (21 years, 6 months ago) by nmav
Branch: MAIN
CVS Tags: hydra_0_0_6
Changes since 1.13: +8 -4 lines
File MIME type: text/plain
some fixes

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26