1 #include "config.h"
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
7 #include <fcntl.h>
8 #include <errno.h>
9 #include <syslog.h>
10 #include <sys/time.h>
11 #include <sys/types.h>
12 #include <sys/socket.h>
13 #include <netinet/in.h>
14
15 #include "httpd.h"
16
17 /* ---------------------------------------------------------------------- */
18
19 void
20 read_request(struct REQUEST *req, int pipelined)
21 {
22 int rc;
23 char *h;
24
25 restart:
26 rc = read(req->fd, req->hreq + req->hdata, MAX_HEADER - req->hdata);
27 switch (rc) {
28 case -1:
29 if (errno == EAGAIN) {
30 if (pipelined)
31 break; /* check if there is already a full request */
32 else
33 return;
34 }
35 if (errno == EINTR)
36 goto restart;
37 xperror(LOG_INFO,"read",req->peerhost);
38 /* fall through */
39 case 0:
40 req->state = STATE_CLOSE;
41 return;
42 default:
43 req->hdata += rc;
44 req->hreq[req->hdata] = 0;
45 }
46
47 /* check if this looks like a http request after
48 the first few bytes... */
49 if (req->hdata < 5)
50 return;
51 if (strncmp(req->hreq,"GET ",4) != 0 &&
52 strncmp(req->hreq,"PUT ",4) != 0 &&
53 strncmp(req->hreq,"HEAD ",5) != 0 &&
54 strncmp(req->hreq,"POST ",5) != 0) {
55 mkerror(req,400,0);
56 return;
57 }
58
59 /* header complete ?? */
60 if (NULL != (h = strstr(req->hreq,"\r\n\r\n")) ||
61 NULL != (h = strstr(req->hreq,"\n\n"))) {
62 if (*h == '\r') {
63 h += 4;
64 *(h-2) = 0;
65 } else {
66 h += 2;
67 *(h-1) = 0;
68 }
69 req->lreq = h - req->hreq;
70 req->state = STATE_PARSE_HEADER;
71 return;
72 }
73
74 if (req->hdata == MAX_HEADER) {
75 /* oops: buffer full, but found no complete request ... */
76 mkerror(req,400,0);
77 return;
78 }
79 return;
80 }
81
82 /* ---------------------------------------------------------------------- */
83
84 static int
85 unhex(unsigned char c)
86 {
87 if (c < '@')
88 return c - '';
89 return (c & 0x0f) + 9;
90 }
91
92 static void
93 unquote(unsigned char *dst, unsigned char *src)
94 {
95 int i,j,q,n=strlen(src);
96
97 q=0;
98 for (i=0, j=0; i<n; i++, j++) {
99 if (src[i] == '?')
100 q = 1;
101 if (q && src[i] == '+') {
102 dst[j] = ' ';
103 } else if (src[i] == '%') {
104 dst[j] = (unhex(src[i+1]) << 4) | unhex(src[i+2]);
105 i += 2;
106 } else {
107 dst[j] = src[i];
108 }
109 }
110 dst[j] = 0;
111 }
112
113 void
114 parse_request(struct REQUEST *req)
115 {
116 char filename[2048], proto[5], *h;
117 int port;
118
119 if (debug > 2)
120 fprintf(stderr,"%s\n",req->hreq);
121
122 /* parse request. Hehe, scanf is powerfull :-) */
123 if (4 != sscanf(req->hreq, "%4[A-Z] %255[^ \t\r\n] HTTP/%d.%d",
124 req->type,filename,&(req->major),&(req->minor))) {
125 mkerror(req,400,0);
126 return;
127 }
128 if (filename[0] == '/') {
129 strcpy(req->uri,filename);
130 } else {
131 port = 0;
132 *proto = 0;
133 if (4 != sscanf(filename,"%4[a-zA-Z]://%64[a-zA-Z0-9.-]:%d%255[^ \t\r\n]",
134 proto,req->hostname,&port,req->uri) &&
135 3 != sscanf(filename,"%4[a-zA-Z]://%64[a-zA-Z0-9.-]%255[^ \t\r\n]",
136 proto,req->hostname,req->uri)) {
137 mkerror(req,400,0);
138 return;
139 }
140 if (*proto != 0 && 0 != strcasecmp(proto,"http")) {
141 mkerror(req,400,0);
142 return;
143 }
144 }
145
146 unquote(req->path,req->uri);
147 if (debug)
148 fprintf(stderr,"%03d: %s \"%s\" HTTP/%d.%d\n",
149 req->fd, req->type, req->path, req->major, req->minor);
150
151 if (0 != strcmp(req->type,"GET") &&
152 0 != strcmp(req->type,"HEAD")) {
153 mkerror(req,501,0);
154 return;
155 }
156
157 if (0 == strcmp(req->type,"HEAD")) {
158 req->head_only = 1;
159 }
160
161 /* checks */
162 if (req->path[0] != '/') {
163 mkerror(req,400,0);
164 return;
165 }
166
167 /* parse header lines */
168 req->keep_alive = req->minor;
169 for (h = req->hreq; h - req->hreq < req->lreq;) {
170 h = strchr(h,'\n');
171 if (NULL == h)
172 break;
173 h++;
174
175 if (0 == strncasecmp(h,"Connection: ",12)) {
176 req->keep_alive = (0 == strncasecmp(h+12,"Keep-Alive",10));
177
178 } else if (0 == strncasecmp(h,"Host: ",6)) {
179 sscanf(h+6,"%64[a-zA-Z0-9.-]",req->hostname);
180 }
181 }
182
183 /* make sure we have a hostname */
184 if (req->hostname[0] == '\0' || canonicalhost)
185 strncpy(req->hostname,server_host,64);
186
187 /* lowercase hostname */
188 for (h = req->hostname; *h != 0; h++) {
189 if (*h < 'A' || *h > 'Z')
190 continue;
191 *h += 32;
192 }
193
194 /* handle request (more to come) */
195 buildpage(req);
196 return;
197 }
198
|
This page was automatically generated by the
LXR engine.
|