feat: new file management utility, splitted http into http and http headers, new string function (to_lowercase) + other small things

This commit is contained in:
Gu://em_ 2025-11-24 22:51:53 +01:00
parent 573e53ef79
commit 5236d71e7e
9 changed files with 269 additions and 67 deletions

View file

@ -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) \

86
httpd/src/http/headers.c Normal file
View file

@ -0,0 +1,86 @@
#include "headers.h"
#include <stdlib.h>
#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;
}

62
httpd/src/http/headers.h Normal file
View file

@ -0,0 +1,62 @@
#ifndef HEADERS_H
#define HEADERS_H
#include <stddef.h>
#include <sys/types.h>
#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

View file

@ -5,45 +5,10 @@
#include <string.h>
#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,36 +60,31 @@ 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;
// === Functions
while (req->data[i] != '\n') // ! Blank line
{
// Read field
ssize_t nread = read_field(req, offset, &res->field);
// 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 nread; // Contains error code when negative
return NULL;
i += nread;
// Read value
nread = read_value(req, offset, &res->value);
// Headers
nread = parse_headers(res, req, i);
if (nread <= 0)
return nread; // Contains error code when negative
return NULL;
i += nread + 1;
}
return i + 1;
return res;
}
// === Functions
// struct http_request *parse_request(struct string *req)
// {}
// struct http_response *generate_response(struct http_request *req)
// {}

View file

@ -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();

View file

@ -0,0 +1,31 @@
#include "files.h"
#include <stdio.h>
#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)))
}

View file

@ -0,0 +1,42 @@
#ifndef FILES_H
#define FILES_H
// === Definitions
#define BUFFER_SIZE 1024
// === Includes
#include <stdbool.h>
#include <stddef.h>
// === 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

View file

@ -1,5 +1,6 @@
#include "string.h"
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
@ -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)

View file

@ -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 */