diff --git a/README.md b/README.md index 8a8e866..3f0b40e 100644 --- a/README.md +++ b/README.md @@ -2,19 +2,13 @@ ## work together #### next commit -+ in fill_script_path() : scipt_path and script_info are filled, removing leadin dot -+ in _cgi_pos() : check validity of extension if it's only alpha characters -+ severall pbm appears - -#### TODO hugo -- pbm : `http://localhost:4040/cgi-bin/cgi.sh` #### questions -- does the root always start with leading "." ? - how should we handle a wrong url like `http://localhost/cgi-bin/wrong.phpp/good.php` ? - do we serve `./srcs/cgi-bin/good.php` ? - or do we return 404 "not found" ? - - for now, execve would crash, but that doesn't produce a 404 error, rather a 500, is it bad ? +-> - for now, execve would crash, but that doesn't produce a 404 error, rather a 500, is it bad ? + - could we use errno after execve to choose an appropriate http error ? subject says : "Checking the value of errno is strictly forbidden after a read or a write operation" - if a url has a file with extension, but it's not a cgi extension, is it necessary to look further ? - ex. `http://localhost/file.php/file.py` for `cgi_ext py;` ? - the response page is received long after the cgi-script is done, why ? diff --git a/srcs/Client.cpp b/srcs/Client.cpp index 70d288b..9759af2 100644 --- a/srcs/Client.cpp +++ b/srcs/Client.cpp @@ -202,26 +202,22 @@ void Client::parse_request_body() status = 413; // HTTP Client Errors } -// TODO HUGO : what if the root doesn't start with leading "." ? void Client::fill_script_path(std::string &path, size_t pos) { std::string tmp; - // should start with "/" - // and being relative to the root : - // if the path to the script is "root/cgi-bin/cgi.php" - // the path relative to the root would be : /cgi-bin/cgi.php - // here we receive the path as : "./cgi-bin/cgi.php/optionnal" - // so we should remove the leading "." /*DEBUG*/ std::cout << "\n" << B_PURPLE << "debug path dot" << RESET << "\npath:[" << path << "]\n" << "&path[pos]:[" << &path[pos] << "]\n"; if (path[0] == '.') { path.erase(0, 1); pos--; - } /*DEBUG*/ std::cout << "path:[" << path << "]\n" << "&path[pos]:[" << &path[pos] << "]\n"; + } + /*DEBUG*/ std::cout << "path:[" << path << "]\n" << "&path[pos]:[" << &path[pos] << "]\n"; - _request.script.path = path.substr(0, pos); /*DEBUG*/ std::cout << "script_path:[" << _request.script.path << "]\n"; - _request.script.info = path.substr(pos); /*DEBUG*/ std::cout << "script_info:[" << _request.script.info << "]\n" << B_PURPLE << "end debug path dot" << RESET << "\n"; + _request.script.path = path.substr(0, pos); + /*DEBUG*/ std::cout << "script_path:[" << _request.script.path << "]\n"; + _request.script.info = path.substr(pos); + /*DEBUG*/ std::cout << "script_info:[" << _request.script.info << "]\n" << B_PURPLE << "end debug path dot" << RESET << "\n"; } void Client::clear() diff --git a/srcs/cgi-bin/cgi.sh b/srcs/cgi-bin/cgi.sh old mode 100644 new mode 100755 index bdfc2b3..14e0d29 --- a/srcs/cgi-bin/cgi.sh +++ b/srcs/cgi-bin/cgi.sh @@ -1,4 +1,4 @@ -#! /usr/bash +#! /bin/bash echo "status: 100\r\n" echo "\r\n\r\n" echo "hiii" diff --git a/srcs/cgi-bin/cgi_second/cgi.php b/srcs/cgi-bin/cgi_second/cgi.php new file mode 100755 index 0000000..fa20b65 --- /dev/null +++ b/srcs/cgi-bin/cgi_second/cgi.php @@ -0,0 +1,29 @@ +#! /usr/bin/php + diff --git a/srcs/utils.cpp b/srcs/utils.cpp index d531b1b..c1dc152 100644 --- a/srcs/utils.cpp +++ b/srcs/utils.cpp @@ -171,6 +171,21 @@ file_type eval_file_type(const std::string &path) return (IS_OTHER); } +size_t eval_file_mode(std::string path, int mode) +{ + if (access(path.c_str(), F_OK) == -1) + { + std::perror("err access()"); + return 404; // NOT_FOUND, file doesn't exist + } + + if (access(path.c_str(), mode) == -1) + { + std::perror("err access()"); + return 403; // FORBIDDEN, file doesn't have execution permission + } + return 0; +} void replace_all_substr( diff --git a/srcs/utils.hpp b/srcs/utils.hpp index 90e734f..893b355 100644 --- a/srcs/utils.hpp +++ b/srcs/utils.hpp @@ -13,6 +13,7 @@ # include // tolower # include // transform # include // perror, fflush +# include // close, access # include "colors.h" // for debug print_special # define CR "\r" @@ -63,6 +64,7 @@ std::string trim(std::string str, char del); http_method str_to_http_method(std::string &str); std::string http_methods_to_str(unsigned int methods); file_type eval_file_type(const std::string &path); +size_t eval_file_mode(std::string path, int mode); void replace_all_substr(std::string &str, const std::string &ori_substr, const std::string &new_substr); std::string str_tolower(std::string str); std::string extract_line(std::string & str, size_t pos = 0, std::string delim = "\n"); diff --git a/srcs/webserv/Webserv.hpp b/srcs/webserv/Webserv.hpp index bb2a644..f55024c 100644 --- a/srcs/webserv/Webserv.hpp +++ b/srcs/webserv/Webserv.hpp @@ -104,7 +104,8 @@ class Webserv void _delete(Client *client, const std::string &path); void _delete_file(Client *client, const std::string &path); // cgi_script.cpp - size_t _cgi_pos(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); std::string _exec_cgi(Client *client); char** _set_env(Client *client); char* _dup_env(std::string var, std::string val); diff --git a/srcs/webserv/cgi_script.cpp b/srcs/webserv/cgi_script.cpp index 7c3082d..c0cc85b 100644 --- a/srcs/webserv/cgi_script.cpp +++ b/srcs/webserv/cgi_script.cpp @@ -1,32 +1,61 @@ #include "Webserv.hpp" -// TODO HUGO : for the moment, this url valid a cgi, it shouldn't : -// http://localhost:4040/cgi-bin/cgi.phpp -// check the output for an alpha value maybe ? check rfc -size_t Webserv::_cgi_pos(Client *client, std::string &path) +bool Webserv::_is_cgi(Client *client, std::string path) +{ + size_t file_type; + size_t file_mode; + size_t pos = 0; + + while (pos != NPOS) + { + pos = _cgi_pos(client, path, pos); + /*DEBUG*/ std::cout << "pos:" << pos << "\n&path[pos]:" << &path[pos] << "\n" << B_YELLOW << "fin debug _cgi_pos()\n\n" << RESET; + if (pos == NPOS) + break; + client->fill_script_path(path, pos); + file_type = ::eval_file_type(client->get_rq_script_path()); + if (file_type == IS_DIR) // but what if it's a symlink ? + continue; + if (file_type == IS_FILE) + { + file_mode = ::eval_file_mode( client->get_rq_script_path(), X_OK ); + if (!file_mode) + return true; + } + } + client->clear_script(); + client->status = file_mode; // 404 not_found OR 403 forbidden + return false; +} + +size_t Webserv::_cgi_pos(Client *client, std::string &path, size_t pos) { std::vector v_ext; std::vector::const_iterator it; std::vector::const_iterator it_end; - size_t pos = 0; size_t len; std::locale loc; // for isalpha() + /*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"; + 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"; + { + /*DEBUG*/ std::cout << "\nwhile\n"; if (path.compare(pos, 2, "./") == 0) - pos += 2; /*DEBUG*/ std::cout << "&path[pos]:[" << &path[pos] << "]\n"; + 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"; + { + /*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"; len = (*it).size(); if (path.compare(pos + 1, len, *it) == 0) if ( !std::isalpha(path[pos + 1 + len], loc) ) @@ -130,13 +159,14 @@ std::string Webserv::_exec_script(Client *client, char **env) 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"; - + dup2(FD_WR_TO_PRNT, STDOUT_FILENO); path = "." + client->get_rq_script_path(); + /*DEBUG*/std::cerr << "execve\n" << "path:[" << path << "]\n"; execve(path.c_str(), nll, env); // for tests execve crash : //execve("wrong", nll, env); std::cerr << "execve crashed.\n"; + // TODO HUGO : check errno } else { diff --git a/srcs/webserv/response.cpp b/srcs/webserv/response.cpp index 98e9c11..d773bb4 100644 --- a/srcs/webserv/response.cpp +++ b/srcs/webserv/response.cpp @@ -67,17 +67,15 @@ void Webserv::_append_base_headers(Client *client) client->response.append("Connection: keep-alive" CRLF); } +// TODO HUGO : wip void Webserv::_construct_response(Client *client) { std::string path; std::string script_output; path = _replace_url_root(client, client->get_rq_abs_path()); - size_t pos = _cgi_pos(client, path); /*DEBUG*/ std::cout << "pos:" << pos << "\n&path[pos]:" << &path[pos] << "\n" << B_YELLOW << "fin debug _cgi_pos()\n\n" << RESET; - - if (pos != NPOS) + if (_is_cgi(client, path)) { - client->fill_script_path(path, pos); script_output = _exec_cgi(client); _check_script_output(client, script_output); client->response += script_output;