diff --git a/Makefile b/Makefile index 2f15769..a67a053 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ NAME = webserv -CXX = clang++ +CXX = c++ CXXFLAGS = -Wall -Wextra #-Werror CXXFLAGS += $(HEADERS_D:%=-I%) diff --git a/default.config b/default.config index 344ea17..125be8b 100644 --- a/default.config +++ b/default.config @@ -43,7 +43,7 @@ server { location /cgi-bin { root ./srcs/cgi-bin/; - cgi_ext cpp php sh; + cgi_ext out php sh; } location /cgi-bin { diff --git a/srcs/Client.cpp b/srcs/Client.cpp index f3247c2..bd81115 100644 --- a/srcs/Client.cpp +++ b/srcs/Client.cpp @@ -215,18 +215,13 @@ void Client::fill_script_path(std::string &path, size_t pos) { std::string tmp; - /*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"; - _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.cpp b/srcs/cgi-bin/cgi.cpp deleted file mode 100755 index 95013cb..0000000 Binary files a/srcs/cgi-bin/cgi.cpp and /dev/null differ diff --git a/srcs/cgi-bin/cgi_cpp.cpp b/srcs/cgi-bin/cgi_cpp.cpp new file mode 100644 index 0000000..8cabc71 --- /dev/null +++ b/srcs/cgi-bin/cgi_cpp.cpp @@ -0,0 +1,114 @@ +# include +# include +# include +# include +# include // getenv + +# define CR "\r" +# define LF "\n" +# define CRLF CR LF +# define NPOS std::string::npos + +std::string trim(std::string str, char del) +{ + size_t pos; + + // delete leadings del + pos = str.find_first_not_of(del); + if (pos == NPOS) + pos = str.size(); + str = str.substr(pos); + + // delete trailing del + pos = str.find_last_not_of(del); + if (pos != NPOS) + str = str.substr(0, pos + 1); + + return str; +} + +std::vector + split(const std::string & input, std::string delim, char ctrim = '\0') +{ + std::vector split_str; + std::string tmp; + size_t start = 0; + size_t end = 0; + size_t len = 0; + + while (end != NPOS) + { + end = input.find(delim, start); + len = end - start; + if (end == NPOS) + len = end; + tmp = input.substr(start, len); + if (ctrim != '\0') + tmp = trim(tmp, ctrim); + if (tmp.size() != 0) + split_str.push_back( tmp ); + start = end + delim.size(); + } + return split_str; +} + +int main (int ac, char **av, char **en) +{ + std::vector split_str; + std::vector sub_split_str; + std::vector::const_iterator it; + char * tmp; + std::string input; + std::string http_header; + std::string http_body; + std::ostringstream strs; + size_t pos; + + std::cin >> input; + + http_header = "Content-Type: text/html; charset=UTF-8" CRLF; + http_header += "Content-Length: "; + + http_body = "\ + \ + \ + \ + CGI\ + \ + \ +

cgi

\ + "; + + http_body += "

"; + tmp = getenv("REQUEST_METHOD"); + if (tmp != NULL) + http_body += tmp; + else + http_body = "method not foud"; + http_body += "

"; + + split_str = split(input, "&"); + for (it = split_str.begin(); it != split_str.end(); ++it) + { + sub_split_str = split(*it, "="); + http_body += "

"; + http_body += sub_split_str[0]; + http_body += "

"; + http_body += "

"; + http_body += sub_split_str[1]; + http_body += "

"; + } + + http_body += "\ + \ + \ + "; + + strs << http_body.size(); + http_header += strs.str(); + http_header += CRLF CRLF; + + std::cout << http_header << CRLF CRLF << http_body; + return 0; +} + diff --git a/srcs/cgi-bin/cgi_cpp_content_length.cpp b/srcs/cgi-bin/cgi_cpp_content_length.cpp new file mode 100644 index 0000000..9bb5089 --- /dev/null +++ b/srcs/cgi-bin/cgi_cpp_content_length.cpp @@ -0,0 +1,133 @@ +# include +# include +# include +# include +# include // getenv + +# define CR "\r" +# define LF "\n" +# define CRLF CR LF +# define NPOS std::string::npos + +std::string trim(std::string str, char del) +{ + size_t pos; + + // delete leadings del + pos = str.find_first_not_of(del); + if (pos == NPOS) + pos = str.size(); + str = str.substr(pos); + + // delete trailing del + pos = str.find_last_not_of(del); + if (pos != NPOS) + str = str.substr(0, pos + 1); + + return str; +} + +std::vector + split(const std::string & input, std::string delim, char ctrim = '\0') +{ + std::vector split_str; + std::string tmp; + size_t start = 0; + size_t end = 0; + size_t len = 0; + + while (end != NPOS) + { + end = input.find(delim, start); + len = end - start; + if (end == NPOS) + len = end; + tmp = input.substr(start, len); + if (ctrim != '\0') + tmp = trim(tmp, ctrim); + if (tmp.size() != 0) + split_str.push_back( tmp ); + start = end + delim.size(); + } + return split_str; +} + +int main (int ac, char **av, char **en) { + std::vector split_str; + std::vector sub_split_str; + std::vector::const_iterator it; + char * tmp; + std::string output; + std::ostringstream strs; + size_t pos; + + std::cout << "Content-Type: text/html; charset=UTF-8" << CRLF CRLF; + + std::cout + << "" + << "" + << "" + << " CGI" + << "" + << "" + << "

cgi

" + << "

"; + + tmp = getenv("REQUEST_METHOD"); + if (tmp != NULL) + output = tmp; + else + output = "method not foud"; + + std::cout + << output + << "

" + << "

http-request-body-message content :

"; + + + std::cin >> output; + split_str = split(output, "&"); + output.clear(); + for (it = split_str.begin(); it != split_str.end(); ++it) + { + sub_split_str = split(*it, "="); + + std::cout + << "

" + << sub_split_str[0] + << " : " + << sub_split_str[1] + << "

"; + } + + tmp = getenv("QUERY_STRING"); + if (tmp == NULL) + std::cout << "query not foud"; + + std::cout + << "

http-uri-query content :

"; + + output = tmp; + split_str = split(output, "&"); + output.clear(); + for (it = split_str.begin(); it != split_str.end(); ++it) + { + sub_split_str = split(*it, "="); + + std::cout + << "

" + << sub_split_str[0] + << "

" + << "

" + << sub_split_str[1] + << "

"; + } + + + std::cout + << "" + << ""; + + return 0; +} + diff --git a/srcs/utils.cpp b/srcs/utils.cpp index 90562ce..793c46b 100644 --- a/srcs/utils.cpp +++ b/srcs/utils.cpp @@ -226,7 +226,7 @@ std::string begin = str.rfind(delim, pos); if (begin == NPOS) begin = 0; - else + else if (begin < pos) begin += delim.size(); end = str.find(delim, pos); diff --git a/srcs/webserv/Webserv.hpp b/srcs/webserv/Webserv.hpp index 7fe0b2a..1c9ace1 100644 --- a/srcs/webserv/Webserv.hpp +++ b/srcs/webserv/Webserv.hpp @@ -114,6 +114,8 @@ class Webserv 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); + void _add_script_body_length_header(std::string & output); + void _remove_body_leading_empty_lines(std::string & output); // epoll_update.cpp int _epoll_update(int fd, uint32_t events, int op); int _epoll_update(int fd, uint32_t events, int op, void *ptr); diff --git a/srcs/webserv/cgi_script.cpp b/srcs/webserv/cgi_script.cpp index e1b4d52..7978ddb 100644 --- a/srcs/webserv/cgi_script.cpp +++ b/srcs/webserv/cgi_script.cpp @@ -11,7 +11,6 @@ bool Webserv::_is_cgi(Client *client, std::string path) 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); @@ -27,7 +26,6 @@ bool Webserv::_is_cgi(Client *client, std::string path) } } client->clear_script(); - client->clear_script(); client->status = file_mode; // 404 not_found OR 403 forbidden return false; } @@ -40,25 +38,20 @@ size_t Webserv::_cgi_pos(Client *client, std::string &path, size_t pos) 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) ) @@ -147,8 +140,6 @@ std::string Webserv::_exec_script(Client *client, char **env) 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); std::string path; pipe(fd_in); @@ -157,21 +148,22 @@ std::string Webserv::_exec_script(Client *client, char **env) pid = fork(); if (pid == -1) std::cerr << "fork crashed" << std::endl; - else if (pid == 0) + else if (pid == 0) // child { close(FD_WR_TO_CHLD); close(FD_RD_FR_CHLD); dup2(FD_RD_FR_PRNT, STDIN_FILENO); dup2(FD_WR_TO_PRNT, STDOUT_FILENO); path = "." + client->get_rq_script_path(); - /*DEBUG*/std::cerr << "execve\n" << "path:[" << path << "]\n"; +/*DEBUG*/std::cerr << "execve:[" << 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 + else //parent { close(FD_RD_FR_PRNT); close(FD_WR_TO_PRNT); @@ -189,9 +181,7 @@ std::string Webserv::_exec_script(Client *client, char **env) } 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; } @@ -199,6 +189,8 @@ void Webserv::_check_script_output(Client *client, std::string & output) { _check_script_status(client, output); _check_script_fields(client, output); + _add_script_body_length_header(output); + _remove_body_leading_empty_lines(output); // _check_script_empty_lines(client, output); // _check_script_space_colons(client, output); // _check_script_new_lines(client, output); @@ -255,3 +247,58 @@ void Webserv::_check_script_fields(Client *client, std::string & output) } } +void Webserv::_remove_body_leading_empty_lines(std::string & output) +{ + size_t pos; + size_t pos_empty; + + pos = output.find(CRLF CRLF); + if (pos == NPOS) + return; + pos += CRLF_SIZE * 2; + pos_empty = pos; + while (pos_empty == pos) + { + pos = output.find(CRLF, pos); + if (pos == pos_empty) + extract_line(output, pos, CRLF); + } +} + +void Webserv::_add_script_body_length_header(std::string & output) +{ + std::map field; + std::map::iterator it; + std::stringstream str_len; + std::string tmp; + size_t pos; + size_t len; + + pos = output.find(CRLF CRLF); + if (pos != NPOS) + tmp = output.substr(pos + CRLF_SIZE); + len = tmp.size(); + str_len << len; + + // put script headers in map + tmp = output; + pos = tmp.find(CRLF CRLF); + if (pos != NPOS) + tmp.erase(pos); + ::parse_http_headers(tmp, field); + // case insensitive search in map for "Content-Length" + tmp = "Content-Length"; + for (it = field.begin(); it != field.end(); ++it) + { + if (str_tolower(it->first) == str_tolower(tmp)) + { + pos = output.find(it->first); + ::extract_line(output, pos, CRLF); + } + } + tmp += ": "; + tmp += str_len.str(); + tmp += CRLF; + output.insert(0, tmp); +} + diff --git a/srcs/webserv/parsing_message_http.cpp b/srcs/webserv/parsing_message_http.cpp deleted file mode 100644 index 2712f20..0000000 --- a/srcs/webserv/parsing_message_http.cpp +++ /dev/null @@ -1,17 +0,0 @@ - -#include "parsing_message_http.hpp" - -std::string - parse_http_body(std::string message) -{ - std::string body; - size_t pos; - - pos = message.find(CRLF CRLF); - pos += std::string(CRLF CRLF).size(); - // TODO: copying just like that might fail in case of binary or images - body = message.substr(pos); - - return body; -} - diff --git a/srcs/webserv/parsing_message_http.hpp b/srcs/webserv/parsing_message_http.hpp deleted file mode 100644 index d1e77ed..0000000 --- a/srcs/webserv/parsing_message_http.hpp +++ /dev/null @@ -1,32 +0,0 @@ - -#ifndef PARSING_MESSAGE_HTTP_HPP -# define PARSING_MESSAGE_HTTP_HPP - -# include -# include -# include -# include -# include "utils.hpp" - -std::map - parse_http_headers ( - std::string headers, - std::map fields ) - -std::string - parse_http_body(std::string message); - -// http message structure : -// -// start-line -// request-line -// method SP target SP version -// response-line -// version SP status SP reason -// header-fields -// name ":" SP value -// CRLF -// body - -#endif - diff --git a/srcs/webserv/response.cpp b/srcs/webserv/response.cpp index 6cce4c0..20f9e41 100644 --- a/srcs/webserv/response.cpp +++ b/srcs/webserv/response.cpp @@ -47,6 +47,8 @@ int Webserv::_send_response(Client *client) if (client->status >= 400) _error_html_response(client); +/*DEBUG*/ std::cout << "\n" B_PURPLE "[response + output + headers]:" RESET "\n"; ::print_special(client->response); std::cout << B_PURPLE "-----------" RESET "\n\n"; + std::cerr << "client->response.size() = " << client->response.size() << "\n"; // DEBUG ret = ::send(client->get_cl_fd(), client->response.c_str(), client->response.size(), 0); if (ret == -1) @@ -83,8 +85,15 @@ void Webserv::_construct_response(Client *client) if (_is_cgi(client, path)) { script_output = _exec_cgi(client); + +/*DEBUG*/ std::cout << "\n" B_PURPLE "[script output]:" RESET "\n"; ::print_special(script_output); std::cout << B_PURPLE "-----------" RESET "\n\n"; +/*DEBUG*/ std::cout << "\n" B_PURPLE "[response]:" RESET "\n"; ::print_special(client->response); std::cout << B_PURPLE "-----------" RESET "\n\n"; + _check_script_output(client, script_output); client->response += script_output; + +/*DEBUG*/ std::cout << "\n" B_PURPLE "[response + output]:" RESET "\n"; ::print_special(client->response); std::cout << B_PURPLE "-----------" RESET "\n\n"; + return; } _process_method(client, path); diff --git a/www/form_get.html b/www/form_get.html index 626478d..8379b2d 100644 --- a/www/form_get.html +++ b/www/form_get.html @@ -3,11 +3,82 @@ + -
+ + + +

get form

+

to /cgi-bin/cgi_cpp.out

+
+
+
+

+
+
+ +
+ +

post form

+

to /cgi-bin/cgi_cpp.out

+
+
+
+

+ + +
+
+ +
+ +

get form

+

to /cgi-bin/cgi_cpp_content_length.out

+
+
+
+

+ + +
+
+ +
+ +

post form

+

to /cgi-bin/cgi_cpp_content_length.out

+
+
+
+

+ + +
+
+ diff --git a/www/form_post.html b/www/form_post.html deleted file mode 100644 index ae36576..0000000 --- a/www/form_post.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - -
- -
- - -