4 |
#include <stdio.h> |
#include <stdio.h> |
5 |
#include <stdlib.h> |
#include <stdlib.h> |
6 |
#include <string.h> |
#include <string.h> |
7 |
|
#include <sys/socket.h> |
8 |
#include <unistd.h> |
#include <unistd.h> |
9 |
|
|
10 |
freehttpd_request_t * |
freehttpd_request_t * |
39 |
} |
} |
40 |
|
|
41 |
freehttpd_header_t * |
freehttpd_header_t * |
42 |
freehttpd_header_init (const char *name, const char *value) |
freehttpd_header_init (const char *name, const char *value, size_t name_length, |
43 |
|
size_t value_length) |
44 |
{ |
{ |
45 |
freehttpd_header_t *header = calloc (1, sizeof (freehttpd_header_t)); |
freehttpd_header_t *header = calloc (1, sizeof (freehttpd_header_t)); |
46 |
|
|
48 |
return NULL; |
return NULL; |
49 |
|
|
50 |
if (name != NULL) |
if (name != NULL) |
51 |
header->name = strdup (name); |
{ |
52 |
|
header->name = strdup (name); |
53 |
|
header->name_length |
54 |
|
= name_length == 0 ? strlen (name) : name_length; |
55 |
|
} |
56 |
|
|
57 |
if (value != NULL) |
if (value != NULL) |
58 |
header->value = strdup (value); |
{ |
59 |
|
header->value = strdup (value); |
60 |
|
header->value_length |
61 |
|
= value_length == 0 ? strlen (value) : value_length; |
62 |
|
} |
63 |
|
|
64 |
return header; |
return header; |
65 |
} |
} |
92 |
free (request->uri); |
free (request->uri); |
93 |
|
|
94 |
if (request->version != NULL) |
if (request->version != NULL) |
95 |
free (request->version); |
free (request->version - 5); |
96 |
|
|
97 |
|
if (request->path != NULL) |
98 |
|
free (request->path); |
99 |
|
|
100 |
|
if (request->query != NULL) |
101 |
|
free (request->query); |
102 |
|
|
103 |
if (request->headers != NULL) |
if (request->headers != NULL) |
104 |
{ |
{ |
114 |
free (request); |
free (request); |
115 |
} |
} |
116 |
|
|
117 |
|
static char * |
118 |
|
urldecode (const char *input, size_t *len) |
119 |
|
{ |
120 |
|
char *output = calloc (strlen (input) + 1, 1); |
121 |
|
|
122 |
|
if (output == NULL) |
123 |
|
return NULL; |
124 |
|
|
125 |
|
size_t i = 0, j = 0; |
126 |
|
|
127 |
|
for (; input[i] != 0; i++, j++) |
128 |
|
{ |
129 |
|
if (input[i] == '%') |
130 |
|
{ |
131 |
|
if (input[i + 1] == 0 || input[i + 2] == 0) |
132 |
|
{ |
133 |
|
free (output); |
134 |
|
return NULL; |
135 |
|
} |
136 |
|
|
137 |
|
char c1 = tolower (input[i + 1]); |
138 |
|
char c2 = tolower (input[i + 2]); |
139 |
|
int c1n = isdigit (c1) ? c1 - '0' : c1 - 'a' + 10; |
140 |
|
int c2n = isdigit (c2) ? c2 - '0' : c2 - 'a' + 10; |
141 |
|
int code = c1n * 16 + c2n; |
142 |
|
output[j] = (char) code; |
143 |
|
i += 2; |
144 |
|
} |
145 |
|
else |
146 |
|
output[j] = input[i]; |
147 |
|
} |
148 |
|
|
149 |
|
output[j] = 0; |
150 |
|
|
151 |
|
printf ("output: %s\n", output); |
152 |
|
|
153 |
|
if (len != NULL) |
154 |
|
*len = j; |
155 |
|
|
156 |
|
return output; |
157 |
|
} |
158 |
|
|
159 |
const char *const SUPPORTED_METHODS[] |
const char *const SUPPORTED_METHODS[] |
160 |
= { "GET", "POST", "PUT", "DELETE", "HEAD", |
= { "GET", "POST", "PUT", "DELETE", "HEAD", |
161 |
"OPTIONS", "TRACE", "CONNECT", NULL }; |
"OPTIONS", "TRACE", "CONNECT", NULL }; |
184 |
char c; |
char c; |
185 |
size_t j = 0; |
size_t j = 0; |
186 |
|
|
187 |
while (read (sockfd, &c, 1) == 1) |
/* TODO: instead of always calling read with size 1, we could |
188 |
|
optimize this by reading more bytes at once and then parsing |
189 |
|
the buffer. */ |
190 |
|
while (recv (sockfd, &c, 1, 0) == 1) |
191 |
{ |
{ |
192 |
if (isspace (c)) |
if (isspace (c)) |
193 |
break; |
break; |
233 |
return NULL; |
return NULL; |
234 |
} |
} |
235 |
|
|
236 |
|
if (memcmp (request->version, "HTTP/", 5) != 0) |
237 |
|
{ |
238 |
|
freehttpd_request_free (request); |
239 |
|
*error = E_MALFORMED_REQUEST; |
240 |
|
return NULL; |
241 |
|
} |
242 |
|
|
243 |
|
request->version += 5; |
244 |
|
request->version_length -= 5; |
245 |
|
|
246 |
|
char *path = strchr (request->uri, '?'); |
247 |
|
|
248 |
|
if (path != NULL) |
249 |
|
{ |
250 |
|
path = strndup (request->uri, path - request->uri); |
251 |
|
request->query = strdup (path + 1); |
252 |
|
request->query_length |
253 |
|
= request->uri_length - request->path_length - 1; |
254 |
|
} |
255 |
|
else |
256 |
|
path = strdup (request->uri); |
257 |
|
|
258 |
|
request->path = urldecode (path, &request->path_length); |
259 |
|
free (path); |
260 |
*error = E_OK; |
*error = E_OK; |
261 |
return request; |
return request; |
262 |
} |
} |