merge hugo5 with script cgi tests

This commit is contained in:
Hugo LAMY
2022-08-17 18:26:06 +02:00
26 changed files with 628 additions and 133 deletions

View File

@@ -1,17 +1,6 @@
## work together ## work together
#### 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 ?
--- ---
## man ## man
@@ -243,6 +232,10 @@ SERVER_SOFTWARE : the server software you're using (e.g. Apache 1.3)
REDIRECT_STATUS : for exemple, 200 REDIRECT_STATUS : for exemple, 200
``` ```
g 50 34 48
p 30 23 32
l 20 14 20
71
--- ---
## http status ## http status

View File

@@ -221,11 +221,6 @@ void Client::fill_script_path(std::string &path, size_t pos)
{ {
std::string tmp; std::string tmp;
if (path[0] == '.')
{
path.erase(0, 1);
pos--;
}
_request.script.path = path.substr(0, pos); _request.script.path = path.substr(0, pos);
_request.script.info = path.substr(pos); _request.script.info = path.substr(pos);
} }

View File

@@ -1,3 +1,4 @@
# - - - - - - # # - - - - - - #
# # # #
# COLORS # # COLORS #
@@ -30,11 +31,7 @@ RESET = "\e[0m"
# . name is case sensitive . ?= set if not already set # # . name is case sensitive . ?= set if not already set #
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
NAME_1 = $(SRCS_1:.cpp=.out) NAME = $(SRCS_X:.cpp=.out)
NAME_2 = $(SRCS_2:.cpp=.out)
NAME_3 = $(SRCS_3:.cpp=.out)
NAME_4 = $(SRCS_4:.cpp=.out)
NAME_5 = $(SRCS_5:.cpp=.out)
CXX = c++ CXX = c++
CXXFLAGS = -Wall -Wextra #-Werror CXXFLAGS = -Wall -Wextra #-Werror
@@ -47,19 +44,24 @@ HEADERS_D = .
SRCS_D = . SRCS_D = .
SRCS = cgi_utils.cpp SRCS = cgi_utils.cpp
SRCS_1 = cgi_cpp.cpp SRCS_X = \
SRCS_2 = cgi_cpp_len.cpp cgi_cpp.cpp \
SRCS_3 = cgi_cpp_len_big.cpp cgi_cpp_bad_headers.cpp \
SRCS_4 = cgi_cpp_len_small.cpp cgi_cpp_empty.cpp \
SRCS_5 = cgi_cpp_status.cpp cgi_cpp_empty_lines.cpp \
cgi_cpp_len.cpp \
cgi_cpp_len_big.cpp \
cgi_cpp_len_small.cpp \
cgi_cpp_no_body.cpp \
cgi_cpp_no_headers.cpp \
cgi_cpp_only_crlf.cpp \
cgi_cpp_sleep.cpp \
cgi_cpp_status.cpp \
cgi_cpp_download.cpp \
OBJS_D = builds OBJS_D = builds
OBJS = $(SRCS:%.cpp=$(OBJS_D)/%.o) OBJS = $(SRCS:%.cpp=$(OBJS_D)/%.o)
OBJS_1 = $(SRCS_1:%.cpp=$(OBJS_D)/%.o) OBJS_X = $(SRCS_X:%.cpp=$(OBJS_D)/%.o)
OBJS_2 = $(SRCS_2:%.cpp=$(OBJS_D)/%.o)
OBJS_3 = $(SRCS_3:%.cpp=$(OBJS_D)/%.o)
OBJS_4 = $(SRCS_4:%.cpp=$(OBJS_D)/%.o)
OBJS_5 = $(SRCS_5:%.cpp=$(OBJS_D)/%.o)
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# . target: prerequisites . $@ : target # # . target: prerequisites . $@ : target #
@@ -67,36 +69,25 @@ OBJS_5 = $(SRCS_5:%.cpp=$(OBJS_D)/%.o)
# . recipe . $^ : all prerequisites # # . recipe . $^ : all prerequisites #
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
all: cgi_1 cgi_2 cgi_3 cgi_4 cgi_5 all: $(NAME)
cgi_1: $(NAME_1)
cgi_2: $(NAME_2)
cgi_3: $(NAME_3)
cgi_4: $(NAME_4)
cgi_5: $(NAME_5)
$(OBJS_D)/%.o: %.cpp | $(OBJS_D) $(OBJS_D)/%.o: %.cpp | $(OBJS_D)
@echo $(B_GREEN)"compilation :" $@ $(RESET)
$(CXX) $(CXXFLAGS) -c $< -o $@ $(CXX) $(CXXFLAGS) -c $< -o $@
$(OBJS_D): $(OBJS_D):
mkdir $@ mkdir $@
$(NAME_1): $(OBJS) $(OBJS_1) $(NAME): $(OBJS) $(OBJS_X)
$(NAME_2): $(OBJS) $(OBJS_2) $(NAME):
$(NAME_3): $(OBJS) $(OBJS_3) @echo $(B_YELLOW)"linkage :" $@ $(RESET)
$(NAME_4): $(OBJS) $(OBJS_4) $(CXX) $(OBJS) $(@:%.out=$(OBJS_D)/%.o) -o $@
$(NAME_5): $(OBJS) $(OBJS_5)
$(NAME_1) $(NAME_2) $(NAME_3) $(NAME_4) $(NAME_5):
$(CXX) $^ -o $@
clean: clean:
rm -rf $(OBJS_D) rm -rf $(OBJS_D)
fclean: clean fclean: clean
rm -f $(NAME_1) rm -f $(NAME)
rm -f $(NAME_2)
rm -f $(NAME_3)
rm -f $(NAME_4)
rm -f $(NAME_5)
re: fclean all re: fclean all

View File

@@ -5,25 +5,20 @@
int main (int ac, char **av, char ** env) int main (int ac, char **av, char ** env)
{ {
std::string http_header; std::string http_header;
std::string http_body; std::string http_body;
std::string rq_body;
std::cin >> rq_body;
(void)ac; (void)ac;
(void)av; (void)av;
// ::sleep(5); http_header = "Content-Type: text/html; charset=UTF-8" CRLF;
fill_response_basic(env, http_body, http_header); fill_body_basic(env, http_body, rq_body);
std::cout << http_header; std::cout << http_header << CRLF << http_body;
std::flush(std::cout);
::sleep(2);
std::cout << CRLF CRLF;
std::flush(std::cout);
::sleep(2);
std::cout << http_body;
std::flush(std::cout);
::sleep(2);
return 0; return 0;
} }

View File

@@ -0,0 +1,24 @@
# include "cgi_utils.hpp"
int main (int ac, char **av, char ** env)
{
std::string http_header;
std::string http_body;
std::string http_status;
std::string rq_body;
std::cin >> rq_body;
(void)ac;
(void)av;
http_header = "Bad-Headers: wrong";
fill_body_basic(env, http_body, rq_body);
std::cout << http_header << CRLF << http_body;
return 0;
}

View File

@@ -0,0 +1,55 @@
# include "cgi_utils.hpp"
int main (int ac, char **av, char ** env)
{
std::string http_header;
std::string http_body;
std::string rq_body;
std::string form_infos;
std::string path;
std::ifstream ifd;
std::stringstream buf;
size_t status;
std::cin >> rq_body;
(void)ac;
(void)av;
(void)env;
http_header = "Content-Type: image/jpeg" CRLF;
form_infos = get_form_infos(rq_body);
path = get_value("file", rq_body);
path = "./www/" + path;
status = ::eval_file_read(path);
if (status)
{
std::cout << "Status: " << status << CRLF CRLF;
return 0;
}
ifd.open(path.c_str());
if (!ifd)
{
std::cout << "Status: " << 500 << CRLF CRLF;
return 0;
}
else
{
buf << ifd.rdbuf();
if (!ifd || !buf)
{
std::cout << "Status: " << 500 << CRLF CRLF;
return 0;
}
}
std::cout << http_header << CRLF << buf.str();
return 0;
}

View File

@@ -0,0 +1,12 @@
# include "cgi_utils.hpp"
int main (int ac, char **av, char ** env)
{
(void)ac;
(void)av;
(void)env;
return 0;
}

View File

@@ -0,0 +1,23 @@
# include "cgi_utils.hpp"
int main (int ac, char **av, char ** env)
{
std::string http_header;
std::string http_body;
std::string rq_body;
std::cin >> rq_body;
(void)ac;
(void)av;
http_header = "Content-Type: text/html; charset=UTF-8" CRLF;
fill_body_basic(env, http_body, rq_body);
std::cout << http_header << CRLF CRLF CRLF CRLF CRLF << http_body;
return 0;
}

View File

@@ -5,15 +5,20 @@ int main (int ac, char **av, char ** env)
{ {
std::string http_header; std::string http_header;
std::string http_body; std::string http_body;
std::string rq_body;
std::cin >> rq_body;
(void)ac; (void)ac;
(void)av; (void)av;
fill_response_basic(env, http_body, http_header); http_header = "Content-Type: text/html; charset=UTF-8" CRLF;
http_header += "Content-Length: " + itos(http_body.size()) + CRLF;
http_header += "Content-Length: " + itos(http_body.size()); fill_body_basic(env, http_body, rq_body);
std::cout << http_header << CRLF CRLF << http_body;
std::cout << http_header << CRLF << http_body;
return 0; return 0;
} }

View File

@@ -3,17 +3,22 @@
int main (int ac, char **av, char ** env) int main (int ac, char **av, char ** env)
{ {
std::string http_header; std::string http_header;
std::string http_body; std::string http_body;
std::string rq_body;
std::cin >> rq_body;
(void)ac; (void)ac;
(void)av; (void)av;
fill_response_basic(env, http_body, http_header); http_header = "Content-Type: text/html; charset=UTF-8" CRLF;
http_header += "Content-Length: " + itos(http_body.size() + 100) + CRLF;
http_header += "Content-Length: " + itos(http_body.size() + 100); fill_body_basic(env, http_body, rq_body);
std::cout << http_header << CRLF CRLF << http_body;
std::cout << http_header << CRLF << http_body;
return 0; return 0;
} }

View File

@@ -3,17 +3,21 @@
int main (int ac, char **av, char ** env) int main (int ac, char **av, char ** env)
{ {
std::string http_header; std::string http_header;
std::string http_body; std::string http_body;
std::string rq_body;
std::cin >> rq_body;
(void)ac; (void)ac;
(void)av; (void)av;
fill_response_basic(env, http_body, http_header); http_header = "Content-Type: text/html; charset=UTF-8" CRLF;
http_header += "Content-Length: " + itos(http_body.size() - 100) + CRLF;
http_header += "Content-Length: " + itos(http_body.size() - 100); fill_body_basic(env, http_body, rq_body);
std::cout << http_header << CRLF CRLF << http_body; std::cout << http_header << CRLF << http_body;
return 0; return 0;
} }

View File

@@ -0,0 +1,22 @@
# include "cgi_utils.hpp"
int main (int ac, char **av, char ** env)
{
std::string http_header;
std::string http_status;
std::string rq_body;
std::cin >> rq_body;
(void)ac;
(void)av;
(void)env;
http_header = "Content-Type: text/html; charset=UTF-8" CRLF;
std::cout << http_header << CRLF;
return 0;
}

View File

@@ -0,0 +1,24 @@
# include "cgi_utils.hpp"
int main (int ac, char **av, char ** env)
{
std::string http_header;
std::string http_body;
std::string http_status;
std::string rq_body;
std::cin >> rq_body;
(void)ac;
(void)av;
http_header = CRLF;
fill_body_basic(env, http_body, rq_body);
std::cout << CRLF << http_body;
return 0;
}

View File

@@ -0,0 +1,15 @@
# include "cgi_utils.hpp"
int main (int ac, char **av, char ** env)
{
(void)ac;
(void)av;
(void)env;
std::cout << CRLF CRLF;
return 0;
}

View File

@@ -0,0 +1,29 @@
# include "cgi_utils.hpp"
int main (int ac, char **av, char ** env)
{
std::string http_header;
std::string http_body;
std::string rq_body;
size_t time;
std::stringstream ss;
std::cin >> rq_body;
(void)ac;
(void)av;
http_header = "Content-Type: text/html; charset=UTF-8" CRLF;
fill_body_basic(env, http_body, rq_body);
ss << get_value("sleep", rq_body);
ss >> time;
sleep(time);
std::cout << http_header << CRLF << http_body;
return 0;
}

View File

@@ -6,14 +6,19 @@ int main (int ac, char **av, char ** env)
std::string http_header; std::string http_header;
std::string http_body; std::string http_body;
std::string http_status; std::string http_status;
std::string rq_body;
std::cin >> rq_body;
(void)ac; (void)ac;
(void)av; (void)av;
fill_response_basic(env, http_body, http_header); http_header = "Content-Type: text/html; charset=UTF-8" CRLF;
http_status = get_value("Status"); fill_body_basic(env, http_body, rq_body);
http_header += "Status: " + http_status;
http_status = get_value("Status", rq_body);
http_header += "Status: " + http_status + CRLF;
std::cout << http_header << CRLF CRLF << http_body; std::cout << http_header << CRLF CRLF << http_body;

View File

@@ -69,14 +69,6 @@ std::string parse_env(const std::string & env)
return ret; return ret;
} }
std::string parse_body()
{
std::string ret;
std::cin >> ret;
return ret;
}
std::string print_env(char **env, std::string tag) std::string print_env(char **env, std::string tag)
{ {
std::string ret = ""; std::string ret = "";
@@ -114,7 +106,7 @@ std::string
return ret; return ret;
} }
std::string get_form_infos() std::string get_form_infos(const std::string & rq_body)
{ {
std::string form_infos; std::string form_infos;
std::string method; std::string method;
@@ -122,14 +114,14 @@ std::string get_form_infos()
method = parse_env("REQUEST_METHOD"); method = parse_env("REQUEST_METHOD");
if (method == "POST") if (method == "POST")
form_infos = parse_body(); form_infos = rq_body;
else if (method == "GET") else if (method == "GET")
form_infos = parse_env("QUERY_STRING"); form_infos = parse_env("QUERY_STRING");
return form_infos; return form_infos;
} }
std::string get_value(std::string key) std::string get_value(const std::string & key, const std::string & rq_body)
{ {
std::string infos; std::string infos;
std::string ret; std::string ret;
@@ -137,7 +129,7 @@ std::string get_value(std::string key)
size_t end; size_t end;
size_t len; size_t len;
infos = get_form_infos(); infos = get_form_infos(rq_body);
pos = str_tolower(infos).find(str_tolower(key)); pos = str_tolower(infos).find(str_tolower(key));
if (pos == NPOS) if (pos == NPOS)
return ""; return "";
@@ -155,15 +147,13 @@ std::string get_value(std::string key)
} }
void void
fill_response_basic(char **env, std::string & http_body, std::string & http_header) fill_body_basic(char **env, std::string & http_body, const std::string & rq_body)
{ {
std::string rq_method = "not found"; std::string rq_method = "not found";
std::string rq_body;
std::string rq_query; std::string rq_query;
std::string form_infos; std::string form_infos;
rq_method = parse_env("REQUEST_METHOD"); rq_method = parse_env("REQUEST_METHOD");
rq_body = parse_body();
rq_query = parse_env("QUERY_STRING"); rq_query = parse_env("QUERY_STRING");
if (rq_method == "POST") if (rq_method == "POST")
@@ -189,7 +179,21 @@ void
http_body += print_env(env, "p"); http_body += print_env(env, "p");
http_body += HTML_BODY_BOTTOM; http_body += HTML_BODY_BOTTOM;
}
http_header = "Content-Type: text/html; charset=UTF-8" CRLF;
size_t eval_file_read(const std::string &path)
{
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(), R_OK) == -1)
{
std::perror("err access()");
return 403; // FORBIDDEN, file doesn't have access permission
}
return 0;
} }

View File

@@ -5,9 +5,11 @@
# include <iostream> # include <iostream>
# include <string> # include <string>
# include <sstream> # include <sstream>
# include <fstream>
# include <vector> # include <vector>
# include <stdlib.h> // getenv # include <stdlib.h> // getenv
# include <algorithm> // transform # include <algorithm> // transform
# include <unistd.h> // sleep, close, access
# define CR "\r" # define CR "\r"
# define LF "\n" # define LF "\n"
@@ -24,42 +26,43 @@
" <link href=\"./cgi_style.css\" type=\"text/css\" rel=\"stylesheet\">"\ " <link href=\"./cgi_style.css\" type=\"text/css\" rel=\"stylesheet\">"\
" </head>"\ " </head>"\
" <body>"\ " <body>"\
" <h1>cgi</h1><br>" " <h1>CGI</h1><br>"
# define HTML_BODY_BOTTOM " </body>"\ # define HTML_BODY_BOTTOM " <br><h1>END CGI</h1>"\
" </body>"\
"</html>" "</html>"
std::string std::string
str_tolower(std::string str); str_tolower(std::string str);
std::string std::string
trim(std::string str, char del); trim(std::string str, char del);
std::vector<std::string> std::vector<std::string>
split(const std::string & input, std::string delim, char ctrim = '\0'); split(const std::string & input, std::string delim, char ctrim = '\0');
std::string std::string
itos(int n); itos(int n);
std::string std::string
parse_env(const std::string & env); parse_env(const std::string & env);
std::string std::string
parse_body(); print_env(char **env, std::string tag = "p");
std::string std::string
print_env(char **env, std::string tag = "p"); get_form_infos(const std::string & rq_body);
std::string std::string
get_form_infos(); get_value(const std::string & key, const std::string & rq_body);
std::string std::string
get_value(std::string key); print_form(std::string form, std::string key = "p", std::string val = "p");
std::string
print_form(std::string form, std::string key = "p", std::string val = "p");
void void
fill_response_basic(char **env, std::string & body, std::string & header); fill_body_basic(char **env, std::string & http_body, const std::string & rq_body);
size_t
eval_file_read(const std::string &path);
#endif #endif

View File

@@ -132,17 +132,15 @@ class Webserv
void _exec_script(Client *client, char *env[]); void _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); size_t _check_script_fields(const std::string & output, size_t status);
void _check_fields_duplicates(Client *client, std::string & output);
void _add_script_body_length_header(std::string & output); void _add_script_body_length_header(std::string & output);
void _remove_body_leading_empty_lines(std::string & output); void _remove_body_leading_empty_lines(std::string & output);
Client *_find_cgi_fd(int cgi_fd);
void _read_cgi_output(Client *client);
Client *_find_cgi_fd(int cgi_fd); void _handle_epoll_error_cgi_fd(uint32_t events, Client *client);
void _read_cgi_output(Client *client); void _cgi_epollhup(uint32_t events, Client *client);
void _handle_epoll_error_cgi_fd(uint32_t events, Client *client);
void _cgi_epollhup(uint32_t events, Client *client);
/////////////////////// ///////////////////////

View File

@@ -18,7 +18,7 @@ bool Webserv::_is_cgi(Client *client, std::string path)
if (pos == NPOS) if (pos == NPOS)
break; break;
client->fill_script_path(path, pos); client->fill_script_path(path, pos);
script_path = "." + client->get_rq_script_path(); script_path = client->get_rq_script_path();
file_type = ::eval_file_type(script_path); file_type = ::eval_file_type(script_path);
if (file_type == IS_DIR) // but what if it's a symlink ? if (file_type == IS_DIR) // but what if it's a symlink ?
continue; continue;
@@ -126,7 +126,7 @@ void Webserv::_set_env_vector(Client *client, std::vector<std::string> &env_vect
env_vector.push_back(_dup_env("REMOTE_IDENT")); // authentification not supported env_vector.push_back(_dup_env("REMOTE_IDENT")); // authentification not supported
env_vector.push_back(_dup_env("REMOTE_USER")); // authentification not supported env_vector.push_back(_dup_env("REMOTE_USER")); // authentification not supported
env_vector.push_back(_dup_env("REQUEST_METHOD" , client->get_rq_method_str())); env_vector.push_back(_dup_env("REQUEST_METHOD" , client->get_rq_method_str()));
env_vector.push_back(_dup_env("SCRIPT_NAME" , client->get_rq_script_path())); // LUKE: To Check env_vector.push_back(_dup_env("SCRIPT_NAME" , "/" + client->get_rq_script_path())); // LUKE: To Check
env_vector.push_back(_dup_env("SERVER_NAME" , client->get_cl_lsocket()->host)); env_vector.push_back(_dup_env("SERVER_NAME" , client->get_cl_lsocket()->host));
env_vector.push_back(_dup_env("SERVER_PORT" , client->get_cl_lsocket()->port)); env_vector.push_back(_dup_env("SERVER_PORT" , client->get_cl_lsocket()->port));
env_vector.push_back(_dup_env("SERVER_PROTOCOL" , "HTTP/1.1")); env_vector.push_back(_dup_env("SERVER_PROTOCOL" , "HTTP/1.1"));
@@ -200,7 +200,7 @@ void Webserv::_exec_script(Client *client, char *env[])
::close(FD_RD_FR_PRNT); ::close(FD_RD_FR_PRNT);
::close(FD_WR_TO_PRNT); ::close(FD_WR_TO_PRNT);
path = "." + client->get_rq_script_path(); // Wut ? Only relative path ? path = client->get_rq_script_path(); // Wut ? Only relative path ?
/*DEBUG*/std::cerr << "execve:[" << path << "]\n"; /*DEBUG*/std::cerr << "execve:[" << path << "]\n";
if (::execve(path.c_str(), nll, env) == -1) // replace path for debug error forcing if (::execve(path.c_str(), nll, env) == -1) // replace path for debug error forcing
{ {
@@ -241,16 +241,14 @@ void Webserv::_check_script_output(Client *client, std::string & output)
_check_script_status(client, output); _check_script_status(client, output);
if (client->status >= 400 && client->status < 600) if (client->status >= 400 && client->status < 600)
return; return;
///*DEBUG*/ std::cout << "\n" B_PURPLE "[script status]:" RESET "\n"; ::print_special(output); std::cout << B_PURPLE "-----------" RESET "\n\n"; //*DEBUG*/ std::cout << "\n" B_PURPLE "[script status]:" RESET "\n"; ::print_special(output); std::cout << B_PURPLE "-----------" RESET "\n\n";
_check_script_fields(client, output); client->status = _check_script_fields(output, client->status);
///*DEBUG*/ std::cout << "\n" B_PURPLE "[script fields]:" RESET "\n"; ::print_special(output); std::cout << B_PURPLE "-----------" RESET "\n\n"; _check_fields_duplicates(client, output);
//*DEBUG*/ std::cout << "\n" B_PURPLE "[script fields]:" RESET "\n"; ::print_special(output); std::cout << B_PURPLE "-----------" RESET "\n\n";
_remove_body_leading_empty_lines(output); _remove_body_leading_empty_lines(output);
///*DEBUG*/ std::cout << "\n" B_PURPLE "[script empty lines]:" RESET "\n"; ::print_special(output); std::cout << B_PURPLE "-----------" RESET "\n\n"; //*DEBUG*/ std::cout << "\n" B_PURPLE "[script empty lines]:" RESET "\n"; ::print_special(output); std::cout << B_PURPLE "-----------" RESET "\n\n";
_add_script_body_length_header(output); _add_script_body_length_header(output);
///*DEBUG*/ std::cout << "\n" B_PURPLE "[script content length]:" RESET "\n"; ::print_special(output); std::cout << B_PURPLE "-----------" RESET "\n\n"; //*DEBUG*/ std::cout << "\n" B_PURPLE "[script content length]:" RESET "\n"; ::print_special(output); std::cout << B_PURPLE "-----------" RESET "\n\n";
// _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) void Webserv::_check_script_status(Client *client, std::string & output)
@@ -269,7 +267,35 @@ void Webserv::_check_script_status(Client *client, std::string & output)
client->status = 200; client->status = 200;
} }
void Webserv::_check_script_fields(Client *client, std::string & output) size_t Webserv::_check_script_fields(const std::string & output, size_t status)
{
std::string headers;
std::string body;
size_t pos;
pos = output.find(CRLF CRLF);
if (pos == NPOS) // there is not empty line
return 500;
headers = output.substr(0, pos);
body = output.substr(pos + CRLF_SIZE * 2);
headers = str_tolower(headers);
pos = headers.find("content-type");
if (pos == NPOS) // there is no content-type field
{
if (!body.empty()) // there is body
return 500;
if (headers.find("location") == NPOS) // there is no location field
return 500;
}
else if (headers.find("location") != NPOS) // there is a location field
{
if (body.empty()) // there is no body
return 500;
}
return status;
}
void Webserv::_check_fields_duplicates(Client *client, std::string & output)
{ {
std::map<std::string, std::string> srv_fld; // server_field 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> scr_fld; // script_field

View File

@@ -64,7 +64,7 @@ int Webserv::_send_response(Client *client)
if (client->status >= 400) if (client->status >= 400)
_error_html_response(client); _error_html_response(client);
//*DEBUG*/ std::cout << "\n" B_PURPLE "[response + output + headers]:" RESET "\n"; ::print_special(client->response); std::cout << "\n" B_PURPLE "-----------" RESET "\n\n"; /*DEBUG*/ std::cout << "\n" B_PURPLE "[response + output + headers]:" RESET "\n"; ::print_special(client->response); std::cout << "\n" B_PURPLE "-----------" RESET "\n\n";
// /* Debug */ std::cerr << "client->response.size() = " << client->response.size() << "\n"; // DEBUG // /* Debug */ std::cerr << "client->response.size() = " << client->response.size() << "\n"; // DEBUG
ret = ::send(client->get_cl_fd(), client->response.c_str(), client->response.size(), 0); ret = ::send(client->get_cl_fd(), client->response.c_str(), client->response.size(), 0);
@@ -97,7 +97,6 @@ void Webserv::_append_base_headers(Client *client)
client->response.append("Connection: keep-alive" CRLF); client->response.append("Connection: keep-alive" CRLF);
} }
// TODO HUGO : wip
void Webserv::_construct_response(Client *client) void Webserv::_construct_response(Client *client)
{ {
std::string path; std::string path;

BIN
www/directory/root.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 KiB

1
www/file.md Normal file
View File

@@ -0,0 +1 @@
some md file to test upload

View File

@@ -18,7 +18,6 @@
form { form {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
border: 1px solid red;
margin: 20px; margin: 20px;
padding: 5px; padding: 5px;
} }
@@ -29,10 +28,31 @@
mark { mark {
margin: 0px 3px; margin: 0px 3px;
} }
#get form {
border: 1px solid red;
}
#post form {
border: 1px solid green;
}
</style> </style>
</head> </head>
<body> <body>
<!--
. cgi_cpp.cpp
cgi_cpp_bad_headers.cpp
cgi_cpp_empty.cpp
. cgi_cpp_empty_lines.cpp
. cgi_cpp_len.cpp
. cgi_cpp_len_big.cpp
. cgi_cpp_len_small.cpp
. cgi_cpp_no_body.cpp
cgi_cpp_no_headers.cpp
cgi_cpp_only_crlf.cpp
. cgi_cpp_sleep.cpp
. cgi_cpp_status.cpp
-->
<div id="get"> <div id="get">
<form method="get" action="/cgi-bin/cgi_cpp.out"> <form method="get" action="/cgi-bin/cgi_cpp.out">
<p><mark>get</mark> form</p> <p><mark>get</mark> form</p>
@@ -42,6 +62,8 @@
<label for="lname">Last name:</label><br> <label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br> <input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="submit" value="submit"> <input type="submit" value="submit">
<h3>expectation:</h3>
<p>normal output</p>
</form> </form>
<br> <br>
@@ -53,6 +75,8 @@
<label for="lname">Last name:</label><br> <label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br> <input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="submit" value="submit"> <input type="submit" value="submit">
<h3>expectation:</h3>
<p>normal output</p>
</form> </form>
<br> <br>
@@ -64,6 +88,8 @@
<label for="lname">Last name:</label><br> <label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br> <input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="submit" value="submit"> <input type="submit" value="submit">
<h3>expectation:</h3>
<p>normal output</p>
</form> </form>
<br> <br>
@@ -75,6 +101,8 @@
<label for="lname">Last name:</label><br> <label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br> <input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="submit" value="submit"> <input type="submit" value="submit">
<h3>expectation:</h3>
<p>normal output</p>
</form> </form>
<br> <br>
@@ -151,9 +179,132 @@
<option value="511">511</option> <option value="511">511</option>
</select> </select>
<input type="submit" value="submit"> <input type="submit" value="submit">
<h3>expectation:</h3>
<p>depend on status code</p>
</form>
<br>
<form method="get" action="/cgi-bin/cgi_cpp_empty_lines.out">
<p><mark>get</mark> form</p>
<p>to <mark>/cgi-bin/cgi_cpp_empty_lines.out</mark></p>
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname" value="John"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="submit" value="submit">
<h3>expectation:</h3>
<p>normal output</p>
</form>
<br>
<form method="get" action="/cgi-bin/cgi_cpp_sleep.out">
<p><mark>get</mark> form</p>
<p>to <mark>/cgi-bin/cgi_cpp_sleep.out</mark></p>
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname" value="John"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br>
<label for="sleep">Sleep time:</label><br>
<input type="text" id="sleep" name="sleep" value="5"><br><br>
<input type="submit" value="submit">
<h3>expectation:</h3>
<p>the request will sleep for chosen seconds</p>
<p>but other request chould not be blocked</p>
</form>
<br>
<form method="get" action="/cgi-bin/cgi_cpp_no_body.out">
<p><mark>get</mark> form</p>
<p>to <mark>/cgi-bin/cgi_cpp_no_body.out</mark></p>
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname" value="John"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="submit" value="submit">
<h3>expectation:</h3>
<p>blank page</p>
</form>
<br>
<form method="get" action="/cgi-bin/cgi_cpp_bad_headers.out">
<p><mark>get</mark> form</p>
<p>to <mark>/cgi-bin/cgi_cpp_bad_headers.out</mark></p>
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname" value="John"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="submit" value="submit">
<h3>expectation:</h3>
<p>error 500</p>
</form>
<br>
<form method="get" action="/cgi-bin/cgi_cpp_empty.out">
<p><mark>get</mark> form</p>
<p>to <mark>/cgi-bin/cgi_cpp_empty.out</mark></p>
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname" value="John"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="submit" value="submit">
<h3>expectation:</h3>
<p>error 500</p>
</form>
<br>
<form method="get" action="/cgi-bin/cgi_cpp_no_headers.out">
<p><mark>get</mark> form</p>
<p>to <mark>/cgi-bin/cgi_cpp_no_headers.out</mark></p>
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname" value="John"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="submit" value="submit">
<h3>expectation:</h3>
<p>error 500</p>
</form>
<br>
<form method="get" action="/cgi-bin/cgi_cpp_only_crlf.out">
<p><mark>get</mark> form</p>
<p>to <mark>/cgi-bin/cgi_cpp_only_crlf.out</mark></p>
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname" value="John"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="submit" value="submit">
<h3>expectation:</h3>
<p>error 500</p>
</form>
<br>
<form method="get" action="/cgi-bin/cgi_cpp_download.out">
<h1>WIP</h1>
<p><mark>get</mark> form</p>
<p>to <mark>/cgi-bin/cgi_cpp_download.out</mark></p>
<label for="fdownload">download file:</label><br>
<input type="file" id="fupload" name="fupload">
<select name="file">
<option value="Cagneyc_intro.gif" >Cagneyc_intro.gif </option>
<option value="file.md" >file.md </option>
<option value="index.html" >index.html </option>
<option value="kermit.ico" >kermit.ico </option>
<option value="punpun.png" selected>punpun.png </option>
<option value="subject.pdf" >subject.pdf </option>
<option value="Van_Eyck_Portrait_Arnolfini.jpg" >Van_Eyck_Portrait_Arnolfini.jpg</option>
<option value="directory" >directory </option>
<option value="DOESNT_EXIST.BAD" >DOESNT_EXIST.BAD </option>
</select>
<input type="submit" value="submit">
<h3>expectation:</h3>
<p>get a file in list</p>
<p>from ./www/user_files/</p>
</form> </form>
</div> </div>
<div id="post"> <div id="post">
<form method="post" action="/cgi-bin/cgi_cpp.out"> <form method="post" action="/cgi-bin/cgi_cpp.out">
<p><mark>post</mark> form</p> <p><mark>post</mark> form</p>
@@ -163,6 +314,8 @@
<label for="lname">Last name:</label><br> <label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br> <input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="submit" value="submit"> <input type="submit" value="submit">
<h3>expectation:</h3>
<p>normal output</p>
</form> </form>
<br> <br>
@@ -174,6 +327,8 @@
<label for="lname">Last name:</label><br> <label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br> <input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="submit" value="submit"> <input type="submit" value="submit">
<h3>expectation:</h3>
<p>normal output</p>
</form> </form>
<br> <br>
@@ -185,6 +340,8 @@
<label for="lname">Last name:</label><br> <label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br> <input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="submit" value="submit"> <input type="submit" value="submit">
<h3>expectation:</h3>
<p>normal output</p>
</form> </form>
<br> <br>
@@ -196,6 +353,8 @@
<label for="lname">Last name:</label><br> <label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br> <input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="submit" value="submit"> <input type="submit" value="submit">
<h3>expectation:</h3>
<p>normal output</p>
</form> </form>
<br> <br>
@@ -272,6 +431,114 @@
<option value="511">511</option> <option value="511">511</option>
</select> </select>
<input type="submit" value="submit"> <input type="submit" value="submit">
<h3>expectation:</h3>
<p>depend on status code</p>
</form>
<br>
<form method="post" action="/cgi-bin/cgi_cpp_empty_lines.out">
<p><mark>post</mark> form</p>
<p>to <mark>/cgi-bin/cgi_cpp_empty_lines.out</mark></p>
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname" value="John"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="submit" value="submit">
<h3>expectation:</h3>
<p>normal output</p>
</form>
<br>
<form method="post" action="/cgi-bin/cgi_cpp_sleep.out">
<p><mark>post</mark> form</p>
<p>to <mark>/cgi-bin/cgi_cpp_sleep.out</mark></p>
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname" value="John"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br>
<label for="sleep">Sleep time:</label><br>
<input type="text" id="sleep" name="sleep" value="5"><br><br>
<input type="submit" value="submit">
<h3>expectation:</h3>
<p>the request will sleep for chosen seconds</p>
<p>but other request chould not be blocked</p>
</form>
<br>
<form method="post" action="/cgi-bin/cgi_cpp_no_body.out">
<p><mark>post</mark> form</p>
<p>to <mark>/cgi-bin/cgi_cpp_no_body.out</mark></p>
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname" value="John"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="submit" value="submit">
<h3>expectation:</h3>
<p>blank page</p>
</form>
<br>
<form method="post" action="/cgi-bin/cgi_cpp_bad_headers.out">
<p><mark>post</mark> form</p>
<p>to <mark>/cgi-bin/cgi_cpp_bad_headers.out</mark></p>
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname" value="John"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="submit" value="submit">
<h3>expectation:</h3>
<p>error 500</p>
</form>
<br>
<form method="post" action="/cgi-bin/cgi_cpp_empty.out">
<p><mark>post</mark> form</p>
<p>to <mark>/cgi-bin/cgi_cpp_empty.out</mark></p>
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname" value="John"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="submit" value="submit">
<h3>expectation:</h3>
<p>error 500</p>
</form>
<br>
<form method="post" action="/cgi-bin/cgi_cpp_no_headers.out">
<p><mark>post</mark> form</p>
<p>to <mark>/cgi-bin/cgi_cpp_no_headers.out</mark></p>
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname" value="John"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="submit" value="submit">
<h3>expectation:</h3>
<p>error 500</p>
</form>
<br>
<form method="post" action="/cgi-bin/cgi_cpp_only_crlf.out">
<p><mark>post</mark> form</p>
<p>to <mark>/cgi-bin/cgi_cpp_only_crlf.out</mark></p>
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname" value="John"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="submit" value="submit">
<h3>expectation:</h3>
<p>error 500</p>
</form>
<br>
<form method="post" action="/cgi-bin/cgi_cpp_upload.out" enctype="multipart/form-data">
<h1>WIP</h1>
<p><mark>post</mark> form</p>
<p>to <mark>/cgi-bin/cgi_cpp_upload.out</mark></p>
<label for="fupload">Upload file:</label><br>
<input type="file" id="fupload" name="fupload">
<input type="submit" value="submit">
<h3>expectation:</h3>
<p>upload file in ./www/user_files/</p>
</form> </form>
</div> </div>

BIN
www/subject.pdf Normal file

Binary file not shown.

BIN
www/user_files/duck.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB