X-Git-Url: https://secure.softndesign.org/git/?a=blobdiff_plain;f=http.c;h=22b5cbcbbf901c169ca439bbcd45b97f837d1c8c;hb=HEAD;hp=6ce72c05854f61204aba636b0036b5d2f8e5978c;hpb=2bec4aa77cff1669f0c29d1ca426e4fa714b0928;p=webserver.git diff --git a/http.c b/http.c index 6ce72c0..22b5cbc 100644 --- a/http.c +++ b/http.c @@ -1,6 +1,8 @@ #include +#include #include #include +#include #include "debug.h" #include "file.h" @@ -40,10 +42,14 @@ typedef enum { not_supported_e = 0, get_e, head_e, post_e } method_t; +typedef enum { + encoding_plain_e = 0, encoding_gzip_e, encoding_compress_e +} encoding_t; + typedef struct { char *allow; char *authorization; - char *content_encoding; + encoding_t content_encoding; char *content_length; char *content_type; char *date; @@ -111,7 +117,14 @@ void print_header_values (header_t *header) printf ("Header values\n"); if (header->allow) printf ("allow = '%s'\n", header->allow); if (header->authorization) printf ("authorization = '%s'\n", header->authorization); - if (header->content_encoding) printf ("content_encoding = '%s'\n", header->content_encoding); + if (header->content_encoding) { + printf ("content_encoding = "); + switch (header->content_encoding) { + case encoding_plain_e: printf ("plain\n"); break; + case encoding_gzip_e: printf ("gzip\n"); break; + case encoding_compress_e: printf ("compress\n"); break; + } + } if (header->content_length) printf ("content_length = '%s'\n", header->content_length); if (header->content_type) printf ("content_type = '%s'\n", header->content_type); if (header->date) printf ("date = '%s'\n", header->date); @@ -221,7 +234,7 @@ int add_entity (char **buffer, char *entity, int size, char *type, char *encodin /* Content-Encoding */ if (encoding != NULL) { - sprintf (tmp, "Content-Encoding: %sn", encoding); + sprintf (tmp, "Content-Encoding: %s", encoding); add_line (buffer, tmp); } @@ -298,15 +311,25 @@ char *trim (char *str) return str; } +/* creqte command */ + +char *createcommand (char *format, char *name) +{ + char *command = (char *) calloc (strlen (format) + strlen (name) + 1, 1); + sprintf (command, format, name); + return command; +} + /* main HTTP processing */ 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) { @@ -333,13 +356,15 @@ int processing (char *data, int len, conf_t *conf, char **pdata) VERBOSE (INFO, PRINT ("%s %s (%s)\n", (type == get_e) ? "Get" : (type == head_e) ? "Head" : "Post", uri, version)); /* analyse uri */ - char *filename = (char *)calloc (strlen (conf->root) + strlen (uri) + 2, 1); + 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 (filename, "%s/%s", conf->root, 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")); @@ -347,65 +372,124 @@ int processing (char *data, int len, conf_t *conf, char **pdata) 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)); - } + if (strcmp (field, "Allow") == 0) { header.allow = value; } + else if (strcmp (field, "Authorization") == 0) { header.authorization = value; } + else if (strcmp (field, "Content-Encoding") == 0) { + if (strcmp (value, "x-gzip") == 0) { + header.content_encoding = encoding_gzip_e; + } else if (strcmp (value, "x-compress") == 0) { + header.content_encoding = encoding_compress_e; + } else { + VERBOSE (WARNING, PRINT ("Unknown content encoding: %s\n", 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)); + /* body */ + char *body = data; + char *newbody = NULL; + 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)); + } + if (len > 0) { + int i; + char *fcomp= NULL; + char *fdecomp = NULL; + char *command = NULL; + + switch (header.content_encoding) { + case encoding_plain_e: + break; + + case encoding_gzip_e: + fcomp = tempname (conf->temp, ".gz"); + writefile (fcomp, body, len); + command = createcommand ("gunzip %s", fcomp); + system (command); + fdecomp = strdup (fcomp); + for (i = strlen (fdecomp) - 1; i > 0; i--) { + if (fdecomp[i] == '.') { + fdecomp[i] = 0; + break; + } + } + len = readfile (&newbody, fdecomp); + break; + + case encoding_compress_e: + fcomp = tempname (conf->temp, ".Z"); + writefile (fcomp, body, len); + command = createcommand ("compress %s", fcomp); + system (command); + fdecomp = strdup (fcomp); + for (i = strlen (fdecomp) - 1; i > 0; i--) { + if (fdecomp[i] == '.') { + fdecomp[i] = 0; + break; + } + } + len = readfile (&newbody, fdecomp); + break; + } + + if (fcomp) { + unlink (fcomp); + free (fcomp); + } + if (fdecomp) { + unlink (fdecomp); + free (fdecomp); + } + if (command) { + free (command); + } + } + /* response */ char *buffer = NULL; + FILE *fid = NULL; switch (type) { case get_e: - VERBOSE (DEBUG, PRINT ("Read file %s\n", filename)); - len = readfile (&buffer, filename); - if (len == 0) { + 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 { - sprintf (location, "http://%s%s", conf->servername, filename); + 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 ("Write file %s\n", filename)); + 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; @@ -413,9 +497,11 @@ int processing (char *data, int len, conf_t *conf, char **pdata) /* cleaning */ VERBOSE (DEBUG, PRINT ("Cleaning\n")); - if (filename) { - VERBOSE (DEBUG, PRINT ("Cleaning filename\n")); - free (filename); + if (path) { + free (path); + } + if (newbody) { + free (newbody); } return len;