From f8c6923c6d74c455b17b1ac1ce80a4f12a20f678 Mon Sep 17 00:00:00 2001 From: lperrey Date: Tue, 16 Aug 2022 01:46:24 +0200 Subject: [PATCH] fixed CGI alloc + handle unknow status from script --- srcs/webserv/Webserv.hpp | 9 +-- srcs/webserv/cgi_script.cpp | 117 +++++++++++++++++++++++------------- srcs/webserv/close.cpp | 2 +- srcs/webserv/init.cpp | 2 +- srcs/webserv/response.cpp | 10 ++- 5 files changed, 91 insertions(+), 49 deletions(-) diff --git a/srcs/webserv/Webserv.hpp b/srcs/webserv/Webserv.hpp index 1c9ace1..ddb784c 100644 --- a/srcs/webserv/Webserv.hpp +++ b/srcs/webserv/Webserv.hpp @@ -107,10 +107,11 @@ class Webserv bool _is_cgi(Client *client, std::string path); size_t _cgi_pos(Client *client, std::string &path, size_t pos); std::string _exec_cgi(Client *client); - char** _set_env(Client *client); - 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 _set_env_vector(Client *client, std::vector &env_vector); + void _set_env_cstr(char *env_cstr[], std::vector &env_vector); + std::string _dup_env(std::string var, std::string val); + std::string _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); diff --git a/srcs/webserv/cgi_script.cpp b/srcs/webserv/cgi_script.cpp index 815218e..cdb744f 100644 --- a/srcs/webserv/cgi_script.cpp +++ b/srcs/webserv/cgi_script.cpp @@ -64,66 +64,100 @@ size_t Webserv::_cgi_pos(Client *client, std::string &path, size_t pos) std::string Webserv::_exec_cgi(Client *client) { - char** env; - std::string script_output; + std::string script_output; + char* env_cstr[19] = {NULL}; + std::vector env_vector; + env_vector.reserve(18); - env = _set_env(client); - script_output = _exec_script(client, env); - - for (int i = 0; env[i]; i++) - delete[] env[i]; - delete[] env; + _set_env_vector(client, env_vector); + _set_env_cstr(env_cstr, env_vector); + script_output = _exec_script(client, env_cstr); + + int i = 0; + while (env_cstr[i] != NULL) + delete[] env_cstr[i++]; return script_output; } -char* Webserv::_dup_env(std::string var, std::string val = "") +std::string Webserv::_dup_env(std::string var, std::string val = "") { std::string str; str = var + "=" + val; - return ( strdup(str.c_str()) ); + return (str); } -char* Webserv::_dup_env(std::string var, int i) +std::string Webserv::_dup_env(std::string var, int i) { std::string str; std::string val; val = ::itos(i); str = var + "=" + val; - // TODO change strdup for something with new - return ( strdup(str.c_str()) ); + return (str); } -char** Webserv::_set_env(Client *client) +// TODO : verifier que les variables sont corrects +void Webserv::_set_env_vector(Client *client, std::vector &env_vector) { - char** env = new char*[19]; - - env[0] = _dup_env("AUTH_TYPE"); // authentification not supported - env[1] = _dup_env("CONTENT_LENGTH" , client->get_rq_body().size()); - env[2] = _dup_env("CONTENT_TYPE" , client->get_rq_headers("Content-Type")); - env[3] = _dup_env("GATEWAY_INTERFACE" , "CGI/1.1"); // https://www.rfc-editor.org/rfc/rfc3875 - env[4] = _dup_env("PATH_INFO" , client->get_rq_script_info()); - env[5] = _dup_env("PATH_TRANSLATED"); // not supported - env[6] = _dup_env("QUERY_STRING" , client->get_rq_query()); - env[7] = _dup_env("REMOTE_ADDR" , client->get_cl_ip()); - env[8] = _dup_env("REMOTE_HOST" , client->get_rq_headers("Host")); // just test - env[9] = _dup_env("REMOTE_IDENT"); // authentification not supported - env[10] = _dup_env("REMOTE_USER"); // authentification not supported - env[11] = _dup_env("REQUEST_METHOD" , client->get_rq_method_str()); - env[12] = _dup_env("SCRIPT_NAME" , client->get_rq_script_path()); - env[13] = _dup_env("SERVER_NAME" , client->get_rq_hostname()); - env[14] = _dup_env("SERVER_PORT" , client->get_rq_port()); - env[15] = _dup_env("SERVER_PROTOCOL" , client->get_rq_version()); - env[16] = _dup_env("SERVER_SOFTWARE" , "webser/1.0"); - env[17] = _dup_env("REDIRECT_STATUS" , "200"); - env[18] = NULL; - - return env; + env_vector.push_back(_dup_env("AUTH_TYPE")); // authentification not supporte + env_vector.push_back(_dup_env("CONTENT_LENGTH" , client->get_rq_body().size())); + env_vector.push_back(_dup_env("CONTENT_TYPE" , client->get_rq_headers("Content-Type"))); + env_vector.push_back(_dup_env("GATEWAY_INTERFACE" , "CGI/1.1")); // https://www.rfc-editor.org/rfc/rfc387) + env_vector.push_back(_dup_env("PATH_INFO" , client->get_rq_script_info())); + env_vector.push_back(_dup_env("REMOTE_ADDR" , client->get_cl_ip())); + env_vector.push_back(_dup_env("REMOTE_HOST" , client->get_rq_headers("Host"))); // just tes + env_vector.push_back(_dup_env("REMOTE_IDENT")); // authentification not supporte + env_vector.push_back(_dup_env("REMOTE_USER")); // authentification not supporte + env_vector.push_back(_dup_env("REQUEST_METHOD" , client->get_rq_method_str())); + env_vector.push_back(_dup_env("SCRIPT_NAME" , client->get_rq_script_path())); + env_vector.push_back(_dup_env("SERVER_NAME" , client->get_rq_hostname())); + env_vector.push_back(_dup_env("SERVER_PORT" , client->get_rq_port())); + env_vector.push_back(_dup_env("SERVER_PROTOCOL" , "HTTP/1.1")); + env_vector.push_back(_dup_env("SERVER_SOFTWARE" , "Webserv/0.1")); + env_vector.push_back(_dup_env("REDIRECT_STATUS" , "200")); } -std::string Webserv::_exec_script(Client *client, char **env) +void Webserv::_set_env_cstr(char *env_cstr[], std::vector &env_vector) +{ + std::vector::const_iterator it = env_vector.begin(); + std::vector::const_iterator it_end = env_vector.end(); + int i = 0; + while (it != it_end) + { + env_cstr[i] = new char[it->size()+1]; + std::strcpy(env_cstr[i], it->c_str()); + ++it; + ++i; + } + env_cstr[i] = NULL; +} + +/* void Webserv::_set_env_cstr(char *env_cstr[], std::vector &env_vector) +{ + env_cstr[0] = const_cast(env_vector[0].c_str()); + env_cstr[1] = const_cast(env_vector[1].c_str()); + env_cstr[2] = const_cast(env_vector[2].c_str()); + env_cstr[3] = const_cast(env_vector[3].c_str()); + env_cstr[4] = const_cast(env_vector[4].c_str()); + env_cstr[5] = const_cast(env_vector[5].c_str()); + env_cstr[6] = const_cast(env_vector[6].c_str()); + env_cstr[7] = const_cast(env_vector[7].c_str()); + env_cstr[8] = const_cast(env_vector[8].c_str()); + env_cstr[9] = const_cast(env_vector[9].c_str()); + env_cstr[10] = const_cast(env_vector[10].c_str()); + env_cstr[11] = const_cast(env_vector[11].c_str()); + env_cstr[12] = const_cast(env_vector[12].c_str()); + env_cstr[13] = const_cast(env_vector[13].c_str()); + env_cstr[14] = const_cast(env_vector[14].c_str()); + env_cstr[15] = const_cast(env_vector[15].c_str()); + env_cstr[16] = const_cast(env_vector[16].c_str()); + env_cstr[17] = const_cast(env_vector[17].c_str()); + env_cstr[18] = NULL; +} */ + +std::string Webserv::_exec_script(Client *client, char *env[]) { #define RD 0 #define WR 1 @@ -135,7 +169,7 @@ std::string Webserv::_exec_script(Client *client, char **env) pid_t pid; char buf[CGI_BUF_SIZE]; // WIP define buffer - char * const * nll = NULL; + char * const nll[1] = {NULL}; std::string script_output; std::string body = client->get_rq_body(); int fd_in[2]; @@ -149,7 +183,8 @@ std::string Webserv::_exec_script(Client *client, char **env) if (pid == -1) std::cerr << "fork crashed" << std::endl; else if (pid == 0) // child - { + { + // _close_all_clients(); close(FD_WR_TO_CHLD); close(FD_RD_FR_CHLD); dup2(FD_RD_FR_PRNT, STDIN_FILENO); @@ -179,7 +214,7 @@ std::string Webserv::_exec_script(Client *client, char **env) close(FD_RD_FR_CHLD); } if (script_output.empty()) - script_output = "Status: 500\r\n\r\n"; + script_output = "Status: 500" CRLF CRLF; return script_output; } diff --git a/srcs/webserv/close.cpp b/srcs/webserv/close.cpp index f71add7..e0e3893 100644 --- a/srcs/webserv/close.cpp +++ b/srcs/webserv/close.cpp @@ -54,7 +54,7 @@ void Webserv::_reopen_lsocket(std::vector::iterator it) if (::close(it->fd) == -1) std::perror("err close()"); std::cerr << "try to reopen lsocket\n"; - ret = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); // (SOCK_CLOEXEC) for CGI fork ? + ret = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); if (ret == -1) { std::perror("err socket()"); diff --git a/srcs/webserv/init.cpp b/srcs/webserv/init.cpp index 0ee6f17..3bc27ec 100644 --- a/srcs/webserv/init.cpp +++ b/srcs/webserv/init.cpp @@ -24,7 +24,7 @@ void Webserv::init_virtual_servers(std::vector* servers) continue; } - ret = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); // (SOCK_CLOEXEC) for CGI fork ? + ret = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); if (ret == -1) { std::perror("err socket()"); diff --git a/srcs/webserv/response.cpp b/srcs/webserv/response.cpp index 627a868..f830cbd 100644 --- a/srcs/webserv/response.cpp +++ b/srcs/webserv/response.cpp @@ -122,9 +122,12 @@ void Webserv::_process_method(Client *client, std::string &path) void Webserv::_insert_status_line(Client *client) { std::string status_line; + std::string status = _http_status[client->status]; + if (status.empty()) + status = ::itos(client->status); status_line.append("HTTP/1.1 "); - status_line.append(_http_status[client->status]); + status_line.append(status); status_line.append(CRLF); client->response.insert(0, status_line); } @@ -141,8 +144,11 @@ void Webserv::_error_html_response(Client *client) } else { + std::string status = _http_status[client->status]; + if (status.empty()) + status = "Error " + ::itos(client->status); std::string html_page = HTML_ERROR; - ::replace_all_substr(html_page, STATUS_PLACEHOLDER, _http_status[client->status]); + ::replace_all_substr(html_page, STATUS_PLACEHOLDER, status); _append_body(client, html_page, "html"); } }