X-Git-Url: https://secure.softndesign.org/git/?a=blobdiff_plain;f=http.c;h=fbd18ef87e67ba23e0ceabc2728e4d1c6d298e34;hb=7a559b2cdf3c9060af1645ae73420c4b91b19cf1;hp=dce3cc86d8a81686abd9d483b60d921a2a6ec63e;hpb=cae065477b8263c7bbbc532e1a5a4313aa535911;p=webserver.git diff --git a/http.c b/http.c index dce3cc8..fbd18ef 100644 --- a/http.c +++ b/http.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -59,6 +60,51 @@ typedef struct { char *www_authenticate; } header_t; +typedef struct { + char *ext; + char *type; + char *charset; +} mime_t; + +#define NB_MIMES 8 + +mime_t mimes[NB_MIMES] = { + {"js", "application/javascript", "iso-8859-1"}, + {"css", "text/css", "iso-8859-1"}, + {"htm", "text/html", "iso-8859-1"}, + {"html", "text/html", "iso-8859-1"}, + {"png", "image/png", NULL}, + {"jpeg", "image/jpeg", NULL}, + {"jpg", "image/jpeg", NULL}, + {"txt", "text/plain", "iso-8859-1"} +}; + +/* find mime type */ + +mime_t *find_mime_type (char *filename) +{ + /* find extention */ + char *ext = filename + strlen (filename); + while (--ext > filename) { + if (ext[-1] == '.') { + break; + } + } + if (ext == filename) { + return NULL; + } + + /* find mime */ + int i; + for (i = 0; i < NB_MIMES; i++) { + if (strcmp (ext, (mimes + i)->ext) == 0) { + return mimes + i; + } + } + + return NULL; +} + /* print header values */ void print_header_values (header_t *header) @@ -107,9 +153,16 @@ char *find_sequence (char *data, int len, char *seq, char **pdata) int add_line (char **buffer, char *str) { - int len = strlen (*buffer) + strlen (str) + 1; - *buffer = realloc (*buffer, len); + VERBOSE (DEBUG, PRINT ("add line: %s\n", str)); + int len = ((*buffer) ? strlen (*buffer) : 0) + strlen (str) + 3; + VERBOSE (DEBUG, PRINT ("len: %d\n", len)); + if (*buffer) { + *buffer = (char *)realloc (*buffer, len); + } else { + *buffer = (char *)calloc (len, 1); + } strcat (*buffer, str); + strcat (*buffer, "\r\n"); return len; } @@ -118,7 +171,7 @@ int add_status_line (char **buffer, code_t code) char tmp[BUFFER_SIZE] = {0}; /* Status */ - sprintf (tmp, "%s %s\r\n", HTTP_VERSION, codes[code]); + sprintf (tmp, "%s %s", HTTP_VERSION, codes[code]); add_line (buffer, tmp); return strlen (*buffer); @@ -130,7 +183,8 @@ int add_general_header (char **buffer) /* Date */ time_t ts = time (NULL); - sprintf (tmp, "Date: %s\r\n", ctime (&ts)); + sprintf (tmp, "Date: %s", ctime (&ts)); + tmp[strlen (tmp) - 1] = 0; // remove last \n add_line (buffer, tmp); /* Pragma */ @@ -143,11 +197,11 @@ int add_response_header (char **buffer, char *uri) char tmp[BUFFER_SIZE] = {0}; /* Location */ - sprintf (tmp, "Location: %s\r\n", uri); + sprintf (tmp, "Location: %s", uri); add_line (buffer, tmp); /* Server */ - sprintf (tmp, "Server: %s\r\n", SERVER_NAME); + sprintf (tmp, "Server: %s", SERVER_NAME); add_line (buffer, tmp); /* WWW-Authentificate */ @@ -168,19 +222,19 @@ int add_entity (char **buffer, char *entity, int size, char *type, char *encodin /* Content-Encoding */ if (encoding != NULL) { - sprintf (tmp, "Content-Encoding: %s\r\n", encoding); + sprintf (tmp, "Content-Encoding: %s", encoding); add_line (buffer, tmp); } /* Content-Length */ - sprintf (tmp, "Content-Length: %d\r\n", size); + sprintf (tmp, "Content-Length: %d", size); add_line (buffer, tmp); /* Content-Type */ - sprintf (tmp, "Content-Type: %s\r\n", type); + sprintf (tmp, "Content-Type: %s", type); add_line (buffer, tmp); - add_line (buffer, "\r\n"); + add_line (buffer, ""); /* Entity */ len = strlen (*buffer); @@ -216,15 +270,21 @@ int error_404 (char **buffer, char *uri) return add_entity (buffer, response, strlen (response), "text/html", "iso-8859-1"); } -/* response html */ +/* generic response */ -int response_html (char **buffer, char *location, char *response) +int generic_response (char **buffer, char *location, char *response, int size) { - add_status_line (buffer, c200); - add_general_header (buffer); - add_response_header (buffer, location); - - return add_entity (buffer, response, strlen (response), "text/html", "iso-8859-1"); + int len = 0; + VERBOSE (DEBUG, PRINT ("add_status_line %d\n", len)); + len = add_status_line (buffer, c200); + VERBOSE (DEBUG, PRINT ("add_general_header %d\n", len)); + len = add_general_header (buffer); + VERBOSE (DEBUG, PRINT ("add_response_header %d\n", len)); + len = add_response_header (buffer, location); + mime_t *mime = find_mime_type (location); + + VERBOSE (DEBUG, PRINT ("add_entity %d\n", len)); + return add_entity (buffer, response, size, mime->type, mime->charset); } /* trim string */ @@ -241,13 +301,14 @@ char *trim (char *str) /* main HTTP processing */ -int processing (char *data, int len, char *root, char **pdata) +int processing (char *data, int len, conf_t *conf, char **pdata) { char *saved_data = data; + char location[BUFFER_SIZE] = {0}; VERBOSE (DEBUG, PRINT ("Start processing\n")); /* check method */ - char *line = find_sequence (data, len, "\r\n", &data); + char *line = find_sequence (data, len + data - saved_data, "\r\n", &data); if (line == NULL) { VERBOSE (WARNING, PRINT ("Unknown received data\n")); if (pdata != NULL) { @@ -269,19 +330,20 @@ int processing (char *data, int len, char *root, char **pdata) type = post_e; } else { VERBOSE (WARNING, PRINT ("Unkown method: %s\n", method)); - 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)); /* analyse uri */ - char *filename = calloc (strlen (root) + strlen (uri) + 2, 1); - //sprintf (filename, "%s%s%s", root, ((root[strlen (root) - 1] != '/') && (uri[0] != '/')) ? "/" : "", uri); - sprintf (filename, "%s/%s", root, uri); + char *filename = strtok (uri, "&"); + char *variables = strtok (NULL, "\n"); + char *path = (char *) calloc (strlen (conf->root) + strlen (filename) + 2, 1); + //sprintf (filename, "%s%s%s", conf->root, ((conf->root[strlen (conf->root) - 1] != '/') && (uri[0] != '/')) ? "/" : "", uri); + sprintf (path, "%s/%s", conf->root, filename); /* check header */ header_t header = {0}; - while (strcmp (line = find_sequence (data, len, "\r\n", &data), "") != 0) { + while (strcmp (line = find_sequence (data, len + data - saved_data, "\r\n", &data), "") != 0) { VERBOSE (DEBUG, PRINT ("Header line: '%s'\n", line)); char *field = strtok (line, ":"); char *value = trim (strtok (NULL, "\r")); @@ -291,72 +353,72 @@ int processing (char *data, int len, char *root, char **pdata) } 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)); - } + 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)); + /* body */ + char *body = data; + len -= saved_data - data; + if (len != (header.content_length ? atoi (header.content_length) : 0)) { + VERBOSE (WARNING, PRINT ("Incoherent size (%d <> %s)\n", len, header.content_length)); } /* response */ char *buffer = NULL; + FILE *fid = NULL; switch (type) { case get_e: - len = readfile (&buffer, filename); - if (len == 0) { - len = error_404 (pdata, "http://localhost/"); + case post_e: /* fall through */ + VERBOSE (DEBUG, PRINT ("Read file %s\n", path)); + len = readfile (&buffer, path); + if (len < 0) { + sprintf (location, "http://%s/", conf->servername); + len = error_404 (pdata, location); } else { - len = response_html (pdata, "http://localhost/", buffer); + sprintf (location, "http://%s%s", conf->servername, path); + len = generic_response (pdata, location, buffer, len); free (buffer); } break; case head_e: - break; - case post_e: + VERBOSE (DEBUG, PRINT ("Test file %s\n", path)); + fid = fopen (path, "rb"); + if (fid == NULL) { + sprintf (location, "http://%s/", conf->servername); + len = error_404 (pdata, location); + } else { + fclose (fid); + sprintf (location, "http://%s%s", conf->servername, path); + len = generic_response (pdata, location, NULL, 0); + } break; case not_supported_e: break; } /* cleaning */ - free (saved_data); - free (filename); + VERBOSE (DEBUG, PRINT ("Cleaning\n")); + if (path) { + VERBOSE (DEBUG, PRINT ("Cleaning path\n")); + free (path); + } return len; }