merged and added colors to makefile

This commit is contained in:
Eric LAZO
2022-08-12 15:24:10 +02:00
29 changed files with 578 additions and 261 deletions

View File

@@ -23,7 +23,7 @@
# include <algorithm> // find
# include <string> // string
# include <cstdio> // perror, remove
# include <cstdlib> // atoi (athough it's already cover by <string>)
# include <cstdlib> // strtol, strtoul
# include <dirent.h> // opendir()
# include "Client.hpp"
@@ -104,9 +104,9 @@ class Webserv
char* _dup_env(std::string var, std::string val);
char* _dup_env(std::string var, int i);
std::string _exec_script(Client *client, char **env);
void _check_script_output(Client *client, std::string output);
void _check_script_status(Client *client, std::string output);
void _check_script_fields(Client *client, std::string output);
void _check_script_output(Client *client, std::string & output);
void _check_script_status(Client *client, std::string & output);
void _check_script_fields(Client *client, std::string & output);
// epoll_update.cpp
int _epoll_update(int fd, uint32_t events, int op);
int _epoll_update(int fd, uint32_t events, int op, void *ptr);

View File

@@ -89,6 +89,8 @@ std::string Webserv::_exec_script(Client *client, char **env)
std::string body = client->get_rq_body();
int fd_in[2];
int fd_out[2];
int save_in = dup(STDIN_FILENO);
int save_out = dup(STDOUT_FILENO);
pipe(fd_in);
pipe(fd_out);
@@ -127,17 +129,22 @@ std::string Webserv::_exec_script(Client *client, char **env)
}
if (script_output.empty())
script_output = "Status: 500\r\n\r\n";
dup2(save_in, STDIN_FILENO);
dup2(save_out, STDOUT_FILENO);
return script_output;
}
void Webserv::_check_script_output(Client *client, std::string output)
void Webserv::_check_script_output(Client *client, std::string & output)
{
// TODO: it doesn't work with execve error, i don't know why yet ?
_check_script_status(client, output);
_check_script_fields(client, output);
// _check_script_empty_lines(client, output);
// _check_script_space_colons(client, output);
// _check_script_new_lines(client, output);
}
void Webserv::_check_script_status(Client *client, std::string output)
void Webserv::_check_script_status(Client *client, std::string & output)
{
size_t pos;
int status_pos;
@@ -146,31 +153,43 @@ void Webserv::_check_script_status(Client *client, std::string output)
if (pos != std::string::npos)
{
status_pos = pos + std::string("Status:").size();
client->status = atoi(output.c_str() + status_pos);
::del_line_in_str(&output, pos, CRLF);
client->status = std::strtoul(output.c_str() + status_pos, NULL, 10);
::extract_line(output, pos, CRLF);
}
client->status = 200;
else
client->status = 200;
}
void Webserv::_check_script_fields(Client *client, std::string output)
void Webserv::_check_script_fields(Client *client, std::string & output)
{
std::map<std::string, std::string> srv_fld; // server_field
std::map<std::string, std::string> scr_fld; // script_field
std::map<std::string, std::string>::iterator it_srv;
std::map<std::string, std::string>::iterator it_scr;
std::string tmp;
size_t pos;
srv_fld = parse_http_headers(client->response);
scr_fld = parse_http_headers(output);
// wip: compare both map to supress duplicates
// put server headers in map
tmp = client->response;
pos = tmp.find(CRLF CRLF);
if (pos != std::string::npos)
tmp.erase(pos);
::parse_http_headers(tmp, srv_fld);
// put script headers in map
tmp = output;
pos = tmp.find(CRLF CRLF);
if (pos != std::string::npos)
tmp.erase(pos);
::parse_http_headers(tmp, scr_fld);
// compare both map to supress duplicates
for (it_srv = srv_fld.begin(); it_srv != srv_fld.end(); it_srv++)
{
for (it_scr = scr_fld.begin(); it_scr != scr_fld.end(); it_scr++)
{
if (it_srv->first == it_scr->first)
if (str_tolower(it_srv->first) == str_tolower(it_scr->first))
{
pos = client->response.find(it_srv->first);
::del_line_in_str(&client->response, pos, CRLF);
::extract_line(client->response, pos, CRLF);
}
}
}

View File

@@ -76,7 +76,7 @@ void Webserv::_reopen_lsocket(std::vector<listen_socket>::iterator it)
// HUGO ADD END
try {
_bind(it->fd, std::atoi(it->port.c_str()), it->host);
_bind(it->fd, std::strtoul(it->port.c_str(), NULL, 10), it->host);
_listen(it->fd, 42); // 42 arbitrary
}
catch (const std::exception& e) {

View File

@@ -43,6 +43,7 @@
# define S405 "405 Method Not Allowed"
# define S408 "408 Request Timeout"
# define S413 "413 Content Too Large"
# define S415 "415 Unsupported Media Type"
# define S500 "500 Internal Server Error"
# define S501 "501 Not Implemented"

View File

@@ -48,7 +48,7 @@ void Webserv::init_virtual_servers(std::vector<ServerConfig>* servers)
//
// HUGO ADD END
_bind(new_socket.fd, std::atoi(it->port.c_str()), it->host);
_bind(new_socket.fd, std::strtoul(it->port.c_str(), NULL, 10), it->host);
_listen(new_socket.fd, 42); // 42 arbitrary
if (_epoll_update(new_socket.fd, EPOLLIN, EPOLL_CTL_ADD) == -1)

View File

@@ -19,9 +19,6 @@ void Webserv::_get(Client *client)
if (_is_cgi(client))
{
script_output = _exec_cgi(client);
// DEBUG
std::cout << "\n____script_output____\n" << script_output << "\n_______________\n";
// wip check output of script
_check_script_output(client, script_output);
client->response += script_output;
return;
@@ -30,14 +27,14 @@ void Webserv::_get(Client *client)
// END TMP HUGO
// Index/Autoindex block
if (path_is_valid(path) == IS_DIR)
if (eval_file_type(path) == IS_DIR)
{
std::cout << "made it to Index/Autoindex\n";
if (path[path.size() - 1] != '/')
path.push_back('/');
for (size_t i = 0; i < client->assigned_location->index.size(); i++)
{
if (path_is_valid(path + client->assigned_location->index[i]) == 2)
if (eval_file_type(path + client->assigned_location->index[i]) == IS_FILE)
{
path.append(client->assigned_location->index[i]);
_get_file(client, path);
@@ -49,8 +46,6 @@ void Webserv::_get(Client *client)
}
else
_get_file(client, path);
}
# define MAX_FILESIZE 1000000 // (1Mo)

View File

@@ -1,64 +1,6 @@
#include "parsing_message_http.hpp"
size_t
parse_http_first_line(std::string message, std::vector<std::string> &line)
{
std::vector<std::string> sline;
std::string sub;
std::string tmp;
size_t pos;
size_t ret;
// TODO: check for err in substr
pos = message.find(CRLF);
sub = message.substr(0, pos);
sline = ::split(sub, ' ');
ret = sline.size();
if (ret != 3)
return ret;
for (int i = 0; i < 3; i++)
{
tmp = ::trim(sline[i], ' ');
tmp = ::trim(tmp, '\r');
line.push_back(tmp);
}
return ret;
}
std::map<std::string, std::string>
parse_http_headers(std::string message)
{
std::map<std::string, std::string> headers;
std::vector<std::string> list;
std::vector<std::string>::iterator it;
std::string sub;
std::string key;
std::string val;
size_t pos;
pos = (message).find(CRLF CRLF);
sub = (message).substr(0, pos);
list = ::split(sub, '\n');
if ( maybe_http_first_line( *list.begin() ) )
list.erase(list.begin());
for (it = list.begin(); it != list.end(); it++)
{
// TODO: if pattern is not "NAME: value" return error
pos = (*it).find(':');
key = (*it).substr( 0, pos );
key = ::trim(key, ' ');
key = ::trim(key, '\r');
key = ::str_tolower(key);
val = (*it).substr( pos + 1 );
val = ::trim(val, ' ');
val = ::trim(val, '\r');
headers.insert( std::pair<std::string, std::string>(key, val) );
}
return headers;
}
std::string
parse_http_body(std::string message)
{
@@ -73,18 +15,3 @@ std::string
return body;
}
bool maybe_http_first_line(std::string str)
{
// method SP target SP version https://www.rfc-editor.org/rfc/rfc7230.html#section-3.1.1
// version SP status SP reason https://www.rfc-editor.org/rfc/rfc7230.html#section-3.1.2
std::vector<std::string> sline;
sline = ::split(str, ' ');
if (sline.size() != 3)
return false;
if (sline[0].find(':') != std::string::npos)
return false;
return true;
}

View File

@@ -8,18 +8,14 @@
# include <map>
# include "utils.hpp"
size_t
parse_http_first_line(std::string message, std::vector<std::string> &line);
std::map<std::string, std::string>
parse_http_headers(std::string message);
parse_http_headers (
std::string headers,
std::map<std::string, std::string> fields )
std::string
parse_http_body(std::string message);
bool
maybe_http_first_line(std::string);
// http message structure :
//
// start-line

View File

@@ -25,12 +25,14 @@ void Webserv::_request(Client *client)
}
else if (ret == READ_COMPLETE)
{
if (client->body_complete)
std::cerr << "______BODY\n" << client->get_rq_body() << "\n______\n"; // DEBUG
_epoll_update(client->get_cl_fd(), EPOLLOUT, EPOLL_CTL_MOD);
client->request_complete = true;
}
}
int Webserv::_read_request(Client *client) // Messy, Need refactoring
int Webserv::_read_request(Client *client)
{
char buf[BUFSIZE];
ssize_t ret;
@@ -41,8 +43,6 @@ int Webserv::_read_request(Client *client) // Messy, Need refactoring
if (ret == -1)
{
std::perror("err recv()");
std::cerr << "client ptr =" << client << "\n"; // DEBUG
std::cerr << "client.fd =" << client->get_cl_fd() << "\n"; // DEBUG
return READ_CLOSE;
}
if (ret == 0)
@@ -50,41 +50,32 @@ int Webserv::_read_request(Client *client) // Messy, Need refactoring
std::cerr << "recv() read 0, then close client" << "\n"; // DEBUG
return READ_CLOSE;
}
client->raw_request.append(buf, ret);
if (!client->header_complete)
{
if (client->raw_request.find(CRLF CRLF) != std::string::npos)
client->parse_request_headers(_servers);
if (client->status)
return READ_COMPLETE;
if (client->header_complete)
{
client->header_complete = true;
client->parse_request(_servers);
std::cerr << client->get_rq_method_str() << " " << client->get_rq_uri() << " " << client->get_rq_version() << "\n"; // DEBUG
if (client->status)
return READ_COMPLETE;
if (client->get_rq_headers("Content-Type").empty() && client->get_rq_headers("Content-Length").empty()) // No body case
return READ_COMPLETE;
if (client->get_rq_headers("Content-Type").empty()
&& client->get_rq_headers("Content-Length").empty()
&& client->get_rq_headers("Transfer-Encoding").empty())
return READ_COMPLETE; // No body case
}
else if (client->raw_request.size() > MAX_HEADER_SIZE)
{
// 413 or 400 ? 413 seems common among http server, but don't fit perfectly.
{ // 413 or 400 ? 413 seems common among http server, but don't fit perfectly.
client->status = 413;
return READ_COMPLETE;
}
}
else if (client->header_complete)
{
client->read_body_size += ret;
if (client->read_body_size > client->assigned_server->client_body_limit)
{
client->status = 413;
// client->read_body_size += ret; // Not accurate, part of body could have been read with headers, unused for now
client->parse_request_body();
if (client->status || client->body_complete)
return READ_COMPLETE;
}
if ((int)client->read_body_size >= ::atoi(client->get_rq_headers("Content-Length").c_str()))
{
client->parse_request_body();
return READ_COMPLETE;
}
}
return READ_IN_PROGRESS;

View File

@@ -20,8 +20,9 @@ void Webserv::run()
nfds = ::epoll_wait(_epfd, events, MAX_EVENTS, TIMEOUT);
if (nfds == -1)
{
int errno_copy = errno;
std::perror("err epoll_wait()");
if (errno == EINTR)
if (errno_copy == EINTR)
g_run = false;
else
throw std::runtime_error("Epoll wait");