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

Contents of /hydra/src/cgi_header.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.4.2.2 - (show annotations)
Sun Jan 19 17:39:10 2003 UTC (21 years, 2 months ago) by nmav
Branch: hydra_0_1_0_patches
CVS Tags: hydra_0_1_3
Changes since 1.4.2.1: +0 -1 lines
File MIME type: text/plain
The return of two mutexes.
Two mutexes are used in accept to allow parallel accepts
of SSL and plain connections.

1 /*
2 * Hydra, an http server
3 * cgi_header.c - cgi header parsing and control
4 * Copyright (C) 1997-99 Jon Nelson <jnelson@boa.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 1, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 */
21
22 #include "boa.h"
23
24 /* process_cgi_header
25
26 * returns 0 -=> error or HEAD, close down.
27 * returns 1 -=> done processing
28 * leaves req->cgi_status as WRITE
29 */
30
31 /*
32 The server MUST also resolve any conflicts between header fields returned by
33 the script and header fields that it would otherwise send itself.
34
35 ...
36
37 At least one CGI-Field MUST be supplied, but no CGI field name may be used
38 more than once in a response. If a body is supplied, then a
39 "Content-type" header field MUST be supplied by the script,
40 otherwise the script MUST send a "Location" or "Status" header
41 field. If a Location CGI-Field is returned, then the script
42 MUST NOT supply any HTTP-Fields.
43 */
44
45 /* TODO:
46 We still need to cycle through the data before the end of the headers,
47 line-by-line, and check for any problems with the CGI
48 outputting overriding http responses, etc...
49 */
50 int process_cgi_header(request * req)
51 {
52 char *buf;
53 char *c;
54
55 if (req->cgi_status != CGI_DONE)
56 req->cgi_status = CGI_BUFFER;
57
58 buf = req->header_line;
59
60 c = strstr(buf, "\n\r\n");
61 if (c == NULL) {
62 c = strstr(buf, "\n\n");
63 if (c == NULL) {
64 log_error_time();
65 fputs("cgi_header: unable to find LFLF\n", stderr);
66 #ifdef FASCIST_LOGGING
67 log_error_time();
68 fprintf(stderr, "\"%s\"\n", buf);
69 #endif
70 send_r_bad_gateway(req);
71 return 0;
72 }
73 }
74 if (req->http_version == HTTP_0_9) {
75 if (*(c + 1) == '\r')
76 req->header_line = c + 2;
77 else
78 req->header_line = c + 1;
79 return 1;
80 }
81 if (!strncasecmp(buf, "Location: ", 10)) { /* got a location header */
82 #ifdef FASCIST_LOGGING
83
84 log_error_time();
85 fprintf(stderr, "%s:%d - found Location header \"%s\"\n",
86 __FILE__, __LINE__, buf + 10);
87 #endif
88
89
90 if (buf[10] == '/') { /* virtual path */
91 log_error_time();
92 fprintf(stderr,
93 "server does not support internal redirection: " \
94 "\"%s\"\n", buf + 10);
95 send_r_bad_request(req);
96
97 /*
98 * We (I, Jon) have declined to support absolute-path parsing
99 * because I see it as a major security hole.
100 * Location: /etc/passwd or Location: /etc/shadow is not funny.
101 *
102 * Also, the below code is borked.
103 * request_uri could contain /cgi-bin/bob/extra_path
104 */
105
106 /*
107 strcpy(req->request_uri, buf + 10);
108 return internal_redirect(req);
109 */
110 } else { /* URL */
111 char *c2;
112 c2 = strchr(buf + 10, '\n');
113 /* c2 cannot ever equal NULL here because we already have found one */
114
115 --c2;
116 while (*c2 == '\r')
117 --c2;
118 ++c2;
119 /* c2 now points to a '\r' or the '\n' */
120 *c2++ = '\0'; /* end header */
121
122 /* first next header, or is at req->header_end */
123 while ((*c2 == '\n' || *c2 == '\r') && c2 < req->header_end)
124 ++c2;
125 if (c2 == req->header_end)
126 send_r_moved_temp(req, buf + 10, "");
127 else
128 send_r_moved_temp(req, buf + 10, c2);
129 }
130 req->status = DONE;
131 return 1;
132 } else { /* not location */
133 char *dest;
134 int howmuch;
135
136 if (!strncasecmp(buf, "Status: ", 8)) {
137 char str_status[4];
138 char desc[32];
139 int len;
140 char *p = buf+8;
141
142 len = 0;
143 while( *p != ' ' && *p != 0) { len++; p++; }
144
145 if (len > 3) { /* status code too long! */
146 req->buffer_start = req->buffer_end = 0;
147 send_r_error(req);
148 return 0;
149 }
150 memcpy( str_status, buf+8, 3);
151 str_status[3] = 0;
152
153 len = 0;
154 if (*p == ' ') p++;
155 while( (*p != '\r') && *p != 0) { len++; p++; }
156
157 if (len > sizeof(desc)-1) { /* description long! */
158 req->buffer_start = req->buffer_end = 0;
159 send_r_error(req);
160 return 0;
161 }
162
163 memcpy( desc, p-len, len);
164 desc[len] = 0;
165
166 send_r_request_cgi_status(req, str_status, desc); /* does not terminate */
167
168 if (*p=='\r' && *(p+1)=='\n')
169 p+=2; /* skip \r\n and move to the next line */
170
171 req->header_line = p;
172 } else {
173 send_r_request_cgi_status(req, "200", "OK"); /* does not terminate */
174 }
175
176 /* got to do special things because
177 a) we have a single buffer divided into 2 pieces
178 b) we need to merge those pieces
179 Easiest way is to memmove the cgi data backward until
180 it touches the buffered data, then reset the cgi data pointers
181 */
182 dest = req->buffer + req->buffer_end;
183 if (req->method == M_HEAD) {
184 if (*(c + 1) == '\r')
185 req->header_end = c + 2;
186 else
187 req->header_end = c + 1;
188 req->cgi_status = CGI_DONE;
189 }
190 howmuch = req->header_end - req->header_line;
191
192 if (dest + howmuch > req->buffer + BUFFER_SIZE) {
193 /* big problem */
194 log_error_time();
195 fprintf(stderr, "Too much data to move! Aborting! %s %d\n",
196 __FILE__, __LINE__);
197 /* reset buffer pointers because we already called
198 send_r_request_ok... */
199 req->buffer_start = req->buffer_end = 0;
200 send_r_error(req);
201 return 0;
202 }
203 memmove(dest, req->header_line, howmuch);
204 req->buffer_end += howmuch;
205 req->header_line = req->buffer + req->buffer_end;
206 req->header_end = req->header_line;
207 req_flush(req);
208
209 if (req->method == M_HEAD)
210 return 0;
211 }
212 return 1;
213 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26