source: trunk/minix/commands/httpd/request.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 7.8 KB
Line 
1/* request.c
2 *
3 * This file is part of httpd.
4 *
5 * 02/17/1996 Michael Temari <Michael@TemWare.Com>
6 * 07/07/1996 Initial Release Michael Temari <Michael@TemWare.Com>
7 * 12/29/2002 Michael Temari <Michael@TemWare.Com>
8 *
9 */
10#include <sys/types.h>
11#include <sys/stat.h>
12#include <signal.h>
13#include <ctype.h>
14#include <stdio.h>
15#include <string.h>
16#include <stdlib.h>
17#include <time.h>
18#include <fcntl.h>
19#include <unistd.h>
20#include <pwd.h>
21#ifdef _MINIX
22#include <minix/minlib.h>
23#endif
24#include <errno.h>
25
26#include "http.h"
27#include "utility.h"
28#include "config.h"
29
30_PROTOTYPE(static void Timeout, (int sig));
31_PROTOTYPE(static int getline, (char *buffer, int size));
32_PROTOTYPE(static void authorize, (char *p, struct http_request *rq));
33_PROTOTYPE(static void decurl, (char *u));
34
35static int TimeOut;
36
37static void Timeout(sig)
38int sig;
39{
40 TimeOut = 1;
41}
42
43static int getline(buffer, size)
44char *buffer;
45int size;
46{
47char *p;
48int s;
49
50 p = buffer;
51
52 while(p < (buffer + size - 1)) {
53 TimeOut = 0;
54 signal(SIGALRM, Timeout);
55 alarm(5*60);
56 s = read(0, p, 1);
57 alarm(0);
58 if(TimeOut)
59 return(-1);
60 if(s != 1)
61 return(-1);
62 if(*p == '\n') break;
63 p++;
64 }
65 *++p = '\0';
66
67 p = &buffer[strlen(buffer) - 1];
68 if(p >= buffer && (*p == '\r' || *p == '\n')) *p-- ='\0';
69 if(p >= buffer && (*p == '\r' || *p == '\n')) *p-- ='\0';
70
71 return(strlen(buffer));
72}
73
74static void authorize(p, rq)
75char *p;
76struct http_request *rq;
77{
78char *s;
79
80 if(toupper(*p++) == 'B' &&
81 toupper(*p++) == 'A' &&
82 toupper(*p++) == 'S' &&
83 toupper(*p++) == 'I' &&
84 toupper(*p++) == 'C' &&
85 toupper(*p++) == ' ') ;
86 else
87 return;
88
89 s = decode64(p);
90
91 if((p = strchr(s, ':')) == (char *)NULL)
92 p = "";
93 else
94 *p++ = '\0';
95
96 strncpy(rq->authuser, s, sizeof(rq->authuser));
97 strncpy(rq->authpass, p, sizeof(rq->authpass));
98
99 return;
100}
101
102int getrequest(rq)
103struct http_request *rq;
104{
105static char line[4096];
106char *p, *p2, *ps;
107int s, len;
108struct vhost *ph;
109
110 /* get request, it may be simple */
111
112 s = getline(line, sizeof(line));
113 if(s < 0)
114 return(-1);
115
116 if(dbglog != (FILE *)NULL) {
117 fprintf(dbglog, "REQUEST: %s\n", line);
118 fflush(dbglog);
119 }
120
121 /* clear http_request */
122 memset(rq, 0, sizeof(*rq));
123 rq->ifmodsince = (time_t) -1;
124
125 /* assume simple request */
126 rq->type = HTTP_REQUEST_TYPE_SIMPLE;
127
128 /* parse the method */
129 p = line;
130 while(*p && !LWS(*p)) {
131 *p = toupper(*p);
132 p++;
133 }
134 if(*p) *p++ = '\0';
135
136 if(!strcmp(line, "GET"))
137 rq->method = HTTP_METHOD_GET; else
138 if(!strcmp(line, "HEAD"))
139 rq->method = HTTP_METHOD_HEAD; else
140 if(!strcmp(line, "POST"))
141 rq->method = HTTP_METHOD_POST; else
142 if(!strcmp(line, "PUT"))
143 rq->method = HTTP_METHOD_PUT; else
144#if 0
145 if(!strcmp(line, "OPTIONS"))
146 rq->method = HTTP_METHOD_OPTIONS; else
147 if(!strcmp(line, "PATCH"))
148 rq->method = HTTP_METHOD_PATCH; else
149 if(!strcmp(line, "COPY"))
150 rq->method = HTTP_METHOD_COPY; else
151 if(!strcmp(line, "MOVE"))
152 rq->method = HTTP_METHOD_MOVE; else
153 if(!strcmp(line, "DELETE"))
154 rq->method = HTTP_METHOD_DELETE; else
155 if(!strcmp(line, "LINK"))
156 rq->method = HTTP_METHOD_LINK; else
157 if(!strcmp(line, "UNLINK"))
158 rq->method = HTTP_METHOD_UNLINK; else
159 if(!strcmp(line, "TRACE"))
160 rq->method = HTTP_METHOD_TRACE; else
161 if(!strcmp(line, "WRAPPED"))
162 rq->method = HTTP_METHOD_WRAPPED; else
163#endif
164 rq->method = HTTP_METHOD_UNKNOWN;
165
166 /* parse the requested URI */
167 p2 = rq->uri;
168 len = sizeof(rq->uri) - 1;
169 while(*p && !LWS(*p) && len > 0) {
170 *p2++ = *p++;
171 len--;
172 }
173 *p2 = '\0';
174
175 /* eat up any leftovers if uri was too big */
176 while(*p && !LWS(*p))
177 p++;
178
179 /* save for continued processing later */
180 ps = p;
181
182 /* parse the requested URL */
183 p = rq->uri;
184 p2 = rq->url;
185 len = sizeof(rq->url) - 1;
186 while(*p && !LWS(*p) && *p != '?' && len > 0) {
187 *p2++ = *p++;
188 len--;
189 }
190 *p2 = '\0';
191
192 /* See if there is a query string */
193 if(*p == '?') {
194 p++;
195 p2 = rq->query;
196 len = sizeof(rq->query) - 1;
197 while(*p && !LWS(*p) && len > 0) {
198 *p2++ = *p++;
199 len--;
200 }
201 }
202
203 /* eat up any leftovers */
204 while(*p && !LWS(*p)) p++;
205
206 if(rq->url[0] == '\0') {
207 rq->url[0] = '/';
208 rq->url[1] = '\0';
209 }
210
211 /* url is a decoded copy of the uri */
212 decurl(rq->url);
213
214 /* restore and continue processing */
215 p = ps;
216
217 /* if this is true it is a simple request */
218 if(*p == '\0')
219 return(0);
220
221 /* parse HTTP version */
222 while(*p && LWS(*p)) p++;
223 if(toupper(*p++) != 'H') return(0);
224 if(toupper(*p++) != 'T') return(0);
225 if(toupper(*p++) != 'T') return(0);
226 if(toupper(*p++) != 'P') return(0);
227 if( *p++ != '/') return(0);
228
229 /* version major */
230 rq->vmajor = 0;
231 while((*p >= '0') && (*p <= '9'))
232 rq->vmajor = rq->vmajor * 10 + (*p++ - '0');
233 if(*p != '.')
234 return(0);
235 p++;
236
237 /* version minor */
238 rq->vminor = 0;
239 while((*p >= '0') && (*p <= '9'))
240 rq->vminor = rq->vminor * 10 + (*p++ - '0');
241 if(*p)
242 return(0);
243
244 rq->type = HTTP_REQUEST_TYPE_FULL;
245
246 p = rq->uri;
247
248 /* check if it is a proxy request */
249 if(toupper(*p++) == 'H' &&
250 toupper(*p++) == 'T' &&
251 toupper(*p++) == 'T' &&
252 toupper(*p++) == 'P' &&
253 toupper(*p++) == ':')
254 rq->type = HTTP_REQUEST_TYPE_PROXY;
255
256 /* parse any header fields */
257 while((s = getline(line, sizeof(line))) > 0) {
258 if(toupper(line[0]) == 'A' &&
259 toupper(line[1]) == 'U')
260 if(dbglog != (FILE *)NULL) {
261 fprintf(dbglog, "REQUEST: Authorization:\n");
262 fflush(dbglog);
263 } else ;
264 else
265 if(dbglog != (FILE *)NULL) {
266 fprintf(dbglog, "REQUEST: %s\n", line);
267 fflush(dbglog);
268 }
269 p = line;
270 while(*p && *p != ':') {
271 *p = toupper(*p);
272 p++;
273 }
274 if(*p != ':') continue; /* bad header field, skip it */
275 *p++ = '\0';
276 while(*p && LWS(*p)) p++;
277
278 /* header field value parsing here */
279 if(!strcmp(line, "HOST")) {
280 strncpy(rq->host, p, sizeof(rq->host));
281 p2 = strrchr(rq->host, ':');
282 if(p2 != (char *)NULL) {
283 *p2++ = '\0';
284 rq->port = atoi(p2);
285 }
286 /* if unknown virtual host then exit quietly */
287 for(ph = vhost; ph != NULL; ph = ph->next) {
288 if(!strcasecmp(ph->hname, "*")) break;
289 if(!strcasecmp(ph->hname, rq->host)) break;
290 }
291 if(rq->type != HTTP_REQUEST_TYPE_PROXY)
292 if(ph == NULL && vhost != NULL) return(1);
293 } else
294 if(!strcmp(line, "USER-AGENT"))
295 strncpy(rq->useragent, p, sizeof(rq->useragent)); else
296 if(!strcmp(line, "CONNECTION"))
297 rq->keepopen = strcasecmp(p, "Keep-Alive") ? 0 : 1; else
298 if(!strcmp(line, "IF-MODIFIED-SINCE"))
299 rq->ifmodsince = httptime(p); else
300 if(!strcmp(line, "CONTENT-LENGTH"))
301 rq->size = atol(p); else
302 if(!strcmp(line, "AUTHORIZATION")) {
303 strncpy(rq->wwwauth, p, sizeof(rq->wwwauth));
304 if(rq->type != HTTP_REQUEST_TYPE_PROXY)
305 authorize(p, rq);
306 } else
307 if(!strcmp(line, "PROXY-AUTHORIZATION")) {
308 if(rq->type == HTTP_REQUEST_TYPE_PROXY)
309 authorize(p, rq);
310 } else
311 if(!strcmp(line, "DATE"))
312 rq->msgdate = httptime(p); else
313 if(!strcmp(line, "COOKIE")) {
314 strncpy(rq->cookie, p, sizeof(rq->cookie)-1);
315 rq->cookie[sizeof(rq->cookie)-1] = '\0';
316 }
317 }
318
319 if(rq->type != HTTP_REQUEST_TYPE_PROXY)
320 if(*rq->host == '\0' && vhost != NULL) return(1);
321
322 if(dbglog != (FILE *)NULL && rq->authuser[0] != '\0') {
323 fprintf(dbglog, "REQUEST: AuthUser=%s\n", rq->authuser);
324 fflush(dbglog);
325 }
326
327 if(s < 0) {
328 fprintf(stderr, "httpd: getrequest: Error getline (header fields)\n");
329 return(-1);
330 }
331
332 return(0);
333}
334
335static void decurl(u)
336char *u;
337{
338char *p;
339char h1, h2;
340char c;
341
342 p = u;
343 while(*p) {
344 switch(*p) {
345 case '\0':
346 c = '\0';
347 break;
348 case '+':
349 c = ' ';
350 p++;
351 break;
352 case '%':
353 h1 = '0';
354 h2 = '0';
355 p++;
356 h1 = tolower(*p);
357 if(*p) p++;
358 h2 = tolower(*p);
359 if(*p) p++;
360 c = (h1 > '9') ? (10 + h1 - 'a') : (h1 - '0');
361 c = 16 * c + ((h2 > '9') ? (10 + h2 - 'a') : (h2 - '0'));
362 break;
363 default:
364 c = *p++;
365 }
366 *u++ = c;
367 }
368 *u = '\0';
369}
Note: See TracBrowser for help on using the repository browser.