diff --git a/httpd/Makefile b/httpd/Makefile index 731ffac..36eeedf 100644 --- a/httpd/Makefile +++ b/httpd/Makefile @@ -9,10 +9,12 @@ ASAN_DBG_FLAGS = -fsanitize=address UTILS_SRCS = src/utils/string/string.c \ src/utils/time/fmt_time.c \ src/utils/parsing/words.c \ - src/utils/parsing/blanks.c + src/utils/parsing/blanks.c \ + utils/files/files.c MODULES_SRCS = src/config/config.c \ src/server/server.c \ src/http/http.c \ + src/http/headers.c \ src/logger/logs.c \ src/logger/errors.c SRCS = $(UTILS_SRCS) \ diff --git a/httpd/src/http/headers.c b/httpd/src/http/headers.c new file mode 100644 index 0000000..29ba0a2 --- /dev/null +++ b/httpd/src/http/headers.c @@ -0,0 +1,86 @@ +#include "headers.h" + +#include + +#include "../utils/parsing/words.h" + +void destroy_headers(struct http_header *headers) +{ + while (headers != NULL) + { + struct http_header *next = headers->next; + free(headers); + headers = next; + } +} + +ssize_t read_field(struct string *str, size_t offset, struct string **res) +{ + ssize_t nread = read_word_delim(str, offset, res, ":\n"); + if (nread <= 0) + return ERR_HTTP_INVALID_INPUT; + + if (str->size <= offset + nread || str->data[offset + nread] != ':') + return ERR_HTTP_INVALID_INPUT; + + string_to_lowercase(*res); + + return nread; +} + +ssize_t read_value(struct string *str, size_t offset, struct string **res) +{ + ssize_t nread = read_word_delim(str, offset, res, "\n"); + if (nread <= 0) + return ERR_HTTP_INVALID_INPUT; + + if (str->size <= offset + nread || str->data[offset + nread] != '\n') + return ERR_HTTP_INVALID_INPUT; + + return nread; +} + +ssize_t parse_headers(struct http_request *res, struct string *req, + size_t offset) +{ + size_t i = offset; + struct http_header *header = NULL; + + // Yes I know I do one useless allocation but I really don't care at this + // point + while (req->data[i] != '\n') // ! Blank line + { + if (header == NULL) + { + // Init list + header = calloc(1, sizeof(struct http_header)); + res->headers = header; + } + else + { + // Append + header->next = calloc(1, sizeof(struct http_header)); + header = header->next; + } + + // Check allocation + if (header == NULL) + return ERR_HTTP_OUT_OF_MEMORY; + + // Read field + ssize_t nread = read_field(req, offset, &header->field); + if (nread <= 0) + return nread; // Contains error code when negative + + i += nread; + + // Read value + nread = read_value(req, offset, &header->value); + if (nread <= 0) + return nread; // Contains error code when negative + + i += nread + 1; + } + + return i + 1; +} diff --git a/httpd/src/http/headers.h b/httpd/src/http/headers.h new file mode 100644 index 0000000..9bbd0a5 --- /dev/null +++ b/httpd/src/http/headers.h @@ -0,0 +1,62 @@ +#ifndef HEADERS_H +#define HEADERS_H + +#include +#include + +#include "http.h" + +// === Functions + +/* + * @brief + * + * @param headers + */ +void destroy_headers(struct http_header *headers); + +/* + * @brief + * + * @param str + * @param offset + * @param res + * + * @return + */ +ssize_t read_field(struct string *str, size_t offset, struct string **res); + +/* + * @brief + * + * @param str + * @param offset + * @param res + * + * @return + */ +ssize_t read_value(struct string *str, size_t offset, struct string **res); + +/* + * @brief + * + * @param res + * @param req + * @param offset + * + * @return + */ +ssize_t parse_headers(struct http_request *res, struct string *req, + size_t offset); + +/* + * @brief + * + * @param headers + * @param field + * + * @return + */ +struct http_header* get_header(struct http_header *headers, const char* field); + +#endif // ! HEADERS_H diff --git a/httpd/src/http/http.c b/httpd/src/http/http.c index 8b7c707..17291d4 100644 --- a/httpd/src/http/http.c +++ b/httpd/src/http/http.c @@ -5,45 +5,10 @@ #include #include "../utils/parsing/words.h" +#include "headers.h" // === Static functions -static void destroy_headers(struct http_header *headers) -{ - while (headers != NULL) - { - struct http_header *next = headers->next; - free(headers); - headers = next; - } -} - -static ssize_t read_field(struct string *str, size_t offset, - struct string **res) -{ - ssize_t nread = read_word_delim(str, offset, res, ":\n"); - if (nread <= 0) - return ERR_HTTP_INVALID_INPUT; - - if (str->size <= offset + nread || str->data[offset + nread] != ':') - return ERR_HTTP_INVALID_INPUT; - - return nread; -} - -static ssize_t read_value(struct string *str, size_t offset, - struct string **res) -{ - ssize_t nread = read_word_delim(str, offset, res, "\n"); - if (nread <= 0) - return ERR_HTTP_INVALID_INPUT; - - if (str->size <= offset + nread || str->data[offset + nread] != '\n') - return ERR_HTTP_INVALID_INPUT; - - return nread; -} - // Parses the status line of req, stores the result in res and returns the // number of read characters or a negative number on error // WARNING res must be pre allocated @@ -95,35 +60,30 @@ static ssize_t parse_reqline(struct http_request *res, struct string *req) return i; } -static ssize_t parse_headers(struct http_header *res, struct string *req, - size_t offset) -{ - size_t i = offset; - - while (req->data[i] != '\n') // ! Blank line - { - // Read field - ssize_t nread = read_field(req, offset, &res->field); - if (nread <= 0) - return nread; // Contains error code when negative - - i += nread; - - // Read value - nread = read_value(req, offset, &res->value); - if (nread <= 0) - return nread; // Contains error code when negative - - i += nread + 1; - } - - return i + 1; -} - // === Functions -// struct http_request *parse_request(struct string *req) -// {} +// TODO handle logs and free adequately +struct http_request *parse_request(struct string *req) +{ + struct http_request *res = calloc(1, sizeof(struct http_request)); + if (res == NULL) + return NULL; + + // Status line + size_t i = 0; + ssize_t nread = parse_reqline(res, req); + if (nread <= 0) + return NULL; + + i += nread; + + // Headers + nread = parse_headers(res, req, i); + if (nread <= 0) + return NULL; + + return res; +} // struct http_response *generate_response(struct http_request *req) // {} diff --git a/httpd/src/logger/errors.h b/httpd/src/logger/errors.h index 718a652..2543fc3 100644 --- a/httpd/src/logger/errors.h +++ b/httpd/src/logger/errors.h @@ -15,13 +15,10 @@ void errlog_init(bool enabled, FILE *logfile_stream); void print_err(); /* @brief Prints error logs, just like print_log(), and also to stderr - * */ void print_log_err(char* format, ...); /* @brief Prints error logs, just like print_log() - * - * */ char* get_err(); diff --git a/httpd/src/utils/files/files.c b/httpd/src/utils/files/files.c new file mode 100644 index 0000000..0729041 --- /dev/null +++ b/httpd/src/utils/files/files.c @@ -0,0 +1,31 @@ +#include "files.h" + +#include + +#include "../string/string.h" + +bool file_exists(const char *path) +{} + +bool is_directory(const char *path) +{} + +// TODO handle logging +struct string *get_file_content(const char *path) +{ + // Open file + FILE *stream = fopen(path, "r"); + if (stream == NULL) + return NULL; + + // Alloc result + char buf[BUFFER_SIZE]; + struct string *res = string_create(NULL, 0); + if (res == NULL) + { + return NULL; + } + + int nread; + while ((fgets(buf, BUFFER_SIZE, stream))) +} diff --git a/httpd/src/utils/files/files.h b/httpd/src/utils/files/files.h new file mode 100644 index 0000000..b44133b --- /dev/null +++ b/httpd/src/utils/files/files.h @@ -0,0 +1,42 @@ +#ifndef FILES_H +#define FILES_H + +// === Definitions + +#define BUFFER_SIZE 1024 + +// === Includes + +#include +#include + +// === Functions + +/* + * @brief + * + * @param path + * + * @return + */ +bool file_exists(const char *path); + +/* + * @brief + * + * @param path + * + * @return + */ +bool is_directory(const char* path); + +/* + * @brief + * + * @param path + * + * @return + */ +struct string* get_file_content(const char *path); + +#endif // ! FILES_H diff --git a/httpd/src/utils/string/string.c b/httpd/src/utils/string/string.c index 68914b5..2b62c90 100644 --- a/httpd/src/utils/string/string.c +++ b/httpd/src/utils/string/string.c @@ -1,5 +1,6 @@ #include "string.h" +#include #include #include @@ -64,6 +65,15 @@ void string_concat_str(struct string *str, const char *to_concat, size_t size) } } +void string_to_lowercase(struct string *str) +{ + for (size_t i = 0; i < str->size; i++) + { + if (isupper(str->data[i])) + str->data[i] += 'a' - 'A'; + } +} + void string_destroy(struct string *str) { if (str != NULL) diff --git a/httpd/src/utils/string/string.h b/httpd/src/utils/string/string.h index afe6d9d..74572c0 100644 --- a/httpd/src/utils/string/string.h +++ b/httpd/src/utils/string/string.h @@ -42,6 +42,18 @@ int string_compare_n_str(const struct string *str1, const char *str2, size_t n); */ void string_concat_str(struct string *str, const char *to_concat, size_t size); +/* + ** @brief Concat a char * with its size in a struct string + ** + ** @param str + */ +void string_to_lowercase(struct string *str); + +/* + ** @brief Free all string content + ** + ** @param str + */ void string_destroy(struct string *str); #endif /* ! STRING_H */