Commit | Line | Data |
---|---|---|
d0b0d52b ML |
1 | #include <malloc.h> |
2 | #include <string.h> | |
3 | ||
4 | #include "debug.h" | |
5 | ||
6 | #include "http.h" | |
7 | ||
bb0468a5 LM |
8 | #define HTTP_VERSION "HTTP/1.0" |
9 | #define SERVER_NAME "Webserver/0.0.1" | |
10 | ||
11 | char **codes = { | |
12 | "200 OK", | |
13 | "201 Created", | |
14 | "202 Accepted", | |
15 | "204 No Content", | |
16 | "301 Moved Permanently", | |
17 | "302 Moved Temporarily", | |
18 | "304 Not Modified", | |
19 | "400 Bad Request", | |
20 | "401 Unauthorized", | |
21 | "403 Forbidden", | |
22 | "404 Not Found", | |
23 | "500 Internal Server Error", | |
24 | "501 Not Implemented", | |
25 | "502 Bad Gateway", | |
26 | "503 Service Unavailable"}; | |
27 | ||
28 | typedef enum { | |
29 | c200 = 0, c201, c202, c204, | |
30 | c301, c302, c304, c400, | |
31 | c401, c403, c404, c500, | |
32 | c501, c502, c503 | |
33 | } code_t; | |
34 | ||
35 | typedef enum { | |
36 | not_supported_e = 0, get_e, head_e, post_e | |
37 | } method_t; | |
38 | ||
39 | typedef struct { | |
40 | char *allow; | |
41 | char *authorization; | |
42 | char *content_encoding; | |
43 | char *content_length; | |
44 | char *content_type; | |
45 | char *date; | |
46 | char *expires; | |
47 | char *from; | |
48 | char *if_modified_since; | |
49 | char *last_modified; | |
50 | char *location; | |
51 | char *pragma; | |
52 | char *referer; | |
53 | char *server; | |
54 | char *user_agent; | |
55 | char *www_authenticate; | |
56 | } header_t; | |
57 | ||
58 | /* print header values */ | |
59 | ||
60 | void print_header_values (header_t *header) | |
61 | { | |
62 | printf ("allow = '%s'\n", header->allow); | |
63 | printf ("authorization = '%s'\n", header->authorization); | |
64 | printf ("content_encoding = '%s'\n", header->content_encoding); | |
65 | printf ("content_length = '%s'\n", header->content_length); | |
66 | printf ("content_type = '%s'\n", header->content_type); | |
67 | printf ("date = '%s'\n", header->date); | |
68 | printf ("expires = '%s'\n", header->expires); | |
69 | printf ("from = '%s'\n", header->from); | |
70 | printf ("if_modified_since = '%s'\n", header->if_modified_since); | |
71 | printf ("last_modified = '%s'\n", header->last_modified); | |
72 | printf ("location = '%s'\n", header->location); | |
73 | printf ("pragma = '%s'\n", header->pragma); | |
74 | printf ("referer = '%s'\n", header->referer); | |
75 | printf ("server = '%s'\n", header->server); | |
76 | printf ("user_agent = '%s'\n", header->user_agent); | |
77 | printf ("www_authenticate = '%s'\n", header->www_authenticate); | |
78 | } | |
79 | ||
80 | /* find sequence*/ | |
81 | ||
82 | char *find_sequence (char *data, int len, char *seq, char **pdata) | |
83 | { | |
84 | ||
85 | int size = strlen (seq); | |
86 | ||
87 | int i; | |
88 | for (i = 0; i < len - size + 1; i++) { | |
89 | if (strncmp (data + i, seq, size) == 0) { | |
90 | data[i] = 0; | |
91 | if (pdata != NULL) { | |
92 | *pdata = data + i + size; | |
93 | } | |
94 | return data; | |
95 | } | |
96 | } | |
97 | ||
98 | return NULL; | |
99 | } | |
100 | ||
101 | /* response entity */ | |
102 | ||
103 | int add_status_line (char **buffer, int len) | |
104 | { | |
d0b0d52b ML |
105 | return len; |
106 | } | |
107 | ||
bb0468a5 LM |
108 | int add_general_header (char **buffer, int len) |
109 | { | |
110 | return len; | |
111 | } | |
112 | ||
113 | int add_response_header (char **buffer, int len) | |
114 | { | |
115 | return len; | |
116 | } | |
117 | ||
118 | int add_entity (char **buffer, int len, unsigned char *entity, int size, char *type) | |
119 | { | |
120 | return len; | |
121 | } | |
122 | ||
123 | /* error 400 */ | |
124 | ||
125 | int error_400 (char **buffer) | |
126 | { | |
127 | ||
128 | } | |
129 | ||
130 | /* trim string */ | |
131 | ||
132 | char *trim (char *str) | |
133 | { | |
134 | if (str != NULL) { | |
135 | while ((*str == ' ') || (*str == '\t')) { | |
136 | str++; | |
137 | } | |
138 | } | |
139 | return str; | |
140 | } | |
141 | ||
142 | /* main HTTP processing */ | |
143 | ||
144 | int processing (char *data, int len, char **pdata) | |
145 | { | |
146 | char *saved_data = data; | |
147 | VERBOSE (DEBUG, PRINT ("Start processing\n")); | |
148 | ||
149 | /* check method */ | |
150 | char *line = find_sequence (data, len, "\r\n", &data); | |
151 | if (line == NULL) { | |
152 | VERBOSE (WARNING, PRINT ("Unknown received data\n")); | |
153 | if (pdata != NULL) { | |
154 | *pdata = NULL; | |
155 | } | |
156 | return 0; | |
157 | } | |
158 | VERBOSE (DEBUG, PRINT ("Command line: '%s'\n", line)); | |
159 | ||
160 | char *method = strtok (line, " "); | |
161 | char *uri = strtok (NULL, " "); | |
162 | char *version = strtok (NULL, " "); | |
163 | method_t type = not_supported_e; | |
164 | if (strcmp (method, "GET") == 0) { | |
165 | type = get_e; | |
166 | } else if (strcmp ("HEAD", method) == 0) { | |
167 | type = head_e; | |
168 | } else if (strcmp ("POST", method) == 0) { | |
169 | type = post_e; | |
170 | } else { | |
171 | VERBOSE (WARNING, PRINT ("Unkown method: %s\n", method)); | |
172 | } else { | |
173 | free (saved_data); | |
174 | return error_400 (pdata); | |
175 | } | |
176 | VERBOSE (INFO, PRINT ("%s %s (%s)\n", (type == get_e) ? "Get" : (type == head_e) ? "Head" : "Post", uri, version)); | |
177 | ||
178 | /* check header */ | |
179 | header_t header = {0}; | |
180 | while (strcmp (line = find_sequence (data, len, "\r\n", &data), "") != 0) { | |
181 | VERBOSE (DEBUG, PRINT ("Header line: '%s'\n", line)); | |
182 | char *field = strtok (line, ":"); | |
183 | char *value = trim (strtok (NULL, "\r")); | |
184 | VERBOSE (DEBUG, PRINT ("Field: %s\nValue: %s\n", field, value)); | |
185 | if (*line == 0) { | |
186 | break; | |
187 | } | |
188 | ||
189 | VERBOSE (DEBUG, PRINT ("Analyse field\n")); | |
190 | if (strcmp (field, "Allow") == 0) { | |
191 | header.allow = value; | |
192 | } else if (strcmp (field, "Authorization") == 0) { | |
193 | header.authorization = value; | |
194 | } else if (strcmp (field, "Content-Encoding") == 0) { | |
195 | header.content_encoding = value; | |
196 | } else if (strcmp (field, "Content-Length") == 0) { | |
197 | header.content_length = value; | |
198 | } else if (strcmp (field, "Content-Type") == 0) { | |
199 | header.content_type = value; | |
200 | } else if (strcmp (field, "Date") == 0) { | |
201 | header.date = value; | |
202 | } else if (strcmp (field, "Expires") == 0) { | |
203 | header.expires = value; | |
204 | } else if (strcmp (field, "From") == 0) { | |
205 | header.from = value; | |
206 | } else if (strcmp (field, "If-Modified-Since") == 0) { | |
207 | header.if_modified_since = value; | |
208 | } else if (strcmp (field, "Last-Modified") == 0) { | |
209 | header.last_modified = value; | |
210 | } else if (strcmp (field, "Location") == 0) { | |
211 | header.location = value; | |
212 | } else if (strcmp (field, "Pragma") == 0) { | |
213 | header.pragma = value; | |
214 | } else if (strcmp (field, "Referer") == 0) { | |
215 | header.referer = value; | |
216 | } else if (strcmp (field, "Server") == 0) { | |
217 | header.server = value; | |
218 | } else if (strcmp (field, "User-Agent") == 0) { | |
219 | header.user_agent = value; | |
220 | } else if (strcmp (field, "WWW-Authenticate") == 0) { | |
221 | header.www_authenticate = value; | |
222 | } else { | |
223 | VERBOSE (WARNING, PRINT ("Unknown header field: '%s'\n", field)); | |
224 | } | |
225 | } | |
226 | VERBOSE (DEBUG, print_header_values (&header)); | |
227 | ||
228 | /* processing data */ | |
229 | if (data) { | |
230 | VERBOSE (DEBUG, PRINT ("Processing data: %s\n", data)); | |
231 | } | |
232 | ||
233 | /* cleaning */ | |
234 | free (saved_data); | |
235 | ||
236 | /* response */ | |
237 | *pdata = strdup ("HTTP/1.0 200 OK\r\nDate: Sat, 20 May 2023 16:37:46 GMT\r\nServer: Webserver/0.0.1 (Debian)\r\nLocation: http://localhost/\r\nContent-Length: 77\r\nContent-Type: text/html; charset=iso-8859-1\r\n\r\n<html><head><title>Test</title></head><body><p>This a test</p></body></html>"); | |
238 | return strlen (*pdata); | |
239 | } | |
240 | ||
d0b0d52b | 241 | /* vim: set ts=4 sw=4 et: */ |