10 #define BUFFER_SIZE 128
12 #define HTTP_VERSION "HTTP/1.0"
13 #define SERVER_NAME "Webserver/0.0.1"
20 "301 Moved Permanently",
21 "302 Moved Temporarily",
27 "500 Internal Server Error",
28 "501 Not Implemented",
30 "503 Service Unavailable"};
33 c200
= 0, c201
, c202
, c204
,
34 c301
, c302
, c304
, c400
,
35 c401
, c403
, c404
, c500
,
40 not_supported_e
= 0, get_e
, head_e
, post_e
46 char *content_encoding
;
52 char *if_modified_since
;
59 char *www_authenticate
;
62 /* print header values */
64 void print_header_values (header_t
*header
)
66 printf ("Header values\n");
67 if (header
->allow
) printf ("allow = '%s'\n", header
->allow
);
68 if (header
->authorization
) printf ("authorization = '%s'\n", header
->authorization
);
69 if (header
->content_encoding
) printf ("content_encoding = '%s'\n", header
->content_encoding
);
70 if (header
->content_length
) printf ("content_length = '%s'\n", header
->content_length
);
71 if (header
->content_type
) printf ("content_type = '%s'\n", header
->content_type
);
72 if (header
->date
) printf ("date = '%s'\n", header
->date
);
73 if (header
->expires
) printf ("expires = '%s'\n", header
->expires
);
74 if (header
->from
) printf ("from = '%s'\n", header
->from
);
75 if (header
->if_modified_since
) printf ("if_modified_since = '%s'\n", header
->if_modified_since
);
76 if (header
->last_modified
) printf ("last_modified = '%s'\n", header
->last_modified
);
77 if (header
->location
) printf ("location = '%s'\n", header
->location
);
78 if (header
->pragma
) printf ("pragma = '%s'\n", header
->pragma
);
79 if (header
->referer
) printf ("referer = '%s'\n", header
->referer
);
80 if (header
->server
) printf ("server = '%s'\n", header
->server
);
81 if (header
->user_agent
) printf ("user_agent = '%s'\n", header
->user_agent
);
82 if (header
->www_authenticate
) printf ("www_authenticate = '%s'\n", header
->www_authenticate
);
87 char *find_sequence (char *data
, int len
, char *seq
, char **pdata
)
90 int size
= strlen (seq
);
93 for (i
= 0; i
< len
- size
+ 1; i
++) {
94 if (strncmp (data
+ i
, seq
, size
) == 0) {
97 *pdata
= data
+ i
+ size
;
106 /* response entity */
108 int add_line (char **buffer
, char *str
)
110 VERBOSE (DEBUG
, PRINT ("add line: %s", str
));
111 int len
= ((*buffer
) ? strlen (*buffer
) : 0) + strlen (str
) + 1;
112 VERBOSE (DEBUG
, PRINT ("len: %d\n", len
));
114 *buffer
= (char *)realloc (*buffer
, len
);
116 *buffer
= (char *)calloc (len
, 1);
118 strcat (*buffer
, str
);
122 int add_status_line (char **buffer
, code_t code
)
124 char tmp
[BUFFER_SIZE
] = {0};
127 sprintf (tmp
, "%s %s\r\n", HTTP_VERSION
, codes
[code
]);
128 add_line (buffer
, tmp
);
130 return strlen (*buffer
);
133 int add_general_header (char **buffer
)
135 char tmp
[BUFFER_SIZE
] = {0};
138 time_t ts
= time (NULL
);
139 sprintf (tmp
, "Date: %s\r\n", ctime (&ts
));
140 add_line (buffer
, tmp
);
144 return strlen (*buffer
);
147 int add_response_header (char **buffer
, char *uri
)
149 char tmp
[BUFFER_SIZE
] = {0};
152 sprintf (tmp
, "Location: %s\r\n", uri
);
153 add_line (buffer
, tmp
);
156 sprintf (tmp
, "Server: %s\r\n", SERVER_NAME
);
157 add_line (buffer
, tmp
);
159 /* WWW-Authentificate */
161 return strlen (*buffer
);
164 int add_entity (char **buffer
, char *entity
, int size
, char *type
, char *encoding
)
166 char tmp
[BUFFER_SIZE
] = {0};
167 int len
= strlen (*buffer
);
173 if (entity
!= NULL
) {
175 /* Content-Encoding */
176 if (encoding
!= NULL
) {
177 sprintf (tmp
, "Content-Encoding: %s\r\n", encoding
);
178 add_line (buffer
, tmp
);
182 sprintf (tmp
, "Content-Length: %d\r\n", size
);
183 add_line (buffer
, tmp
);
186 sprintf (tmp
, "Content-Type: %s\r\n", type
);
187 add_line (buffer
, tmp
);
189 add_line (buffer
, "\r\n");
192 len
= strlen (*buffer
);
193 *buffer
= realloc (*buffer
, len
+ size
);
194 memcpy (*buffer
+ len
, entity
, size
);
203 int error_400 (char **buffer
)
205 add_status_line (buffer
, c400
);
206 add_general_header (buffer
);
207 add_response_header (buffer
, NULL
);
209 char *response
= "<html><head><title>Error 400</title></head><body><p>Bad Request</p></body></html>";
210 return add_entity (buffer
, response
, strlen (response
), "text/html", "iso-8859-1");
215 int error_404 (char **buffer
, char *uri
)
217 add_status_line (buffer
, c404
);
218 add_general_header (buffer
);
219 add_response_header (buffer
, uri
);
221 char *response
= "<html><head><title>Error 404</title></head><body><p>File not found</p></body></html>";
222 return add_entity (buffer
, response
, strlen (response
), "text/html", "iso-8859-1");
227 int response_html (char **buffer
, char *location
, char *response
)
230 VERBOSE (DEBUG
, PRINT ("add_status_line %d\n", len
));
231 len
= add_status_line (buffer
, c200
);
232 VERBOSE (DEBUG
, PRINT ("add_general_header %d\n", len
));
233 len
= add_general_header (buffer
);
234 VERBOSE (DEBUG
, PRINT ("add_response_header %d\n", len
));
235 len
= add_response_header (buffer
, location
);
237 VERBOSE (DEBUG
, PRINT ("add_entity %d\n", len
));
238 return add_entity (buffer
, response
, strlen (response
), "text/html", "iso-8859-1");
243 char *trim (char *str
)
246 while ((*str
== ' ') || (*str
== '\t')) {
253 /* main HTTP processing */
255 int processing (char *data
, int len
, char *root
, char **pdata
)
257 VERBOSE (DEBUG
, PRINT ("Start processing\n"));
260 char *line
= find_sequence (data
, len
, "\r\n", &data
);
262 VERBOSE (WARNING
, PRINT ("Unknown received data\n"));
268 VERBOSE (DEBUG
, PRINT ("Command line: '%s'\n", line
));
270 char *method
= strtok (line
, " ");
271 char *uri
= strtok (NULL
, " ");
272 char *version
= strtok (NULL
, " ");
273 method_t type
= not_supported_e
;
274 if (strcmp (method
, "GET") == 0) {
276 } else if (strcmp ("HEAD", method
) == 0) {
278 } else if (strcmp ("POST", method
) == 0) {
281 VERBOSE (WARNING
, PRINT ("Unkown method: %s\n", method
));
282 return error_400 (pdata
);
284 VERBOSE (INFO
, PRINT ("%s %s (%s)\n", (type
== get_e
) ? "Get" : (type
== head_e
) ? "Head" : "Post", uri
, version
));
287 char *filename
= (char *)calloc (strlen (root
) + strlen (uri
) + 2, 1);
288 //sprintf (filename, "%s%s%s", root, ((root[strlen (root) - 1] != '/') && (uri[0] != '/')) ? "/" : "", uri);
289 sprintf (filename
, "%s/%s", root
, uri
);
292 header_t header
= {0};
293 while (strcmp (line
= find_sequence (data
, len
, "\r\n", &data
), "") != 0) {
294 VERBOSE (DEBUG
, PRINT ("Header line: '%s'\n", line
));
295 char *field
= strtok (line
, ":");
296 char *value
= trim (strtok (NULL
, "\r"));
297 VERBOSE (DEBUG
, PRINT ("Field: %s\nValue: %s\n", field
, value
));
302 VERBOSE (DEBUG
, PRINT ("Analyse field\n"));
303 if (strcmp (field
, "Allow") == 0) {
304 header
.allow
= value
;
305 } else if (strcmp (field
, "Authorization") == 0) {
306 header
.authorization
= value
;
307 } else if (strcmp (field
, "Content-Encoding") == 0) {
308 header
.content_encoding
= value
;
309 } else if (strcmp (field
, "Content-Length") == 0) {
310 header
.content_length
= value
;
311 } else if (strcmp (field
, "Content-Type") == 0) {
312 header
.content_type
= value
;
313 } else if (strcmp (field
, "Date") == 0) {
315 } else if (strcmp (field
, "Expires") == 0) {
316 header
.expires
= value
;
317 } else if (strcmp (field
, "From") == 0) {
319 } else if (strcmp (field
, "If-Modified-Since") == 0) {
320 header
.if_modified_since
= value
;
321 } else if (strcmp (field
, "Last-Modified") == 0) {
322 header
.last_modified
= value
;
323 } else if (strcmp (field
, "Location") == 0) {
324 header
.location
= value
;
325 } else if (strcmp (field
, "Pragma") == 0) {
326 header
.pragma
= value
;
327 } else if (strcmp (field
, "Referer") == 0) {
328 header
.referer
= value
;
329 } else if (strcmp (field
, "Server") == 0) {
330 header
.server
= value
;
331 } else if (strcmp (field
, "User-Agent") == 0) {
332 header
.user_agent
= value
;
333 } else if (strcmp (field
, "WWW-Authenticate") == 0) {
334 header
.www_authenticate
= value
;
336 VERBOSE (WARNING
, PRINT ("Unknown header field: '%s'\n", field
));
339 VERBOSE (DEBUG
, print_header_values (&header
));
345 VERBOSE (DEBUG
, PRINT ("Read file %s\n", filename
));
346 len
= readfile (&buffer
, filename
);
348 len
= error_404 (pdata
, "http://localhost/");
350 len
= response_html (pdata
, "http://localhost/", buffer
);
357 VERBOSE (DEBUG
, PRINT ("Write file %s\n", filename
));
359 case not_supported_e
:
364 VERBOSE (DEBUG
, PRINT ("Cleaning\n"));
366 VERBOSE (DEBUG
, PRINT ("Cleaning filename\n"));
373 /* vim: set ts=4 sw=4 et: */