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

Annotation of /hydra/src/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.12 - (hide annotations)
Mon Sep 30 17:16:54 2002 UTC (21 years, 6 months ago) by nmav
Branch: MAIN
Changes since 1.11: +4 -17 lines
File MIME type: text/plain
Added support for multiple HIC threads.

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.12 /* $Id: response.c,v 1.11 2002/09/29 15:34:23 nmav Exp $*/
24 nmav 1.1
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 nmav 1.2 char buf[22];
37 nmav 1.3
38     simple_itoa( (req->range_stop)-(req->range_start), buf);
39 nmav 1.1 req_write(req, "Content-Length: ");
40 nmav 1.2 req_write(req, buf);
41 nmav 1.1 req_write(req, "\r\n");
42     }
43    
44 nmav 1.3 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 nmav 1.1 void print_last_modified(request * req)
62     {
63 nmav 1.2 char lm[] = "Last-Modified: "
64 nmav 1.1 " " "\r\n";
65     rfc822_time_buf(lm + 15, req->last_modified);
66     req_write(req, lm);
67     }
68    
69 nmav 1.9 void print_etag(request * req)
70     {
71 nmav 1.10 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 nmav 1.9
78     req_write(req, buffer);
79     }
80    
81 nmav 1.1 void print_ka_phrase(request * req)
82     {
83 nmav 1.2
84 nmav 1.1 if (req->kacount > 0 &&
85     req->keepalive == KA_ACTIVE && req->response_status < 500) {
86 nmav 1.2 char buf[22];
87 nmav 1.1 req_write(req, "Connection: Keep-Alive\r\nKeep-Alive: timeout=");
88 nmav 1.2 simple_itoa(ka_timeout, buf);
89     req_write(req, buf);
90 nmav 1.1 req_write(req, ", max=");
91 nmav 1.2 simple_itoa(req->kacount, buf);
92     req_write(req, buf);
93 nmav 1.1 req_write(req, "\r\n");
94     } else
95     req_write(req, "Connection: close\r\n");
96     }
97    
98     void print_http_headers(request * req)
99     {
100 nmav 1.2 char date_stuff[] = "Date: "
101 nmav 1.1 " "
102     "\r\n";
103    
104     rfc822_time_buf(date_stuff + 6, 0);
105    
106     req_write(req, date_stuff);
107    
108     if (!req->secure)
109 nmav 1.12 req_write(req, boa_version);
110 nmav 1.1 else
111 nmav 1.12 req_write(req, boa_tls_version);
112 nmav 1.1
113 nmav 1.12 req_write(req, "\r\nAccept-Ranges: bytes\r\n");
114 nmav 1.1 print_ka_phrase(req);
115     }
116    
117     /* The routines above are only called by the routines below.
118 nmav 1.8 * The rest of Hydra only enters through the routines below.
119 nmav 1.1 */
120    
121     /* R_REQUEST_OK: 200 */
122     void send_r_request_ok(request * req)
123     {
124     req->response_status = R_REQUEST_OK;
125     if (req->simple)
126     return;
127    
128 nmav 1.6 req_write(req, HTTP_VERSION" 200 OK\r\n");
129 nmav 1.1 print_http_headers(req);
130    
131     if (!req->is_cgi) {
132     print_content_length(req);
133     print_last_modified(req);
134 nmav 1.9 print_etag(req);
135 nmav 1.1 print_content_type(req);
136     req_write(req, "\r\n");
137     }
138     }
139    
140 nmav 1.3 /* 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 nmav 1.6 req_write(req, HTTP_VERSION" 206 Partial content\r\n");
148 nmav 1.3 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 nmav 1.1 /* 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 nmav 1.6 req_write(req, HTTP_VERSION" 301 Moved Permanently\r\n");
166 nmav 1.1 print_http_headers(req);
167 nmav 1.6 req_write(req, "Content-Type: " TEXT_HTML "\r\n");
168 nmav 1.1
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 nmav 1.6 req_write(req, HTTP_VERSION" 302 Moved Temporarily\r\n");
191 nmav 1.1 print_http_headers(req);
192 nmav 1.6 req_write(req, "Content-Type: " TEXT_HTML "\r\n");
193 nmav 1.1
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 nmav 1.6 req_write(req, HTTP_VERSION" 304 Not Modified\r\n");
217 nmav 1.1 print_http_headers(req);
218     print_content_type(req);
219 nmav 1.11 print_etag(req);
220 nmav 1.1 req_write(req, "\r\n");
221     req_flush(req);
222     }
223    
224     /* R_BAD_REQUEST: 400 */
225     void send_r_bad_request(request * req)
226     {
227     SQUASH_KA(req);
228     req->response_status = R_BAD_REQUEST;
229     if (!req->simple) {
230 nmav 1.6 req_write(req, HTTP_VERSION" 400 Bad Request\r\n");
231 nmav 1.1 print_http_headers(req);
232 nmav 1.6 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
233 nmav 1.1 }
234     if (req->method != M_HEAD)
235     req_write(req,
236     "<HTML><HEAD><TITLE>400 Bad Request</TITLE></HEAD>\n"
237     "<BODY><H1>400 Bad Request</H1>\nYour client has issued "
238     "a malformed or illegal request.\n</BODY></HTML>\n");
239     req_flush(req);
240     }
241    
242     /* R_UNAUTHORIZED: 401 */
243     void send_r_unauthorized(request * req, char *realm_name)
244     {
245     SQUASH_KA(req);
246     req->response_status = R_UNAUTHORIZED;
247     if (!req->simple) {
248 nmav 1.6 req_write(req, HTTP_VERSION" 401 Unauthorized\r\n");
249 nmav 1.1 print_http_headers(req);
250     req_write(req, "WWW-Authenticate: Basic realm=\"");
251     req_write(req, realm_name);
252     req_write(req, "\"\r\n");
253 nmav 1.6 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
254 nmav 1.1 }
255     if (req->method != M_HEAD) {
256     req_write(req,
257     "<HTML><HEAD><TITLE>401 Unauthorized</TITLE></HEAD>\n"
258     "<BODY><H1>401 Unauthorized</H1>\nYour client does not "
259     "have permission to get URL ");
260     req_write_escape_html(req, req->request_uri);
261     req_write(req, " from this server.\n</BODY></HTML>\n");
262     }
263     req_flush(req);
264     }
265    
266     /* R_FORBIDDEN: 403 */
267     void send_r_forbidden(request * req)
268     {
269     SQUASH_KA(req);
270     req->response_status = R_FORBIDDEN;
271     if (!req->simple) {
272 nmav 1.6 req_write(req, HTTP_VERSION" 403 Forbidden\r\n");
273 nmav 1.1 print_http_headers(req);
274 nmav 1.6 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
275 nmav 1.1 }
276     if (req->method != M_HEAD) {
277     req_write(req, "<HTML><HEAD><TITLE>403 Forbidden</TITLE></HEAD>\n"
278     "<BODY><H1>403 Forbidden</H1>\nYour client does not "
279     "have permission to get URL ");
280     req_write_escape_html(req, req->request_uri);
281     req_write(req, " from this server.\n</BODY></HTML>\n");
282     }
283     req_flush(req);
284     }
285    
286     /* R_NOT_FOUND: 404 */
287     void send_r_not_found(request * req)
288     {
289     SQUASH_KA(req);
290     req->response_status = R_NOT_FOUND;
291     if (!req->simple) {
292 nmav 1.6 req_write(req, HTTP_VERSION" 404 Not Found\r\n");
293 nmav 1.1 print_http_headers(req);
294 nmav 1.6 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
295 nmav 1.1 }
296     if (req->method != M_HEAD) {
297     req_write(req, "<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>\n"
298     "<BODY><H1>404 Not Found</H1>\nThe requested URL ");
299     req_write_escape_html(req, req->request_uri);
300     req_write(req, " was not found on this server.\n</BODY></HTML>\n");
301     }
302     req_flush(req);
303     }
304 nmav 1.3
305 nmav 1.9 /* R_PRECONDITION_FAILED: 412 */
306     void send_r_precondition_failed(request * req)
307     {
308     req->response_status = R_PRECONDITION_FAILED;
309     if (req->simple)
310     return;
311    
312     if (!req->simple) {
313     req_write(req, HTTP_VERSION" 412 Precondition Failed\r\n");
314     print_http_headers(req);
315     req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
316     }
317     if (req->method != M_HEAD) {
318     req_write(req, "<HTML><HEAD><TITLE>412 Precondition Failed</TITLE></HEAD>\n"
319     "<BODY><H1>412 Precondition failed</H1>\n");
320    
321     req_write(req, "</BODY></HTML>\n");
322     }
323     req_flush(req);
324     }
325    
326 nmav 1.3 /* R_RANGE_UNSATISFIABLE: 416 */
327     void send_r_range_unsatisfiable(request * req)
328     {
329     req->response_status = R_RANGE_UNSATISFIABLE;
330     if (req->simple)
331     return;
332    
333     if (!req->simple) {
334 nmav 1.6 req_write(req, HTTP_VERSION" 416 Range Not Satisfiable\r\n");
335 nmav 1.3 print_http_headers(req);
336 nmav 1.6 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
337 nmav 1.3 }
338     if (req->method != M_HEAD) {
339     char int1[22], int2[22];
340     char range[45];
341     req_write(req, "<HTML><HEAD><TITLE>416 Range Not Satisfiable</TITLE></HEAD>\n"
342     "<BODY><H1>416 Range Not Satisfiable</H1>\nThe requested range URL ");
343     req_write_escape_html(req, req->request_uri);
344     req_write( req, " had illegal range( ");
345    
346     simple_itoa( req->range_start, int1);
347     simple_itoa( req->range_stop, int2);
348     sprintf( range, "%s-%s", int1, int2);
349     req_write(req, range);
350     req_write(req, " ).\n</BODY></HTML>\n");
351     }
352     req_flush(req);
353     }
354 nmav 1.1
355     /* R_ERROR: 500 */
356     void send_r_error(request * req)
357     {
358     SQUASH_KA(req);
359     req->response_status = R_ERROR;
360     if (!req->simple) {
361 nmav 1.6 req_write(req, HTTP_VERSION" 500 Server Error\r\n");
362 nmav 1.1 print_http_headers(req);
363 nmav 1.6 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
364 nmav 1.1 }
365     if (req->method != M_HEAD) {
366     req_write(req,
367     "<HTML><HEAD><TITLE>500 Server Error</TITLE></HEAD>\n"
368     "<BODY><H1>500 Server Error</H1>\nThe server encountered "
369     "an internal error and could not complete your request.\n"
370     "</BODY></HTML>\n");
371     }
372     req_flush(req);
373     }
374    
375     /* R_NOT_IMP: 501 */
376     void send_r_not_implemented(request * req)
377     {
378     SQUASH_KA(req);
379     req->response_status = R_NOT_IMP;
380     if (!req->simple) {
381 nmav 1.6 req_write(req, HTTP_VERSION" 501 Not Implemented\r\n");
382 nmav 1.1 print_http_headers(req);
383 nmav 1.6 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
384 nmav 1.1 }
385     if (req->method != M_HEAD) {
386     req_write(req,
387     "<HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD>\n"
388     "<BODY><H1>501 Not Implemented</H1>\nPOST to non-script "
389 nmav 1.8 "is not supported in Hydra.\n</BODY></HTML>\n");
390 nmav 1.1 }
391     req_flush(req);
392     }
393    
394     /* R_BAD_GATEWAY: 502 */
395     void send_r_bad_gateway(request * req)
396     {
397     SQUASH_KA(req);
398     req->response_status = R_BAD_GATEWAY;
399     if (!req->simple) {
400 nmav 1.6 req_write(req, HTTP_VERSION" 502 Bad Gateway" CRLF);
401 nmav 1.1 print_http_headers(req);
402 nmav 1.6 req_write(req, "Content-Type: " TEXT_HTML CRLF CRLF); /* terminate header */
403 nmav 1.1 }
404     if (req->method != M_HEAD) {
405     req_write(req,
406     "<HTML><HEAD><TITLE>502 Bad Gateway</TITLE></HEAD>\n"
407     "<BODY><H1>502 Bad Gateway</H1>\nThe CGI was "
408     "not CGI/1.1 compliant.\n" "</BODY></HTML>\n");
409     }
410     req_flush(req);
411     }
412    
413     /* R_SERVICE_UNAVAILABLE: 503 */
414     void send_r_service_unavailable(request * req) /* 503 */
415     {
416 nmav 1.2 static const char body[] =
417 nmav 1.1 "<HTML><HEAD><TITLE>503 Service Unavailable</TITLE></HEAD>\n"
418     "<BODY><H1>503 Service Unavailable</H1>\n"
419     "There are too many connections in use right now.\r\n"
420     "Please try again later.\r\n</BODY></HTML>\n";
421     static int _body_len;
422 nmav 1.2 static char body_len[22];
423 nmav 1.1
424     if (!_body_len)
425     _body_len = strlen(body);
426 nmav 1.2 if (!body_len[0])
427     simple_itoa( _body_len, body_len);
428 nmav 1.1
429     SQUASH_KA(req);
430     req->response_status = R_SERVICE_UNAV;
431     if (!req->simple) {
432 nmav 1.6 req_write(req, HTTP_VERSION" 503 Service Unavailable\r\n");
433 nmav 1.1 print_http_headers(req);
434     if (body_len) {
435     req_write(req, "Content-Length: ");
436     req_write(req, body_len);
437     req_write(req, "\r\n");
438     }
439 nmav 1.6 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header
440 nmav 1.1 */
441     }
442     if (req->method != M_HEAD) {
443     req_write(req, body);
444     }
445     req_flush(req);
446     }
447    
448    
449     /* R_NOT_IMP: 505 */
450     void send_r_bad_version(request * req)
451     {
452     SQUASH_KA(req);
453     req->response_status = R_BAD_VERSION;
454     if (!req->simple) {
455 nmav 1.6 req_write(req, HTTP_VERSION" 505 HTTP Version Not Supported\r\n");
456 nmav 1.1 print_http_headers(req);
457 nmav 1.6 req_write(req, "Content-Type: " TEXT_HTML "\r\n\r\n"); /* terminate header */
458 nmav 1.1 }
459     if (req->method != M_HEAD) {
460     req_write(req,
461     "<HTML><HEAD><TITLE>505 HTTP Version Not Supported</TITLE></HEAD>\n"
462     "<BODY><H1>505 HTTP Version Not Supported</H1>\nHTTP versions "
463     "other than 0.9 and 1.0 "
464 nmav 1.8 "are not supported in Hydra.\n<p><p>Version encountered: ");
465 nmav 1.1 req_write(req, req->http_version);
466     req_write(req, "<p><p></BODY></HTML>\n");
467     }
468     req_flush(req);
469     }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26