/[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 - (show annotations)
Sun Oct 6 09:42:50 2002 UTC (21 years, 6 months ago) by nmav
Branch: MAIN
CVS Tags: hydra_0_0_10, hydra_0_0_8, hydra_0_0_9, hydra_0_0_7, hydra_0_1_2, hydra_0_1_1, hydra_0_1_0
Branch point for: hydra_0_1_0_patches
Changes since 1.3: +44 -6 lines
File MIME type: text/plain
The headers of HIC-CGIs are now parsed by the server.

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
51 int process_cgi_header(request * req)
52 {
53 char *buf;
54 char *c;
55
56 if (req->cgi_status != CGI_DONE)
57 req->cgi_status = CGI_BUFFER;
58
59 buf = req->header_line;
60
61 c = strstr(buf, "\n\r\n");
62 if (c == NULL) {
63 c = strstr(buf, "\n\n");
64 if (c == NULL) {
65 log_error_time();
66 fputs("cgi_header: unable to find LFLF\n", stderr);
67 #ifdef FASCIST_LOGGING
68 log_error_time();
69 fprintf(stderr, "\"%s\"\n", buf);
70 #endif
71 send_r_bad_gateway(req);
72 return 0;
73 }
74 }
75 if (req->simple) {
76 if (*(c + 1) == '\r')
77 req->header_line = c + 2;
78 else
79 req->header_line = c + 1;
80 return 1;
81 }
82 if (!strncasecmp(buf, "Location: ", 10)) { /* got a location header */
83 #ifdef FASCIST_LOGGING
84
85 log_error_time();
86 fprintf(stderr, "%s:%d - found Location header \"%s\"\n",
87 __FILE__, __LINE__, buf + 10);
88 #endif
89
90
91 if (buf[10] == '/') { /* virtual path */
92 log_error_time();
93 fprintf(stderr,
94 "server does not support internal redirection: " \
95 "\"%s\"\n", buf + 10);
96 send_r_bad_request(req);
97
98 /*
99 * We (I, Jon) have declined to support absolute-path parsing
100 * because I see it as a major security hole.
101 * Location: /etc/passwd or Location: /etc/shadow is not funny.
102 *
103 * Also, the below code is borked.
104 * request_uri could contain /cgi-bin/bob/extra_path
105 */
106
107 /*
108 strcpy(req->request_uri, buf + 10);
109 return internal_redirect(req);
110 */
111 } else { /* URL */
112 char *c2;
113 c2 = strchr(buf + 10, '\n');
114 /* c2 cannot ever equal NULL here because we already have found one */
115
116 --c2;
117 while (*c2 == '\r')
118 --c2;
119 ++c2;
120 /* c2 now points to a '\r' or the '\n' */
121 *c2++ = '\0'; /* end header */
122
123 /* first next header, or is at req->header_end */
124 while ((*c2 == '\n' || *c2 == '\r') && c2 < req->header_end)
125 ++c2;
126 if (c2 == req->header_end)
127 send_r_moved_temp(req, buf + 10, "");
128 else
129 send_r_moved_temp(req, buf + 10, c2);
130 }
131 req->status = DONE;
132 return 1;
133 } else { /* not location */
134 char *dest;
135 int howmuch;
136
137 if (!strncasecmp(buf, "Status: ", 8)) {
138 char str_status[4];
139 char desc[32];
140 int len;
141 char *p = buf+8;
142
143 len = 0;
144 while( *p != ' ' && *p != 0) { len++; p++; }
145
146 if (len > 3) { /* status code too long! */
147 req->buffer_start = req->buffer_end = 0;
148 send_r_error(req);
149 return 0;
150 }
151 memcpy( str_status, buf+8, 3);
152 str_status[3] = 0;
153
154 len = 0;
155 if (*p == ' ') p++;
156 while( (*p != '\r') && *p != 0) { len++; p++; }
157
158 if (len > sizeof(desc)-1) { /* description long! */
159 req->buffer_start = req->buffer_end = 0;
160 send_r_error(req);
161 return 0;
162 }
163
164 memcpy( desc, p-len, len);
165 desc[len] = 0;
166
167 send_r_request_cgi_status(req, str_status, desc); /* does not terminate */
168
169 if (*p=='\r' && *(p+1)=='\n')
170 p+=2; /* skip \r\n and move to the next line */
171
172 req->header_line = p;
173 } else {
174 send_r_request_cgi_status(req, "200", "OK"); /* does not terminate */
175 }
176
177 /* got to do special things because
178 a) we have a single buffer divided into 2 pieces
179 b) we need to merge those pieces
180 Easiest way is to memmove the cgi data backward until
181 it touches the buffered data, then reset the cgi data pointers
182 */
183 dest = req->buffer + req->buffer_end;
184 if (req->method == M_HEAD) {
185 if (*(c + 1) == '\r')
186 req->header_end = c + 2;
187 else
188 req->header_end = c + 1;
189 req->cgi_status = CGI_DONE;
190 }
191 howmuch = req->header_end - req->header_line;
192
193 if (dest + howmuch > req->buffer + BUFFER_SIZE) {
194 /* big problem */
195 log_error_time();
196 fprintf(stderr, "Too much data to move! Aborting! %s %d\n",
197 __FILE__, __LINE__);
198 /* reset buffer pointers because we already called
199 send_r_request_ok... */
200 req->buffer_start = req->buffer_end = 0;
201 send_r_error(req);
202 return 0;
203 }
204 memmove(dest, req->header_line, howmuch);
205 req->buffer_end += howmuch;
206 req->header_line = req->buffer + req->buffer_end;
207 req->header_end = req->header_line;
208 req_flush(req);
209
210 if (req->method == M_HEAD)
211 return 0;
212 }
213 return 1;
214 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26