218 lines
6.4 KiB
C++
218 lines
6.4 KiB
C++
|
|
#include "Webserv.hpp"
|
|
|
|
// TODO HUGO : go ameliorer la recherche comme on a dit.
|
|
size_t Webserv::_cgi_pos(Client *client, std::string &path)
|
|
{
|
|
std::vector<std::string> v_ext;
|
|
std::vector<std::string>::const_iterator it;
|
|
std::vector<std::string>::const_iterator it_end;
|
|
size_t pos = 0;
|
|
/*DEBUG*/ it = client->assigned_location->cgi_ext.begin(); std::cout << B_YELLOW << "\nDEBUG _cgi_pos()\n" << RESET << "vector_ext.size():[" << client->assigned_location->cgi_ext.size() << "]\n\n";
|
|
v_ext = client->assigned_location->cgi_ext;
|
|
if (v_ext.empty())
|
|
return NPOS; /*DEBUG*/ std::cout << "ext:[" << *it << "]\n" << "path:[" << path << "]\n\n";
|
|
it_end = client->assigned_location->cgi_ext.end();
|
|
while (pos < path.size())
|
|
{ /*DEBUG*/ std::cout << "\nwhile\n";
|
|
if (path.compare(pos, 2, "./") == 0)
|
|
pos += 2; /*DEBUG*/ std::cout << "&path[pos]:[" << &path[pos] << "]\n";
|
|
pos = path.find('.', pos);
|
|
if (pos == NPOS)
|
|
return pos;
|
|
it = client->assigned_location->cgi_ext.begin();
|
|
for ( ; it != it_end; ++it)
|
|
{ /*DEBUG*/ std::cout << " for\n"; std::cout << " &path[pos]:[" << &path[pos] << "]\n" << " *it:[" << *it << "]\n" << " (*it).size():[" << (*it).size() << "]\n" << " path.substr(pos, (*it).size()):[" << path.substr(pos + 1, (*it).size()) << "]\n\n";
|
|
if (path.compare(pos + 1, (*it).size(), *it) == 0)
|
|
return pos;
|
|
}
|
|
pos++;
|
|
}
|
|
return NPOS;
|
|
}
|
|
|
|
std::string Webserv::_exec_cgi(Client *client)
|
|
{
|
|
char** env;
|
|
std::string script_output;
|
|
|
|
env = _set_env(client);
|
|
script_output = _exec_script(client, env);
|
|
|
|
for (int i = 0; env[i]; i++)
|
|
delete[] env[i];
|
|
delete[] env;
|
|
|
|
return script_output;
|
|
}
|
|
|
|
char* Webserv::_dup_env(std::string var, std::string val = "")
|
|
{
|
|
std::string str;
|
|
|
|
str = var + "=" + val;
|
|
return ( strdup(str.c_str()) );
|
|
}
|
|
|
|
char* 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()) );
|
|
}
|
|
|
|
char** Webserv::_set_env(Client *client)
|
|
{
|
|
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;
|
|
}
|
|
|
|
std::string Webserv::_exec_script(Client *client, char **env)
|
|
{
|
|
#define RD 0
|
|
#define WR 1
|
|
#define CGI_BUF_SIZE 10
|
|
#define FD_WR_TO_CHLD fd_in[WR]
|
|
#define FD_WR_TO_PRNT fd_out[WR]
|
|
#define FD_RD_FR_CHLD fd_out[RD]
|
|
#define FD_RD_FR_PRNT fd_in[RD]
|
|
|
|
pid_t pid;
|
|
char buf[CGI_BUF_SIZE]; // WIP define buffer
|
|
char * const * nll = NULL;
|
|
std::string script_output;
|
|
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);
|
|
|
|
pid = fork();
|
|
if (pid == -1)
|
|
std::cerr << "fork crashed" << std::endl;
|
|
else if (pid == 0)
|
|
{
|
|
close(FD_WR_TO_CHLD);
|
|
close(FD_RD_FR_CHLD);
|
|
dup2(FD_RD_FR_PRNT, STDIN_FILENO);
|
|
dup2(FD_WR_TO_PRNT, STDOUT_FILENO);
|
|
// DEBUG
|
|
std::cerr << "execve:\n";
|
|
execve(client->get_rq_script_path().c_str(), nll, env);
|
|
// for tests execve crash :
|
|
//execve("wrong", nll, env);
|
|
std::cerr << "execve crashed.\n";
|
|
}
|
|
else
|
|
{
|
|
close(FD_RD_FR_PRNT);
|
|
close(FD_WR_TO_PRNT);
|
|
write(FD_WR_TO_CHLD, body.c_str(), body.size());
|
|
close(FD_WR_TO_CHLD);
|
|
waitpid(-1, NULL, 0);
|
|
|
|
memset(buf, '\0', CGI_BUF_SIZE);
|
|
while (read(FD_RD_FR_CHLD, buf, CGI_BUF_SIZE - 1) > 0)
|
|
{
|
|
script_output += buf;
|
|
memset(buf, '\0', CGI_BUF_SIZE);
|
|
}
|
|
close(FD_RD_FR_CHLD);
|
|
}
|
|
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)
|
|
{
|
|
_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)
|
|
{
|
|
size_t pos;
|
|
int status_pos;
|
|
|
|
pos = output.find("Status:");
|
|
if (pos != NPOS)
|
|
{
|
|
status_pos = pos + std::string("Status:").size();
|
|
client->status = std::strtoul(output.c_str() + status_pos, NULL, 10);
|
|
::extract_line(output, pos, CRLF);
|
|
}
|
|
else
|
|
client->status = 200;
|
|
}
|
|
|
|
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;
|
|
|
|
// put server headers in map
|
|
tmp = client->response;
|
|
pos = tmp.find(CRLF CRLF);
|
|
if (pos != NPOS)
|
|
tmp.erase(pos);
|
|
::parse_http_headers(tmp, srv_fld);
|
|
// put script headers in map
|
|
tmp = output;
|
|
pos = tmp.find(CRLF CRLF);
|
|
if (pos != 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 (str_tolower(it_srv->first) == str_tolower(it_scr->first))
|
|
{
|
|
pos = client->response.find(it_srv->first);
|
|
::extract_line(client->response, pos, CRLF);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|