1 |
#include "request.h" |
2 |
#include "freehttpd.h" |
3 |
#include <ctype.h> |
4 |
#include <stdio.h> |
5 |
#include <stdlib.h> |
6 |
#include <string.h> |
7 |
#include <unistd.h> |
8 |
|
9 |
freehttpd_request_t * |
10 |
freehttpd_request_init (const char *method, const char *uri, |
11 |
const char *version) |
12 |
{ |
13 |
freehttpd_request_t *request = calloc (1, sizeof (freehttpd_request_t)); |
14 |
|
15 |
if (request == NULL) |
16 |
return NULL; |
17 |
|
18 |
if (method != NULL) |
19 |
{ |
20 |
request->method = strdup (method); |
21 |
request->method_length = strlen (method); |
22 |
} |
23 |
|
24 |
if (uri != NULL) |
25 |
{ |
26 |
request->uri = strdup (uri); |
27 |
request->uri_length = strlen (uri); |
28 |
} |
29 |
|
30 |
if (version != NULL) |
31 |
{ |
32 |
|
33 |
request->version = strdup (version); |
34 |
request->version_length = strlen (version); |
35 |
} |
36 |
|
37 |
return request; |
38 |
} |
39 |
|
40 |
freehttpd_header_t * |
41 |
freehttpd_header_init (const char *name, const char *value) |
42 |
{ |
43 |
freehttpd_header_t *header = calloc (1, sizeof (freehttpd_header_t)); |
44 |
|
45 |
if (header == NULL) |
46 |
return NULL; |
47 |
|
48 |
if (name != NULL) |
49 |
header->name = strdup (name); |
50 |
|
51 |
if (value != NULL) |
52 |
header->value = strdup (value); |
53 |
|
54 |
return header; |
55 |
} |
56 |
|
57 |
void |
58 |
freehttpd_header_free (freehttpd_header_t *header) |
59 |
{ |
60 |
if (header == NULL) |
61 |
return; |
62 |
|
63 |
if (header->name != NULL) |
64 |
free (header->name); |
65 |
|
66 |
if (header->value != NULL) |
67 |
free (header->value); |
68 |
|
69 |
free (header); |
70 |
} |
71 |
|
72 |
void |
73 |
freehttpd_request_free (freehttpd_request_t *request) |
74 |
{ |
75 |
if (request == NULL) |
76 |
return; |
77 |
|
78 |
if (request->method != NULL) |
79 |
free (request->method); |
80 |
|
81 |
if (request->uri != NULL) |
82 |
free (request->uri); |
83 |
|
84 |
if (request->version != NULL) |
85 |
free (request->version); |
86 |
|
87 |
if (request->headers != NULL) |
88 |
{ |
89 |
for (size_t i = 0; i < request->headers_count; i++) |
90 |
freehttpd_header_free (request->headers[i]); |
91 |
|
92 |
free (request->headers); |
93 |
} |
94 |
|
95 |
if (request->body != NULL) |
96 |
free (request->body); |
97 |
|
98 |
free (request); |
99 |
} |
100 |
|
101 |
const char *const SUPPORTED_METHODS[] |
102 |
= { "GET", "POST", "PUT", "DELETE", "HEAD", |
103 |
"OPTIONS", "TRACE", "CONNECT", NULL }; |
104 |
|
105 |
freehttpd_request_t * |
106 |
freehttpd_request_parse (freehttpd_t *freehttpd, int sockfd, ecode_t *error) |
107 |
{ |
108 |
freehttpd_request_t *request = freehttpd_request_init (NULL, NULL, NULL); |
109 |
|
110 |
if (request == NULL) |
111 |
{ |
112 |
*error = E_LIBC_MALLOC; |
113 |
return NULL; |
114 |
} |
115 |
|
116 |
const freehttpd_config_t *config = freehttpd_get_config (freehttpd); |
117 |
char *buf[3] = { 0 }; |
118 |
char **buf_ptrs[] = { &request->method, &request->uri, &request->version }; |
119 |
size_t max_lengths[] = { config->max_method_len, config->max_uri_len, |
120 |
config->max_version_len }; |
121 |
size_t *length_ptrs[] = { &request->method_length, &request->uri_length, |
122 |
&request->version_length }; |
123 |
|
124 |
for (int i = 0; i < 3; i++) |
125 |
{ |
126 |
char c; |
127 |
size_t j = 0; |
128 |
|
129 |
while (read (sockfd, &c, 1) == 1) |
130 |
{ |
131 |
if (isspace (c)) |
132 |
break; |
133 |
|
134 |
if (j >= max_lengths[i]) |
135 |
{ |
136 |
freehttpd_request_free (request); |
137 |
*error = E_MALFORMED_REQUEST; |
138 |
return NULL; |
139 |
} |
140 |
|
141 |
buf[i] = realloc (buf[i], j + 1); |
142 |
buf[i][j++] = c; |
143 |
} |
144 |
|
145 |
if (j == 0) |
146 |
{ |
147 |
freehttpd_request_free (request); |
148 |
*error = E_MALFORMED_REQUEST; |
149 |
return NULL; |
150 |
} |
151 |
|
152 |
buf[i] = realloc (buf[i], j + 1); |
153 |
buf[i][j] = 0; |
154 |
*length_ptrs[i] = j; |
155 |
*buf_ptrs[i] = buf[i]; |
156 |
} |
157 |
|
158 |
for (size_t i = 0; SUPPORTED_METHODS[i] != NULL; i++) |
159 |
{ |
160 |
if (strcmp (buf[0], SUPPORTED_METHODS[i]) == 0) |
161 |
{ |
162 |
request->method = buf[0]; |
163 |
break; |
164 |
} |
165 |
} |
166 |
|
167 |
if (request->method == NULL || request->uri == NULL |
168 |
|| request->version == NULL) |
169 |
{ |
170 |
freehttpd_request_free (request); |
171 |
*error = E_MALFORMED_REQUEST; |
172 |
return NULL; |
173 |
} |
174 |
|
175 |
*error = E_OK; |
176 |
return request; |
177 |
} |