diff --git a/include/Config.hpp b/include/Config.hpp index a325ea2..295325b 100644 --- a/include/Config.hpp +++ b/include/Config.hpp @@ -49,7 +49,7 @@ class Config void parseServerName(const std::string & line); void parseRoot(const std::string & line); void parseIndex(const std::string & line); - void parsemaxPackageSize(const std::string & line); + void parseMaxPackageSize(const std::string & line); void parseErrorPage(const std::string & line); void parseClientTimeout(const std::string & line); @@ -77,7 +77,7 @@ class Config int getPort() const { return _port; } std::string getRootDir() const { return _root_dir; } FilePath getIndexFile() const { return *_index_file; } - unsigned int getmaxPackageSize() const { return _max_package_size; } + unsigned int getMaxPackageSize() const { return _client_max_body_size; } std::map getErrorPages() const { return _error_pages; } int getClientTimeout() const { return _client_timeout; } std::vector getLocations() const { return _locations; } diff --git a/src/Config.cpp b/src/Config.cpp index bd35b45..67552f4 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -12,8 +12,8 @@ Config::Config(std::string data) extractConfigFromBrackets(lines, static_cast(data)); // 2. parse each line, based on starting keyword - std::array keywords = {"listen", "server_name", "root", "index", "max_package_size", "error_page", "location", "client_timeout"}; - std::array parsers = {&Config::parseListen, &Config::parseServerName, &Config::parseRoot, &Config::parseIndex, &Config::parsemaxPackageSize, &Config::parseErrorPage, &Config::parseLocation, &Config::parseClientTimeout}; + std::array keywords = {"listen", "server_name", "root", "index", "client_max_body_size", "error_page", "location", "client_timeout"}; + std::array parsers = {&Config::parseListen, &Config::parseServerName, &Config::parseRoot, &Config::parseIndex, &Config::parseMaxPackageSize, &Config::parseErrorPage, &Config::parseLocation, &Config::parseClientTimeout}; for (std::string &line : lines) { std::string keyword = line.substr(0, line.find(' ')); @@ -138,7 +138,7 @@ void Config::parseIndex(const std::string & line) #endif } -void Config::parsemaxPackageSize(const std::string & line) +void Config::parseMaxPackageSize(const std::string & line) { std::regex size_regex(R"(max_package_size\s+(\d+)\s*([KMG]?B);)", std::regex::icase); std::smatch match; diff --git a/src/Packets/Methods/Delete.cpp b/src/Packets/Methods/Delete.cpp index 3134b4a..80d9643 100644 --- a/src/Packets/Methods/Delete.cpp +++ b/src/Packets/Methods/Delete.cpp @@ -1,8 +1,85 @@ #include "Response.hpp" +#include void Response::handleDelete(Request& req, Config &config) { - (void)config; - (void)req; - std::cout << "DELETE request received" << std::endl; -} \ No newline at end of file + std::string content = req.getBody(); + std::string path = req.getPath(); + + setVersion("HTTP/1.1"); + + t_location location = get_location(config, Path(path, Path::Type::URL, config).asFilePath()); + + if (!get_location(config, Path(path, Path::Type::URL, config).asUrl()).allowed_methods[static_cast(Method::DELETE)]) + { + std::cerr << "DELETE method not allowed" << std::endl; + setStatus(Status::Forbidden); + setBody("DELETE method not allowed"); + return; + } + + // FIXME: sometimes the path is corrent and sometimes not + path = "." + location.root_dir + path; + std::cout << "Path: " << path << std::endl; + + // delete file + if(path[path.length() - 1] != '/') + { + std::cout << "Trying to delete file: " << path << std::endl; + if (remove(path.c_str()) != 0) + { + std::cerr << "Error deleting file" << std::endl; + setStatus(Status::Forbidden); + setBody("Error deleting file"); + } + else + { + setStatus(Status::OK); + setBody("File deleted"); + } + return; + } + + // delete directory + DIR *dir; + struct dirent *ent; + + std::cout << "Trying to delete directory: " << path << std::endl; + + if ((dir = opendir(path.c_str())) != NULL) + { + while ((ent = readdir(dir)) != NULL) + { + std::string file = ent->d_name; + if (file != "." && file != "..") + { + std::string filepath = path + file; + if (remove(filepath.c_str()) != 0) + { + std::cerr << "Error deleting file" << std::endl; + setStatus(Status::Forbidden); + setBody("Error deleting file"); + return; + } + } + } + closedir(dir); + if (rmdir(path.c_str()) != 0) + { + std::cerr << "Error deleting directory" << std::endl; + setStatus(Status::Forbidden); + setBody("Error deleting directory"); + } + else + { + setStatus(Status::OK); + setBody("Directory deleted"); + } + } + else + { + std::cerr << "Error opening directory" << std::endl; + setStatus(Status::Forbidden); + setBody("Error opening directory"); + } +} diff --git a/src/Packets/Methods/Post.cpp b/src/Packets/Methods/Post.cpp index e4e5581..20ef9ac 100644 --- a/src/Packets/Methods/Post.cpp +++ b/src/Packets/Methods/Post.cpp @@ -6,14 +6,11 @@ void Response::handlePost(Request& req, Config &config) { - (void)config; - - // TODO: Check if on route POST is allowed - // reutrn 405 (FORBIDDEN) if not allowed + std::cout << "Handling POST request" << std::endl; std::string content = req.getBody(); std::string path = req.getPath(); - int content_length; + size_t content_length; setVersion("HTTP/1.1"); @@ -35,7 +32,7 @@ void Response::handlePost(Request& req, Config &config) return; } - content_length = std::stoi(req.getHeaders()["Content-Length"]); + content_length = std::stoul(req.getHeaders()["Content-Length"]); if (req.getHeaders().find("Content-Type") == req.getHeaders().end()) { @@ -49,8 +46,8 @@ void Response::handlePost(Request& req, Config &config) try { Path filepath = Path(req.getPath(), Path::Type::URL, config); - if (req.getHeaders().find("X-Filename") != req.getHeaders().end()) - filename = filepath.asFilePath() + req.getHeaders()["X-Filename"]; + if (req.getHeaders().find("Content-Filename") != req.getHeaders().end()) + filename = filepath.asFilePath() + req.getHeaders()["Content-Filename"]; else filename = filepath.asFilePath() + "default"; } @@ -81,6 +78,7 @@ void Response::handlePost(Request& req, Config &config) return ; } filename += "." + extension; + filename = "." + filename; std::cout << "Filename: " << filename << std::endl; @@ -100,7 +98,8 @@ void Response::handlePost(Request& req, Config &config) if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) throw std::runtime_error("Failed to set non-blocking mode"); - if (write(fd, content.c_str(), content_length) == -1) + (void)content_length; // TODO: use content_length instead of content.length() for it to be technically correct cuz we gotta use that what it says in the header + if (write(fd, content.c_str(), content.length()) == -1) { close(fd); std::cerr << "Error writing to file" << std::endl; diff --git a/src/Server.cpp b/src/Server.cpp index 2e072f1..f1d2dd0 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -28,7 +28,7 @@ void Server::updatePoll() fds.push_back(listen_pfd); // poll - int ret = poll(fds.data(), fds.size(), 100); + int ret = poll(fds.data(), fds.size(), 10); if (ret < 0) { Logger::Log(LogLevel::ERROR, "Poll error: " + std::string(strerror(errno)) + " -> means that there is no data to read."); @@ -52,20 +52,15 @@ void Server::updatePoll() bool Server::isDataComplete(t_socket_data &socket) { std::string data = socket.buffer.str(); - - // Step 1: Ensure buffer is not giant - if (data.size() > _config.getmaxPackageSize()) - throw std::runtime_error("Client data size exceeded maximum body size"); - size_t headerEnd = data.find("\r\n\r\n"); if (headerEnd == std::string::npos) return false; - // Step 2: Check for complete content (chunked transfer encoding) + // Chunked transfer encoding if (data.find("Transfer-Encoding: chunked") != std::string::npos) return data.find("0\r\n\r\n") != std::string::npos; - // Step 3: Check for complete content (normal packets) + // Normal packet if (data.find("Content-Length: ") != std::string::npos) { size_t headerEnd = data.find("\r\n\r\n"); @@ -79,11 +74,7 @@ bool Server::isDataComplete(t_socket_data &socket) } } - // Step 4: Check for stale packet - // ... - // TODO - - return true; // Step 5: No body & header is done + return true; } void Server::acceptNewConnections() @@ -123,6 +114,12 @@ void Server::handleExistingConnections() try { _sockets[i].buffer << _sockets[i].socket.receiveData(); + if (_sockets[i].buffer.str().size() > _config.getMaxPackageSize()) + { + Logger::Log(LogLevel::ERROR, "Client data size exceeded maximum body size"); + _sockets.erase(_sockets.begin() + i); + continue; + } _sockets[i].last_activity = std::chrono::steady_clock::now(); } catch(const std::runtime_error &e) diff --git a/src/Socket.cpp b/src/Socket.cpp index 4c58143..79f59d7 100644 --- a/src/Socket.cpp +++ b/src/Socket.cpp @@ -107,7 +107,7 @@ void Socket::sendData(Response &response) std::string Socket::receiveData() { std::string data; - int size = std::min(1024, static_cast(_config.getmaxPackageSize() + 1)); + int size = std::min(1048576, static_cast(_config.getMaxPackageSize() + 1)); char buffer[size]; ssize_t received;