9 #define BUFFER_SIZE 128
11 #define HTTP_VERSION "HTTP/1.0"
12 #define SERVER_NAME "Webserver/0.0.1"
19 "301 Moved Permanently",
20 "302 Moved Temporarily",
26 "500 Internal Server Error",
27 "501 Not Implemented",
29 "503 Service Unavailable"};
32 c200
= 0, c201
, c202
, c204
,
33 c301
, c302
, c304
, c400
,
34 c401
, c403
, c404
, c500
,
39 not_supported_e
= 0, get_e
, head_e
, post_e
45 char *content_encoding
;
51 char *if_modified_since
;
58 char *www_authenticate
;
61 /* print header values */
63 void print_header_values (header_t
*header
)
65 printf ("allow = '%s'\n", header
->allow
);
66 printf ("authorization = '%s'\n", header
->authorization
);
67 printf ("content_encoding = '%s'\n", header
->content_encoding
);
68 printf ("content_length = '%s'\n", header
->content_length
);
69 printf ("content_type = '%s'\n", header
->content_type
);
70 printf ("date = '%s'\n", header
->date
);
71 printf ("expires = '%s'\n", header
->expires
);
72 printf ("from = '%s'\n", header
->from
);
73 printf ("if_modified_since = '%s'\n", header
->if_modified_since
);
74 printf ("last_modified = '%s'\n", header
->last_modified
);
75 printf ("location = '%s'\n", header
->location
);
76 printf ("pragma = '%s'\n", header
->pragma
);
77 printf ("referer = '%s'\n", header
->referer
);
78 printf ("server = '%s'\n", header
->server
);
79 printf ("user_agent = '%s'\n", header
->user_agent
);
80 printf ("www_authenticate = '%s'\n", header
->www_authenticate
);
85 char *find_sequence (char *data
, int len
, char *seq
, char **pdata
)
88 int size
= strlen (seq
);
91 for (i
= 0; i
< len
- size
+ 1; i
++) {
92 if (strncmp (data
+ i
, seq
, size
) == 0) {
95 *pdata
= data
+ i
+ size
;
104 /* response entity */
106 int add_line (char **buffer
, char *str
)
108 int len
= strlen (*buffer
) + strlen (str
) + 1;
109 *buffer
= realloc (*buffer
, len
);
110 strcat (*buffer
, str
);
114 int add_status_line (char **buffer
, code_t code
)
116 char tmp
[BUFFER_SIZE
] = {0};
119 sprintf (tmp
, "%s %s\r\n", HTTP_VERSION
, codes
[code
]);
120 add_line (buffer
, tmp
);
122 return strlen (*buffer
);
125 int add_general_header (char **buffer
)
127 char tmp
[BUFFER_SIZE
] = {0};
130 time_t ts
= time (NULL
);
131 sprintf (tmp
, "Date: %s\r\n", ctime (&ts
));
132 add_line (buffer
, tmp
);
136 return strlen (*buffer
);
139 int add_response_header (char **buffer
, char *uri
)
141 char tmp
[BUFFER_SIZE
] = {0};
144 sprintf (tmp
, "Location: %s\r\n", uri
);
145 add_line (buffer
, tmp
);
148 sprintf (tmp
, "Server: %s\r\n", SERVER_NAME
);
149 add_line (buffer
, tmp
);
151 /* WWW-Authentificate */
153 return strlen (*buffer
);
156 int add_entity (char **buffer
, unsigned char *entity
, int size
, char *type
, char *encoding
)
158 char tmp
[BUFFER_SIZE
] = {0};
159 int len
= strlen (*buffer
);
165 if (entity
!= NULL
) {
167 /* Content-Encoding */
168 if (encoding
!= NULL
) {
169 sprintf (tmp
, "Content-Encoding: %s\r\n", encoding
);
170 add_line (buffer
, tmp
);
174 sprintf (tmp
, "Content-Length: %d\r\n", size
);
175 add_line (buffer
, tmp
);
178 sprintf (tmp
, "Content-Type: %s\r\n", type
);
179 add_line (buffer
, tmp
);
181 add_line (buffer
, "\r\n");
184 len
= strlen (*buffer
);
185 *buffer
= realloc (*buffer
, len
+ size
);
186 memcpy (*buffer
+ len
, entity
, size
);
195 int error_400 (char **buffer
)
197 add_status_line (buffer
, c400
);
198 add_general_header (buffer
);
199 add_response_header (buffer
, NULL
);
201 char *response
= "<html><head><title>Error 400</title></head><body><p>Bad Request</p></body></html>";
202 return add_entity (buffer
, (unsigned char *)response
, strlen (response
), "text/html", "iso-8859-1");
207 int response_html (char **buffer
, char *location
, char *response
)
209 add_status_line (buffer
, c200
);
210 add_general_header (buffer
);
211 add_response_header (buffer
, location
);
213 return add_entity (buffer
, (unsigned char *)response
, strlen (response
), "text/html", "iso-8859-1");
218 char *trim (char *str
)
221 while ((*str
== ' ') || (*str
== '\t')) {
228 /* main HTTP processing */
230 int processing (char *data
, int len
, char **pdata
)
232 char *saved_data
= data
;
233 VERBOSE (DEBUG
, PRINT ("Start processing\n"));
236 char *line
= find_sequence (data
, len
, "\r\n", &data
);
238 VERBOSE (WARNING
, PRINT ("Unknown received data\n"));
244 VERBOSE (DEBUG
, PRINT ("Command line: '%s'\n", line
));
246 char *method
= strtok (line
, " ");
247 char *uri
= strtok (NULL
, " ");
248 char *version
= strtok (NULL
, " ");
249 method_t type
= not_supported_e
;
250 if (strcmp (method
, "GET") == 0) {
252 } else if (strcmp ("HEAD", method
) == 0) {
254 } else if (strcmp ("POST", method
) == 0) {
257 VERBOSE (WARNING
, PRINT ("Unkown method: %s\n", method
));
259 return error_400 (pdata
);
261 VERBOSE (INFO
, PRINT ("%s %s (%s)\n", (type
== get_e
) ? "Get" : (type
== head_e
) ? "Head" : "Post", uri
, version
));
264 header_t header
= {0};
265 while (strcmp (line
= find_sequence (data
, len
, "\r\n", &data
), "") != 0) {
266 VERBOSE (DEBUG
, PRINT ("Header line: '%s'\n", line
));
267 char *field
= strtok (line
, ":");
268 char *value
= trim (strtok (NULL
, "\r"));
269 VERBOSE (DEBUG
, PRINT ("Field: %s\nValue: %s\n", field
, value
));
274 VERBOSE (DEBUG
, PRINT ("Analyse field\n"));
275 if (strcmp (field
, "Allow") == 0) {
276 header
.allow
= value
;
277 } else if (strcmp (field
, "Authorization") == 0) {
278 header
.authorization
= value
;
279 } else if (strcmp (field
, "Content-Encoding") == 0) {
280 header
.content_encoding
= value
;
281 } else if (strcmp (field
, "Content-Length") == 0) {
282 header
.content_length
= value
;
283 } else if (strcmp (field
, "Content-Type") == 0) {
284 header
.content_type
= value
;
285 } else if (strcmp (field
, "Date") == 0) {
287 } else if (strcmp (field
, "Expires") == 0) {
288 header
.expires
= value
;
289 } else if (strcmp (field
, "From") == 0) {
291 } else if (strcmp (field
, "If-Modified-Since") == 0) {
292 header
.if_modified_since
= value
;
293 } else if (strcmp (field
, "Last-Modified") == 0) {
294 header
.last_modified
= value
;
295 } else if (strcmp (field
, "Location") == 0) {
296 header
.location
= value
;
297 } else if (strcmp (field
, "Pragma") == 0) {
298 header
.pragma
= value
;
299 } else if (strcmp (field
, "Referer") == 0) {
300 header
.referer
= value
;
301 } else if (strcmp (field
, "Server") == 0) {
302 header
.server
= value
;
303 } else if (strcmp (field
, "User-Agent") == 0) {
304 header
.user_agent
= value
;
305 } else if (strcmp (field
, "WWW-Authenticate") == 0) {
306 header
.www_authenticate
= value
;
308 VERBOSE (WARNING
, PRINT ("Unknown header field: '%s'\n", field
));
311 VERBOSE (DEBUG
, print_header_values (&header
));
313 /* processing data */
315 VERBOSE (DEBUG
, PRINT ("Processing data: %s\n", data
));
324 len
= response_html (pdata
, "http://localhost/", "<html><head><title>Test</title></head><body><p>This a test</p></body></html>");
330 case not_supported_e
:
337 /* vim: set ts=4 sw=4 et: */