fixed CGI alloc

+ handle unknow status from script
This commit is contained in:
lperrey
2022-08-16 01:46:24 +02:00
parent e691c517e8
commit f8c6923c6d
5 changed files with 91 additions and 49 deletions

View File

@@ -107,10 +107,11 @@ class Webserv
bool _is_cgi(Client *client, std::string path); bool _is_cgi(Client *client, std::string path);
size_t _cgi_pos(Client *client, std::string &path, size_t pos); size_t _cgi_pos(Client *client, std::string &path, size_t pos);
std::string _exec_cgi(Client *client); std::string _exec_cgi(Client *client);
char** _set_env(Client *client); void _set_env_vector(Client *client, std::vector<std::string> &env_vector);
char* _dup_env(std::string var, std::string val); void _set_env_cstr(char *env_cstr[], std::vector<std::string> &env_vector);
char* _dup_env(std::string var, int i); std::string _dup_env(std::string var, std::string val);
std::string _exec_script(Client *client, char **env); 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_output(Client *client, std::string & output);
void _check_script_status(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_fields(Client *client, std::string & output);

View File

@@ -64,66 +64,100 @@ size_t Webserv::_cgi_pos(Client *client, std::string &path, size_t pos)
std::string Webserv::_exec_cgi(Client *client) std::string Webserv::_exec_cgi(Client *client)
{ {
char** env; std::string script_output;
std::string script_output; char* env_cstr[19] = {NULL};
std::vector<std::string> env_vector;
env_vector.reserve(18);
env = _set_env(client); _set_env_vector(client, env_vector);
script_output = _exec_script(client, env); _set_env_cstr(env_cstr, env_vector);
script_output = _exec_script(client, env_cstr);
for (int i = 0; env[i]; i++)
delete[] env[i]; int i = 0;
delete[] env; while (env_cstr[i] != NULL)
delete[] env_cstr[i++];
return script_output; 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; std::string str;
str = var + "=" + val; 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 str;
std::string val; std::string val;
val = ::itos(i); val = ::itos(i);
str = var + "=" + val; str = var + "=" + val;
// TODO change strdup for something with new return (str);
return ( strdup(str.c_str()) );
} }
char** Webserv::_set_env(Client *client) // TODO : verifier que les variables sont corrects
void Webserv::_set_env_vector(Client *client, std::vector<std::string> &env_vector)
{ {
char** env = new char*[19]; 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[0] = _dup_env("AUTH_TYPE"); // authentification not supported env_vector.push_back(_dup_env("CONTENT_TYPE" , client->get_rq_headers("Content-Type")));
env[1] = _dup_env("CONTENT_LENGTH" , client->get_rq_body().size()); env_vector.push_back(_dup_env("GATEWAY_INTERFACE" , "CGI/1.1")); // https://www.rfc-editor.org/rfc/rfc387)
env[2] = _dup_env("CONTENT_TYPE" , client->get_rq_headers("Content-Type")); env_vector.push_back(_dup_env("PATH_INFO" , client->get_rq_script_info()));
env[3] = _dup_env("GATEWAY_INTERFACE" , "CGI/1.1"); // https://www.rfc-editor.org/rfc/rfc3875 env_vector.push_back(_dup_env("REMOTE_ADDR" , client->get_cl_ip()));
env[4] = _dup_env("PATH_INFO" , client->get_rq_script_info()); env_vector.push_back(_dup_env("REMOTE_HOST" , client->get_rq_headers("Host"))); // just tes
env[5] = _dup_env("PATH_TRANSLATED"); // not supported env_vector.push_back(_dup_env("REMOTE_IDENT")); // authentification not supporte
env[6] = _dup_env("QUERY_STRING" , client->get_rq_query()); env_vector.push_back(_dup_env("REMOTE_USER")); // authentification not supporte
env[7] = _dup_env("REMOTE_ADDR" , client->get_cl_ip()); env_vector.push_back(_dup_env("REQUEST_METHOD" , client->get_rq_method_str()));
env[8] = _dup_env("REMOTE_HOST" , client->get_rq_headers("Host")); // just test env_vector.push_back(_dup_env("SCRIPT_NAME" , client->get_rq_script_path()));
env[9] = _dup_env("REMOTE_IDENT"); // authentification not supported env_vector.push_back(_dup_env("SERVER_NAME" , client->get_rq_hostname()));
env[10] = _dup_env("REMOTE_USER"); // authentification not supported env_vector.push_back(_dup_env("SERVER_PORT" , client->get_rq_port()));
env[11] = _dup_env("REQUEST_METHOD" , client->get_rq_method_str()); env_vector.push_back(_dup_env("SERVER_PROTOCOL" , "HTTP/1.1"));
env[12] = _dup_env("SCRIPT_NAME" , client->get_rq_script_path()); env_vector.push_back(_dup_env("SERVER_SOFTWARE" , "Webserv/0.1"));
env[13] = _dup_env("SERVER_NAME" , client->get_rq_hostname()); env_vector.push_back(_dup_env("REDIRECT_STATUS" , "200"));
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;
} }
std::string Webserv::_exec_script(Client *client, char **env) void Webserv::_set_env_cstr(char *env_cstr[], std::vector<std::string> &env_vector)
{
std::vector<std::string>::const_iterator it = env_vector.begin();
std::vector<std::string>::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<std::string> &env_vector)
{
env_cstr[0] = const_cast<char*>(env_vector[0].c_str());
env_cstr[1] = const_cast<char*>(env_vector[1].c_str());
env_cstr[2] = const_cast<char*>(env_vector[2].c_str());
env_cstr[3] = const_cast<char*>(env_vector[3].c_str());
env_cstr[4] = const_cast<char*>(env_vector[4].c_str());
env_cstr[5] = const_cast<char*>(env_vector[5].c_str());
env_cstr[6] = const_cast<char*>(env_vector[6].c_str());
env_cstr[7] = const_cast<char*>(env_vector[7].c_str());
env_cstr[8] = const_cast<char*>(env_vector[8].c_str());
env_cstr[9] = const_cast<char*>(env_vector[9].c_str());
env_cstr[10] = const_cast<char*>(env_vector[10].c_str());
env_cstr[11] = const_cast<char*>(env_vector[11].c_str());
env_cstr[12] = const_cast<char*>(env_vector[12].c_str());
env_cstr[13] = const_cast<char*>(env_vector[13].c_str());
env_cstr[14] = const_cast<char*>(env_vector[14].c_str());
env_cstr[15] = const_cast<char*>(env_vector[15].c_str());
env_cstr[16] = const_cast<char*>(env_vector[16].c_str());
env_cstr[17] = const_cast<char*>(env_vector[17].c_str());
env_cstr[18] = NULL;
} */
std::string Webserv::_exec_script(Client *client, char *env[])
{ {
#define RD 0 #define RD 0
#define WR 1 #define WR 1
@@ -135,7 +169,7 @@ std::string Webserv::_exec_script(Client *client, char **env)
pid_t pid; pid_t pid;
char buf[CGI_BUF_SIZE]; // WIP define buffer char buf[CGI_BUF_SIZE]; // WIP define buffer
char * const * nll = NULL; char * const nll[1] = {NULL};
std::string script_output; std::string script_output;
std::string body = client->get_rq_body(); std::string body = client->get_rq_body();
int fd_in[2]; int fd_in[2];
@@ -149,7 +183,8 @@ std::string Webserv::_exec_script(Client *client, char **env)
if (pid == -1) if (pid == -1)
std::cerr << "fork crashed" << std::endl; std::cerr << "fork crashed" << std::endl;
else if (pid == 0) // child else if (pid == 0) // child
{ {
// _close_all_clients();
close(FD_WR_TO_CHLD); close(FD_WR_TO_CHLD);
close(FD_RD_FR_CHLD); close(FD_RD_FR_CHLD);
dup2(FD_RD_FR_PRNT, STDIN_FILENO); 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); close(FD_RD_FR_CHLD);
} }
if (script_output.empty()) if (script_output.empty())
script_output = "Status: 500\r\n\r\n"; script_output = "Status: 500" CRLF CRLF;
return script_output; return script_output;
} }

View File

@@ -54,7 +54,7 @@ void Webserv::_reopen_lsocket(std::vector<listen_socket>::iterator it)
if (::close(it->fd) == -1) if (::close(it->fd) == -1)
std::perror("err close()"); std::perror("err close()");
std::cerr << "try to reopen lsocket\n"; 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) if (ret == -1)
{ {
std::perror("err socket()"); std::perror("err socket()");

View File

@@ -24,7 +24,7 @@ void Webserv::init_virtual_servers(std::vector<ServerConfig>* servers)
continue; 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) if (ret == -1)
{ {
std::perror("err socket()"); std::perror("err socket()");

View File

@@ -122,9 +122,12 @@ void Webserv::_process_method(Client *client, std::string &path)
void Webserv::_insert_status_line(Client *client) void Webserv::_insert_status_line(Client *client)
{ {
std::string status_line; 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/1.1 ");
status_line.append(_http_status[client->status]); status_line.append(status);
status_line.append(CRLF); status_line.append(CRLF);
client->response.insert(0, status_line); client->response.insert(0, status_line);
} }
@@ -141,8 +144,11 @@ void Webserv::_error_html_response(Client *client)
} }
else else
{ {
std::string status = _http_status[client->status];
if (status.empty())
status = "Error " + ::itos(client->status);
std::string html_page = HTML_ERROR; 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"); _append_body(client, html_page, "html");
} }
} }