feat: OK là ça fait trop je sais mm plus combien j'ai changé de trucs, RENDEZ LES PUSH DE LA MAISON

This commit is contained in:
Gu://em_ 2025-11-26 15:01:04 +01:00
parent 2255bfc2e2
commit 1771f72ecb
12 changed files with 288 additions and 49 deletions

View file

@ -50,6 +50,10 @@ static void print_help(char *program_name)
// limit imposed by school
static int parse_daemon_arg(struct config *cfg)
{
// Multiple contradictory parameters
if (cfg->daemon != NO_OPTION)
return ARG_INVALID;
if (strcmp(optarg, "start") == 0)
cfg->daemon = START;
else if (strcmp(optarg, "stop") == 0)

View file

@ -2,6 +2,7 @@
#define CONFIG_H
#define _XOPEN_SOURCE 500
#define HTTP_VERSION "HTTP/1.1"
#include <stdbool.h>
@ -32,6 +33,7 @@ struct config
char *pid_file;
char *log_file;
bool log;
char* protocol_version;
struct server_config *servers;
enum daemon daemon;

View file

@ -7,7 +7,7 @@
*
* @param
*/
void stop_daemon(int pid);
void stop_daemon();
/* @brief
*
@ -21,6 +21,6 @@ int start_daemon(void);
*
* @return
*/
int restart_daemon(int pid);
int restart_daemon();
#endif // ! DAEMON_H

View file

@ -1,6 +1,8 @@
#include "headers.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../utils/parsing/words.h"
@ -84,3 +86,49 @@ ssize_t parse_headers(struct http_request *res, struct string *req,
return i + 1;
}
struct http_header *create_header(const char *field, const char *value)
{
struct http_header *res = calloc(1, sizeof(struct http_header));
if (res == NULL)
return NULL;
// Field
ssize_t field_size = strlen(field);
if (field_size < 0)
{
free(res);
return NULL;
}
res->field = string_create(field, field_size);
// Value
ssize_t value_size = strlen(value);
if (value_size < 0)
{
string_destroy(res->field);
free(res);
return NULL;
}
res->value = string_create(value, value_size);
return res;
}
void append_header(struct http_header **list, struct http_header *element)
{
if (list == NULL)
return;
if (*list == NULL)
*list = element;
else
{
struct http_header *cur_elt = *list;
while (cur_elt->next != NULL)
{
cur_elt = cur_elt->next;
}
cur_elt->next = element;
}
}

View file

@ -59,4 +59,24 @@ ssize_t parse_headers(struct http_request *res, struct string *req,
*/
struct http_header* get_header(struct http_header *headers, const char* field);
/*
* @brief
*
* @param field
* @param value
*
* @return
*/
struct http_header* create_header(const char* field, const char* value);
/*
* @brief
*
* @param field
* @param value
*
* @return
*/
void append_header(struct http_header **list, struct http_header *element);
#endif // ! HEADERS_H

View file

@ -1,11 +1,14 @@
#include "http.h"
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../utils/files/files.h"
#include "../utils/parsing/words.h"
#include "../utils/time/fmt_time.h"
#include "headers.h"
// === Static variables
@ -45,7 +48,7 @@ static ssize_t parse_reqline(struct http_request *res, struct string *req)
return ERR_HTTP_INVALID_INPUT;
// Target (path)
skipped += read_word(req, i, &res->path);
skipped += read_word(req, i, &res->target);
if (skipped <= 0)
return ERR_HTTP_INVALID_INPUT;
@ -58,29 +61,81 @@ static ssize_t parse_reqline(struct http_request *res, struct string *req)
if (skipped <= 0)
return ERR_HTTP_INVALID_INPUT;
// EOL
if (req->data[i++] != '\n')
// CRLF (EOL)
if (req->data[i++] != '\r' && req->data[i++] != '\n')
return ERR_HTTP_INVALID_INPUT;
return i;
}
// Split target into path and queries
static void split_target(struct http_request *req)
{
size_t i = 0;
while (i < req->path->size)
while (i < req->target->size)
{
if (req->path->data[i] == '?')
if (req->target->data[i] == '?')
{
req->queries =
string_create(req->path->data + i, req->path->size - i);
req->path->size = i;
string_create(req->target->data + i, req->target->size - i);
req->target->size = i;
return;
}
i++;
}
}
// Finds a valid path based on the client input
static bool find_target(struct http_request *req)
{
// Check filename
if (!check_filename(req->target))
return false;
int err = is_directory(req->target->data);
if (err == -1)
return false;
else if (err == 1)
{
if (req->target->data[req->target->size - 1] != '/')
string_concat_str(req->target, "/", 1);
string_concat_str(req->target, config->servers->default_file,
strlen(config->servers->default_file));
}
return true;
}
static struct string *generate_status_message(int status_code)
{
char *message;
switch (status_code)
{
case 200:
message = "OK";
break;
case 400:
message = "Bad Request";
break;
case 403:
message = "Forbidden";
break;
case 404:
message = "Not Found";
break;
case 405:
message = "Method Not Allowed";
break;
case 505:
message = "HTTP Version Not Supported";
break;
default:
message = "WTF";
}
return string_create(message, strlen(message));
}
// === Functions
void http_init(struct config *cfg)
@ -117,31 +172,84 @@ struct http_request *parse_request(struct string *req)
// TODO handle logs and free adequately
struct http_response *generate_response(struct http_request *req)
{
// Path
// Malloc
struct http_response *res = calloc(1, sizeof(struct http_response));
if (res == NULL)
return NULL;
// Check filename
if (!check_filename(req->path))
return NULL;
int err = is_directory(req->path->data);
if (err == -1)
return NULL;
else if (err == 1)
// Protocol
char *protocol = "HTTP/1.1";
res->protocol = string_create(protocol, strlen(protocol));
// Status code
if (req->status_code == 0)
{
string_concat_str(req->path, "/", 1);
string_concat_str(req->path, config->servers->default_file,
strlen(config->servers->default_file));
}
if (!find_target(req))
res->status_code = 404;
else
res->status_code = 200;
}
// struct string *format_response(struct http_response *resp)
// {}
// Status msg
res->status_msg = generate_status_message(res->status_code);
// Headers
char *time = get_time();
append_header(&res->headers, create_header("Date", time));
free(time); // Yes, the one that completely disapeared this year
if (res->status_code == 200)
{
char buf[21] = { 0 }; // (21 ~= log10(2^64)) + 1 (null byte)
char *target = string_to_charptr(req->target);
sprintf(buf, "%lu", get_file_content_size(target));
append_header(&res->headers, create_header("Content-Length", buf));
}
append_header(&res->headers, create_header("Connection", "close"));
return res;
}
struct string *format_response(struct http_response *resp)
{
// Protocol
struct string *res =
string_create(resp->protocol->data, resp->protocol->size);
string_concat_str(res, " ", 1);
// Status code
char buf[4] = { 0 };
sprintf(buf, "%d", resp->status_code);
string_concat_str(res, buf, strlen(buf));
string_concat_str(res, " ", 1);
// Status message
string_concat_str(res, buf, strlen(buf));
string_concat_str(res, "/r/n", 2);
// Headers
struct http_header *cur_header = resp->headers;
while (cur_header != NULL)
{
string_concat_str(res, cur_header->field->data,
cur_header->field->size);
string_concat_str(res, "/r/n", 2);
}
string_concat_str(res, "/r/n", 2);
return res;
}
void destroy_request(struct http_request *req)
{
if (req != NULL)
{
if (req->path != NULL)
string_destroy(req->path);
if (req->target != NULL)
string_destroy(req->target);
if (req->protocol != NULL)
string_destroy(req->protocol);

View file

@ -43,10 +43,11 @@ struct http_header
struct http_request
{
enum http_method method;
struct string *path;
struct string *target;
struct string *queries;
struct string *protocol;
struct http_header *headers; // Headers linked list
int status_code; // Set by program
};
struct http_response
@ -61,7 +62,7 @@ struct http_response
/* @brief Initializes the HTTP module with the given configuration
*
* @warning Do no use any other function of this module before calling that one
* @warn Do no use any other function of this module before calling that one
*
* @param cfg
*/

View file

@ -1,7 +1,7 @@
#include <getopt.h>
#include <stdio.h>
#include "config/config.h"
#include "http/http.h"
#include "logger/logs.h"
#include "server/server.h"
@ -9,12 +9,35 @@
int main(int argc, char **argv)
{
// Parse config
struct config *config = parse_configuration(argc, argv);
if (config == NULL)
return ERR_ARG;
// Initialize modules
log_init(config);
http_init(config);
// Start server
switch (config->daemon)
{
NO_OPTION:
start_server("localhost", config->servers->port);
break;
START:
start_daemon();
break;
RESTART:
restart_daemon();
STOP:
stop_daemon();
default:
return 2;
}
return 0;
}

View file

@ -1,12 +1,12 @@
#include "files.h"
#include <stdio.h>
// #include <stdio.h>
#include <sys/stat.h>
#include "../string/string.h"
// #include "../string/string.h"
bool file_exists(const char *path)
{}
// bool file_exists(const char *path)
// {}
int is_directory(const char *path)
{
@ -18,21 +18,21 @@ int 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;
// 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;
}
// // 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)))
}
// int nread;
// while ((fgets(buf, BUFFER_SIZE, stream)))
// }

View file

@ -9,6 +9,7 @@
#include <stdbool.h>
#include <stddef.h>
#include <sys/types.h>
// === Functions
@ -61,10 +62,19 @@ bool check_filename(struct string* path);
/*
* @brief
*
* @param path
* @param filename
*
* @return
*/
bool sanitize_filename(struct string* filename);
/*
* @brief
*
* @param path
*
* @return
*/
ssize_t get_file_content_size(const char* path);
#endif // ! FILES_H

View file

@ -85,3 +85,17 @@ void string_destroy(struct string *str)
free(str);
}
}
char *string_to_charptr(struct string *str)
{
if (str == NULL || str->data == NULL)
return NULL;
char *res = realloc(str->data, str->size + 1);
if (res == NULL)
return NULL;
res[str->size] = '\0';
return res;
}

View file

@ -56,4 +56,13 @@ void string_to_lowercase(struct string *str);
*/
void string_destroy(struct string *str);
/*
** @brief Converts the string to the native C implementation
**
** @param str
**
** @return a pointer to an allocated memory zone containing the string
*/
char* string_to_charptr(struct string *str);
#endif /* ! STRING_H */