diff --git a/includes/Client.hpp b/includes/Client.hpp
index f4d62e7..eff5ba4 100644
--- a/includes/Client.hpp
+++ b/includes/Client.hpp
@@ -8,27 +8,30 @@ class Client {
ip_port_t _ip_port;
Master *_parent;
- string _method;
- string _uri;
- string _host;
- string _len;
+ string _method;
+ string _uri;
+ string _host;
+ int _len;
+ int _last_len;
+
Server *_server;
Route *_route;
string _header;
- string _content;
+ string _body;
request_t _request;
public:
Client(int fd, ip_port_t ip_port, Master *parent);
~Client(void);
void clean(void);
- bool getRequest(Env *env, string paquet);
bool parseHeader(Env *env);
string header_pick(string key, size_t id);
void answer();
bool check_method();
+ void create_file(string path);
void send_cgi(string cgi, string path);
+ void send_cgi_redir(string cgi, string path);
void send_error(int error_code);
void send_answer(string msg);
diff --git a/srcs/load/Route.cpp b/srcs/load/Route.cpp
index 8012c44..b6f0598 100644
--- a/srcs/load/Route.cpp
+++ b/srcs/load/Route.cpp
@@ -64,11 +64,11 @@ string Route::getIndex(string uri, string path) {
struct dirent *entry;
struct stat info;
std::vector< string >::iterator it;
- cout << "get index(): path=" << path << "\n";
- if ((dir = opendir(path.c_str())) == NULL)
+ if ((dir = opendir(path.c_str())) == NULL) {
return "";
- else {
+ } else {
+ cout << "get index(): path=" << path << "\n";
content << "
" << path
<< " files :
\n\n";
while ((entry = readdir(dir)) != NULL) {
@@ -89,6 +89,7 @@ string Route::getIndex(string uri, string path) {
}
if (!_autoindex)
return "";
+ cout << "Getting autoindex\n";
ret << "Content-type: text/html \r\n";
ret << "Content-length: " << content.str().length() << "\r\n";
ret << "\r\n" << content.str();
diff --git a/srcs/load/Server.cpp b/srcs/load/Server.cpp
index 2ceea18..9c34a1a 100644
--- a/srcs/load/Server.cpp
+++ b/srcs/load/Server.cpp
@@ -96,6 +96,7 @@ Route *Server::choose_route(string uri) {
for (std::map< string, Route * >::iterator rit = _routes.begin();
rit != _routes.end(); rit++) {
root = split((*rit).first, "/");
+ cout << "Route: " << (*rit).first << "\n";
std::vector< string >::iterator root_it = root.begin();
for (std::vector< string >::iterator it = req.begin(); it < req.end();
it++) {
diff --git a/srcs/sock/Client.cpp b/srcs/sock/Client.cpp
index b230fca..693e44e 100644
--- a/srcs/sock/Client.cpp
+++ b/srcs/sock/Client.cpp
@@ -2,6 +2,7 @@
Client::Client(int fd, ip_port_t ip_port, Master *parent)
: _fd(fd), _ip_port(ip_port), _parent(parent) {
+ clean();
cout << "New connection, socket fd is " << fd << ", ip is : " << _ip_port.ip
<< ", port : " << _ip_port.port << "\n";
}
@@ -19,9 +20,11 @@ void Client::clean(void) {
_method = "";
_uri = "";
_host = "";
+ _len = 0;
+ _last_len = -1;
_header = "";
- _content = "";
+ _body = "";
_request.clear();
}
@@ -29,84 +32,71 @@ bool Client::getHeader(Env *env, string paquet) {
if (paquet.length() < 1)
send_error(403);
if (header_pick("Method:", 0) != "")
- return true;
+ return getBody(paquet);
std::vector< string > lines = split(paquet, "\r\n");
for (std::vector< string >::iterator it = lines.begin(); it < lines.end();
it++) {
- if (*it == "") {
+ size_t pos = paquet.find("\r\n");
+ if (pos != string::npos)
+ paquet.erase(0, pos + 2);
+ else
+ paquet.clear();
+ _header += *it + (it + 1 != lines.end() ? "\r\n" : "");
+ if (_header.find("\r\n\r\n") != string::npos) {
+ cout << "Header: \n-|" << _header << "|-\n";
if (!this->parseHeader(env))
return false;
- size_t pos = paquet.find("\r\n\r\n");
- if (pos != string::npos)
- paquet.erase(pos + 4);
- return true;
- } else
- _header += *it + "\r\n";
+ if (header_pick("Method:", 0) == "GET" ||
+ header_pick("Method:", 0) == "HEAD")
+ return true;
+ else if (paquet.length() > 0) {
+ // cout << "Remaining paquet: " << paquet.length() << "\n";
+ return getBody(paquet);
+ }
+ cout << "next: " << *it << "\n";
+ cout << "paquet length remain: " << paquet.length() << "\n";
+ }
}
- _header.resize(_header.length() - 2);
return false;
}
bool Client::getBody(string paquet) {
- std::vector< string > lines = split(paquet, "\r\n");
-
- long chunk_len = header_pick("Transfer-Encoding:", 0) == "chunked"
- ? std::strtol(lines.at(0).c_str(), 0, 16)
- : -1;
-
+ std::vector< string > lines = split(paquet, "\r\n");
std::vector< string >::iterator it;
+ cout << paquet << "\n";
+
for (it = lines.begin(); it < lines.end(); it++) {
- if (chunk_len == -1 || it != lines.begin())
- _content += *it + "\r\n";
+ cout << "line: " << *it << "\n";
+ if ((*it).length() && _len <= 0 &&
+ header_pick("Transfer-Encoding:", 0) == "chunked") {
+ _len = std::strtol((*it).c_str(), 0, 16) + 2;
+ _last_len = _len - 2;
+ // +2 for the final \r\n closing chunk
+ } else if (_len > 0 || it != lines.begin()) {
+ _body += *it + "\r\n";
+ _len -= ((*it).length() + 2);
+ }
+ cout << "Remaining chunk length: " << _len << "\n";
+ cout << "Previous chunk length: " << _last_len << "\n";
}
- _content.resize(_content.length() - 2);
- if ((header_pick("Method:", 0) == "GET" && *it == "") ||
- (chunk_len == 0 ||
- std::strtoul(header_pick("Content-Length:", 0).c_str(), 0, 10) <=
- _content.length())) {
- cout << "Request received\n";
+ if (_body.size())
+ _body.resize(_body.length() - 2);
+ _len += 2;
+ cout << "Remaining chunk characters: " << _len << "\n";
+ if (_last_len == 0 && _len == 0) {
+ cout << "Content:\n-|" << _body << "|-\n";
return true;
}
- return false;
-}
-
-bool Client::getRequest(Env *env, string paquet) {
- cout << "|===|paquet|===>\n" << paquet << "|===||\n";
- if (paquet.length() < 1) // HTTPS?
- return false;
- std::vector< string > lines = split(paquet, "\n");
- long chunk_len = (_content.length() > 0 &&
- header_pick("Transfer-Encoding:", 0) == "chunked")
- ? std::strtol(lines.at(0).c_str(), 0, 16)
- : -1;
- cout << "Chunk length: " << chunk_len << "\r\n";
- for (std::vector< string >::iterator it = lines.begin(); it < lines.end();
- it++) {
- if (*it == "\r" && header_pick("Method:", 0) == "") {
- if (!this->parseHeader(env))
- return false;
- } else if (*it != "\r" && header_pick("Method:", 0) == "")
- _header += *it + "\n";
- else if (*it != "\r" && (chunk_len == -1 || it != lines.begin()))
- _content += *it + "\n";
+ string content_length = header_pick("Content_Length:", 0);
+ if (content_length != "" &&
+ std::strtoul(content_length.c_str(), 0, 10) <= _body.length()) {
+ cout << "Content:\n-|" << _body << "|-\n";
+ return true;
}
- cout << "Content: \n-|" << _content << "|-\n";
- if (_content.length() > 0) {
- _content.resize(_content.length() - 1);
- if ((header_pick("Method:", 0) == "GET" && _content.find("\r\n\r\n")) ||
- (chunk_len == 0 ||
- std::strtoul(header_pick("Content-Length:", 0).c_str(), 0, 10) <=
- _content.length())) {
- cout << "Request received\n";
- return true;
- }
- } else if (header_pick("Method:", 0) == "")
- _header.resize(_header.length() - 1);
return false;
}
bool Client::parseHeader(Env *env) {
- cout << "Header: \n-|" << _header << "|-\n";
std::vector< string > lines = split(_header, "\r\n");
std::vector< string > method = split(lines.at(0), " ");
_request["Method:"] = method;
@@ -120,7 +110,8 @@ bool Client::parseHeader(Env *env) {
std::vector< string >(line.begin() + 1, line.end());
}
}
- if (method.at(0) == "POST" && header_pick("Content-Length:", 0) == "" &&
+ if ((method.at(0) == "POST" || method.at(0) == "PUT") &&
+ header_pick("Content-Length:", 0) == "" &&
header_pick("Transfer-Encoding:", 0) != "chunked") {
send_error(400);
return false;
@@ -131,22 +122,33 @@ bool Client::parseHeader(Env *env) {
_host = header_pick("Host:", 0);
_server = _parent->choose_server(env, _host);
_route = _server->choose_route(_uri);
- _len = header_pick("Content-Length:", 0).c_str();
- if (_len != "" && std::atoi(_len.c_str()) > _route->_client_max_body_size) {
- send_error(413);
- return false;
+ string len = header_pick("Content-Length:", 0).c_str();
+ if (len != "") {
+ _len = std::atoi(len.c_str());
+ _last_len = 0;
+ if (_len > _route->_client_max_body_size) {
+ send_error(413);
+ return false;
+ }
}
return true;
}
bool Client::check_method() {
std::vector< string > allowed;
- if (_method != "GET" && _method != "POST" && _method != "DELETE")
- send_error(405);
- else if ((allowed = _route->_allowed_methods).size() > 0 &&
- std::find(allowed.begin(), allowed.end(), _method) ==
- allowed.end()) {
+ if (_method != "GET" && _method != "POST" && _method != "DELETE" &&
+ _method != "PUT")
send_error(405);
+ else if ((allowed = _route->_allowed_methods).size() > 0) {
+ if (std::find(allowed.begin(), allowed.end(), _method) == allowed.end())
+ send_error(405);
+ else
+ return true;
+ } else if ((allowed = _server->_allowed_methods).size() > 0) {
+ if (std::find(allowed.begin(), allowed.end(), _method) == allowed.end())
+ send_error(405);
+ else
+ return true;
} else
return (true);
return (false);
@@ -165,18 +167,37 @@ void Client::answer() {
cout << "URI: " << _uri << "\n";
cout << "Host: " << _host << "\n";
string ret;
- if (check_method()) {
- string path = _route->correctUri(_uri);
- string cgi =
- _route->_cgi.size() ? _route->_cgi[get_extension(path)] : "";
- if (cgi == "") {
- if ((ret = _route->getIndex(_uri, path)) == "" &&
- (ret = read_file(path)) == "")
+ string path = _route->correctUri(_uri);
+ string cgi =
+ _route->_cgi.size()
+ ? _route->_cgi[get_extension(path)]
+ : (_server->_cgi.size() ? _server->_cgi[get_extension(path)] : "");
+ cout << "Path: " << path << "\n";
+ if (_method == "PUT")
+ create_file(path);
+ if (cgi == "") {
+ if (check_method()) {
+ if ((ret = _route->getIndex(_uri, path)) == "")
+ ret = read_file(path);
+ if (ret == "404")
send_error(404);
+ else if (ret == "403")
+ send_error(403);
else
send_answer("HTTP/1.1 200 OK\r\n" + ret);
- } else
- send_cgi(cgi, path);
+ }
+ } else
+ send_cgi(cgi, path);
+}
+
+void Client::create_file(string path) {
+ std::ofstream file(path.c_str());
+ if (!file.good())
+ send_error(403);
+ else {
+ file << _body;
+ file.close();
+ send_answer("HTTP/1.1 201 Accepted\r\nContent-Length: 0\r\n\r\n");
}
}
@@ -219,7 +240,8 @@ void Client::send_redir(int redir_code, string opt) {
switch (redir_code) {
case 301:
return send_answer(
- "HTTTP/1.1 301 Moved Permanently\r\nLocation: " + opt + "\r\n\r\n");
+ "HTTTP/1.1 301 Moved Permanently\r\nLocation: " + opt +
+"\r\n\r\n");
}
}
*/
@@ -228,6 +250,9 @@ void Client::send_error(int error_code) {
case 400:
return send_answer(
"HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\n\r\n");
+ case 403:
+ return send_answer(
+ "HTTP/1.1 403 Forbidden\r\nContent-Length: 0\r\n\r\n");
case 404:
return send_answer(
"HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n");
diff --git a/srcs/sock/Master.cpp b/srcs/sock/Master.cpp
index 6ede9d2..b87c5e0 100644
--- a/srcs/sock/Master.cpp
+++ b/srcs/sock/Master.cpp
@@ -54,8 +54,8 @@ Master::Master(ip_port_t list) : _listen(list) {
void Master::set_fds(void) {
FD_SET(_fd, &_readfds);
-
int child_fd;
+
for (std::vector< Client * >::iterator it = _childs.begin();
it < _childs.end(); it++) {
child_fd = (*it)->_fd;
@@ -74,7 +74,8 @@ void Master::set_fds(void) {
void Master::refresh(Env *env) {
int valread;
int addrlen = sizeof(_address);
- char buffer[10000];
+ char buffer[1000000];
+
if (FD_ISSET(_fd, &_readfds)) {
int new_socket =
accept(_fd, (struct sockaddr *)&_address, (socklen_t *)&addrlen);
@@ -93,16 +94,18 @@ void Master::refresh(Env *env) {
it < _childs.end(); it++) {
child_fd = (*it)->_fd;
if (FD_ISSET(child_fd, &_readfds)) {
- valread = read(child_fd, buffer, 10000);
+ valread = read(child_fd, buffer, 1000000);
buffer[valread] = '\0';
if (valread == 0) {
getpeername(child_fd, (struct sockaddr *)&_address,
(socklen_t *)&addrlen);
delete (*it);
_childs.erase(it);
- //} else if ((*it)->getRequest(env, buffer))
- } else if ((*it)->getHeader(env, buffer) && (*it)->getBody(buffer))
- (*it)->answer();
+ } else {
+ // cout << "Paquet:\n-|" << buffer << "|-\n";
+ if ((*it)->getHeader(env, buffer))
+ (*it)->answer();
+ }
}
}
}
@@ -131,11 +134,9 @@ Server *Master::choose_server(Env *env, string host) {
ip_required = split(_listen.ip, ".");
for (std::vector< Server * >::iterator sit = env->_servers.begin();
sit < env->_servers.end(); sit++) {
-
std::vector< ip_port_t > serv_listens = (*sit)->_listens;
for (std::vector< ip_port_t >::iterator it = serv_listens.begin();
it < serv_listens.end(); it++) {
-
if (_listen.port != (*it).port)
continue;
if (_listen.ip == (*it).ip) {
diff --git a/srcs/tools.cpp b/srcs/tools.cpp
index cdeaa0b..638b651 100644
--- a/srcs/tools.cpp
+++ b/srcs/tools.cpp
@@ -226,15 +226,16 @@ string read_file(string path) {
string str;
string content;
std::stringstream ret;
- // struct stat info;
- /*if (stat(path.c_str(), &info) != 0 || S_ISDIR(info.st_mode)) {
+ struct stat info;
+ if (stat(path.c_str(), &info) != 0) {
std::cerr << "stat() error on " << path << ": " << strerror(errno)
<< "\n";
- return "";
- }*/
+ return "404";
+ } else if (S_ISDIR(info.st_mode))
+ return "404";
std::ifstream file(path.c_str());
if (!file.good())
- return "";
+ return "404";
while (file) {
std::getline(file, str);
content += str + "\n";