diff --git a/README.md b/README.md index 831a28f..3f0b40e 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,16 @@ ## work together -#### TODO hugo -- `_is_cgi()` and `_fill_cgi_path()` -- two cgi tests : -? - a basic form with "name" and "something", that return a html page with that -? - for GET and POST -? - a script called by a file extension in URI +#### next commit #### questions +- 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 ? + - 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/default.config b/default.config index 3802689..9cf3a31 100644 --- a/default.config +++ b/default.config @@ -19,6 +19,11 @@ server { autoindex on; } + location /cgi-bin { + root ./srcs/cgi-bin/; + cgi_ext cpp php sh; + } + location /upload { allow_methods POST; autoindex on; diff --git a/srcs/Client.cpp b/srcs/Client.cpp index d85a0c1..03864d1 100644 --- a/srcs/Client.cpp +++ b/srcs/Client.cpp @@ -211,27 +211,22 @@ void Client::_parse_chunked_body(size_t pos) -// TODO HUGO : faire la fonction, mdr. -void Client::fill_script_path(const std::string &path, size_t pos) +void Client::fill_script_path(std::string &path, size_t pos) { - (void)path; - (void)pos; -/* size_t pos; - size_t len = path.size(); - std::string path = this->get_rq_abs_path(); std::string tmp; - pos = path.find(script); - if (pos == 0) + /*DEBUG*/ std::cout << "\n" << B_PURPLE << "debug path dot" << RESET << "\npath:[" << path << "]\n" << "&path[pos]:[" << &path[pos] << "]\n"; + if (path[0] == '.') { - tmp = path.substr(0, pos + len); - _request.script.path = "./srcs" + tmp; // TODO: root path ? - - _request.script.path = "./srcs" + tmp; // TODO: root path ? - _request.script.info = path.substr(pos + len); - return true; + path.erase(0, 1); + pos--; } - return false; */ + /*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"; } void Client::clear() diff --git a/srcs/Client.hpp b/srcs/Client.hpp index 23a855c..958d482 100644 --- a/srcs/Client.hpp +++ b/srcs/Client.hpp @@ -11,6 +11,7 @@ # include // htonl, htons, ntohl, ntohs, inet_addr, inet_ntoa # include "utils.hpp" # include "ServerConfig.hpp" +# include "colors.h" struct Script { @@ -86,7 +87,7 @@ class Client void clear(); void clear_request(); void clear_script(); - void fill_script_path(const std::string &path, size_t pos); + void fill_script_path(std::string &path, size_t pos); // DEBUG void print_client(std::string message = ""); diff --git a/srcs/cgi-bin/cgi.cpp b/srcs/cgi-bin/cgi.cpp old mode 100644 new mode 100755 index 3882239..95013cb Binary files a/srcs/cgi-bin/cgi.cpp and b/srcs/cgi-bin/cgi.cpp differ diff --git a/srcs/cgi-bin/php-cgi b/srcs/cgi-bin/cgi.php similarity index 100% rename from srcs/cgi-bin/php-cgi rename to srcs/cgi-bin/cgi.php diff --git a/srcs/cgi-bin/cgi.sh b/srcs/cgi-bin/cgi.sh new file mode 100755 index 0000000..14e0d29 --- /dev/null +++ b/srcs/cgi-bin/cgi.sh @@ -0,0 +1,4 @@ +#! /bin/bash +echo "status: 100\r\n" +echo "\r\n\r\n" +echo "hiii" diff --git a/srcs/cgi-bin/cgi_cpp.cgi b/srcs/cgi-bin/cgi_cpp.cgi deleted file mode 100755 index 95013cb..0000000 Binary files a/srcs/cgi-bin/cgi_cpp.cgi and /dev/null differ 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 8c5bdbd..90562ce 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( @@ -198,8 +213,8 @@ std::string str_tolower(std::string str) } // identify a line in a string, by delim (ex. '\n') -// delete this line from the string -// and return the deleted line +// delete this line from the string (and the following nl sequence characters) +// and return the deleted line (without the followinf nl sequence characters) std::string extract_line(std::string & str, size_t pos, std::string delim) { @@ -220,7 +235,7 @@ std::string len = end - begin; del_str = str.substr(begin, len); - str.erase(begin, len); + str.erase(begin, len + delim.size()); return del_str; } diff --git a/srcs/utils.hpp b/srcs/utils.hpp index 97171a7..ede2808 100644 --- a/srcs/utils.hpp +++ b/srcs/utils.hpp @@ -14,6 +14,7 @@ # include // tolower # include // transform # include // perror, fflush +# include // close, access # include "colors.h" // for debug print_special # define CR "\r" @@ -64,6 +65,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 cdcac07..7fe0b2a 100644 --- a/srcs/webserv/Webserv.hpp +++ b/srcs/webserv/Webserv.hpp @@ -25,12 +25,14 @@ # include // perror, remove # include // strtol, strtoul # include // opendir() +# include // isalpha, local # include "Client.hpp" # include "ServerConfig.hpp" # include "utils.hpp" # include "http_status.hpp" # include "autoindex.hpp" +# include "colors.h" extern bool g_run; extern int g_last_signal; @@ -102,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 fe81ff4..e1b4d52 100644 --- a/srcs/webserv/cgi_script.cpp +++ b/srcs/webserv/cgi_script.cpp @@ -1,21 +1,72 @@ #include "Webserv.hpp" -// TODO HUGO : go ameliorer la recherche comme on a dit. -size_t Webserv::_cgi_pos(Client *client, std::string &path) +bool Webserv::_is_cgi(Client *client, std::string path) { - size_t pos = NPOS; - std::vector::const_iterator it; - it = client->assigned_location->cgi_ext.begin(); - while (it != client->assigned_location->cgi_ext.end()) + std::string script_path; + size_t file_type; + size_t file_mode; + size_t pos = 0; + + while (pos != NPOS) { - pos = std::min(path.find(*it) + it->size(), pos); - ++it; + 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); + script_path = "." + client->get_rq_script_path(); + file_type = ::eval_file_type(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( script_path, X_OK ); + if (!file_mode) + return true; + } } - if (pos == NPOS) - return false; - else - return true; + client->clear_script(); + 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 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"; + 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"; + len = (*it).size(); + if (path.compare(pos + 1, len, *it) == 0) + if ( !std::isalpha(path[pos + 1 + len], loc) ) + return pos + 1 + len; + } + pos++; + } + return NPOS; } std::string Webserv::_exec_cgi(Client *client) @@ -98,6 +149,7 @@ std::string Webserv::_exec_script(Client *client, char **env) int fd_out[2]; int save_in = dup(STDIN_FILENO); int save_out = dup(STDOUT_FILENO); + std::string path; pipe(fd_in); pipe(fd_out); @@ -111,12 +163,13 @@ std::string Webserv::_exec_script(Client *client, char **env) 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); + 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/method_post.cpp b/srcs/webserv/method_post.cpp index 5218453..9ee0aaa 100644 --- a/srcs/webserv/method_post.cpp +++ b/srcs/webserv/method_post.cpp @@ -24,7 +24,7 @@ void Webserv::_post(Client *client, const std::string &path) client->response.append(CRLF); } else - _upload_file(client); + _upload_files(client); } #define DEFAULT_NAME "unnamed_file" diff --git a/srcs/webserv/response.cpp b/srcs/webserv/response.cpp index 05a83b0..5c249ad 100644 --- a/srcs/webserv/response.cpp +++ b/srcs/webserv/response.cpp @@ -73,19 +73,20 @@ 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 = _replace_url_root(client, client->get_rq_abs_path()); + std::string path; + std::string script_output; -/* size_t pos = _cgi_pos(client, path); - if (pos != NPOS) + path = _replace_url_root(client, client->get_rq_abs_path()); + if (_is_cgi(client, path)) { - client->fill_script_path(path, pos); - std::string script_output = _exec_cgi(client); + script_output = _exec_cgi(client); _check_script_output(client, script_output); client->response += script_output; return; - } */ + } _process_method(client, path); }