#include "http.h"
-int processing (unsigned char *data, int len, unsigned char **pdata) {
- *pdata = data;
+#define HTTP_VERSION "HTTP/1.0"
+#define SERVER_NAME "Webserver/0.0.1"
+
+char **codes = {
+ "200 OK",
+ "201 Created",
+ "202 Accepted",
+ "204 No Content",
+ "301 Moved Permanently",
+ "302 Moved Temporarily",
+ "304 Not Modified",
+ "400 Bad Request",
+ "401 Unauthorized",
+ "403 Forbidden",
+ "404 Not Found",
+ "500 Internal Server Error",
+ "501 Not Implemented",
+ "502 Bad Gateway",
+ "503 Service Unavailable"};
+
+typedef enum {
+ c200 = 0, c201, c202, c204,
+ c301, c302, c304, c400,
+ c401, c403, c404, c500,
+ c501, c502, c503
+} code_t;
+
+typedef enum {
+ not_supported_e = 0, get_e, head_e, post_e
+} method_t;
+
+typedef struct {
+ char *allow;
+ char *authorization;
+ char *content_encoding;
+ char *content_length;
+ char *content_type;
+ char *date;
+ char *expires;
+ char *from;
+ char *if_modified_since;
+ char *last_modified;
+ char *location;
+ char *pragma;
+ char *referer;
+ char *server;
+ char *user_agent;
+ char *www_authenticate;
+} header_t;
+
+/* print header values */
+
+void print_header_values (header_t *header)
+{
+ printf ("allow = '%s'\n", header->allow);
+ printf ("authorization = '%s'\n", header->authorization);
+ printf ("content_encoding = '%s'\n", header->content_encoding);
+ printf ("content_length = '%s'\n", header->content_length);
+ printf ("content_type = '%s'\n", header->content_type);
+ printf ("date = '%s'\n", header->date);
+ printf ("expires = '%s'\n", header->expires);
+ printf ("from = '%s'\n", header->from);
+ printf ("if_modified_since = '%s'\n", header->if_modified_since);
+ printf ("last_modified = '%s'\n", header->last_modified);
+ printf ("location = '%s'\n", header->location);
+ printf ("pragma = '%s'\n", header->pragma);
+ printf ("referer = '%s'\n", header->referer);
+ printf ("server = '%s'\n", header->server);
+ printf ("user_agent = '%s'\n", header->user_agent);
+ printf ("www_authenticate = '%s'\n", header->www_authenticate);
+}
+
+/* find sequence*/
+
+char *find_sequence (char *data, int len, char *seq, char **pdata)
+{
+
+ int size = strlen (seq);
+
+ int i;
+ for (i = 0; i < len - size + 1; i++) {
+ if (strncmp (data + i, seq, size) == 0) {
+ data[i] = 0;
+ if (pdata != NULL) {
+ *pdata = data + i + size;
+ }
+ return data;
+ }
+ }
+
+ return NULL;
+}
+
+/* response entity */
+
+int add_status_line (char **buffer, int len)
+{
return len;
}
+int add_general_header (char **buffer, int len)
+{
+ return len;
+}
+
+int add_response_header (char **buffer, int len)
+{
+ return len;
+}
+
+int add_entity (char **buffer, int len, unsigned char *entity, int size, char *type)
+{
+ return len;
+}
+
+/* error 400 */
+
+int error_400 (char **buffer)
+{
+
+}
+
+/* trim string */
+
+char *trim (char *str)
+{
+ if (str != NULL) {
+ while ((*str == ' ') || (*str == '\t')) {
+ str++;
+ }
+ }
+ return str;
+}
+
+/* main HTTP processing */
+
+int processing (char *data, int len, char **pdata)
+{
+ char *saved_data = data;
+ VERBOSE (DEBUG, PRINT ("Start processing\n"));
+
+ /* check method */
+ char *line = find_sequence (data, len, "\r\n", &data);
+ if (line == NULL) {
+ VERBOSE (WARNING, PRINT ("Unknown received data\n"));
+ if (pdata != NULL) {
+ *pdata = NULL;
+ }
+ return 0;
+ }
+ VERBOSE (DEBUG, PRINT ("Command line: '%s'\n", line));
+
+ char *method = strtok (line, " ");
+ char *uri = strtok (NULL, " ");
+ char *version = strtok (NULL, " ");
+ method_t type = not_supported_e;
+ if (strcmp (method, "GET") == 0) {
+ type = get_e;
+ } else if (strcmp ("HEAD", method) == 0) {
+ type = head_e;
+ } else if (strcmp ("POST", method) == 0) {
+ type = post_e;
+ } else {
+ VERBOSE (WARNING, PRINT ("Unkown method: %s\n", method));
+ } else {
+ free (saved_data);
+ return error_400 (pdata);
+ }
+ VERBOSE (INFO, PRINT ("%s %s (%s)\n", (type == get_e) ? "Get" : (type == head_e) ? "Head" : "Post", uri, version));
+
+ /* check header */
+ header_t header = {0};
+ while (strcmp (line = find_sequence (data, len, "\r\n", &data), "") != 0) {
+ VERBOSE (DEBUG, PRINT ("Header line: '%s'\n", line));
+ char *field = strtok (line, ":");
+ char *value = trim (strtok (NULL, "\r"));
+ VERBOSE (DEBUG, PRINT ("Field: %s\nValue: %s\n", field, value));
+ if (*line == 0) {
+ break;
+ }
+
+ VERBOSE (DEBUG, PRINT ("Analyse field\n"));
+ if (strcmp (field, "Allow") == 0) {
+ header.allow = value;
+ } else if (strcmp (field, "Authorization") == 0) {
+ header.authorization = value;
+ } else if (strcmp (field, "Content-Encoding") == 0) {
+ header.content_encoding = value;
+ } else if (strcmp (field, "Content-Length") == 0) {
+ header.content_length = value;
+ } else if (strcmp (field, "Content-Type") == 0) {
+ header.content_type = value;
+ } else if (strcmp (field, "Date") == 0) {
+ header.date = value;
+ } else if (strcmp (field, "Expires") == 0) {
+ header.expires = value;
+ } else if (strcmp (field, "From") == 0) {
+ header.from = value;
+ } else if (strcmp (field, "If-Modified-Since") == 0) {
+ header.if_modified_since = value;
+ } else if (strcmp (field, "Last-Modified") == 0) {
+ header.last_modified = value;
+ } else if (strcmp (field, "Location") == 0) {
+ header.location = value;
+ } else if (strcmp (field, "Pragma") == 0) {
+ header.pragma = value;
+ } else if (strcmp (field, "Referer") == 0) {
+ header.referer = value;
+ } else if (strcmp (field, "Server") == 0) {
+ header.server = value;
+ } else if (strcmp (field, "User-Agent") == 0) {
+ header.user_agent = value;
+ } else if (strcmp (field, "WWW-Authenticate") == 0) {
+ header.www_authenticate = value;
+ } else {
+ VERBOSE (WARNING, PRINT ("Unknown header field: '%s'\n", field));
+ }
+ }
+ VERBOSE (DEBUG, print_header_values (&header));
+
+ /* processing data */
+ if (data) {
+ VERBOSE (DEBUG, PRINT ("Processing data: %s\n", data));
+ }
+
+ /* cleaning */
+ free (saved_data);
+
+ /* response */
+ *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>");
+ return strlen (*pdata);
+}
+
/* vim: set ts=4 sw=4 et: */