diff --git a/.vscode/settings.json b/.vscode/settings.json index a232413..8a5b79f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -41,5 +41,11 @@ } } } + }, + "files.associations": { + "hash_map": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "string_view": "cpp" } } diff --git a/config/default.conf b/config/default.conf index 4863e6c..7fc3642 100644 --- a/config/default.conf +++ b/config/default.conf @@ -35,6 +35,47 @@ server { allow_methods GET; } + cgi_pass /cgi-bin/; + cgi_ext .py .php; +} + +server { + listen 80; + server_name mylocal; + + root /var/www/html2; + index index.html index2.htm; + + error_page 400 /400.html; + error_page 403 /403.html; + error_page 404 /404.html; + error_page 405 /405.html; + error_page 413 /413.html; + error_page 500 /500.html; + error_page 502 /502.html; + error_page 504 /504.html; + + client_max_body_size 1M; + + location / { + autoindex off; + index index.html; + allow_methods GET POST DELETE; + } + + location /2uploads { + root /var/www/uploads; + autoindex on; + allow_methods GET POST; + } + + location /2images { + root /var/www/images; + autoindex off; + index index.jpg; + allow_methods GET; + } + cgi_pass /cgi-bin/; cgi_ext .py .php; } \ No newline at end of file diff --git a/webserv/config/ConfigManager.cpp b/webserv/config/ConfigManager.cpp index c571bb8..16011b4 100644 --- a/webserv/config/ConfigManager.cpp +++ b/webserv/config/ConfigManager.cpp @@ -1,7 +1,11 @@ -#include #include +#include +#include - +#include +#include +#include +#include ConfigManager::ConfigManager() : _initialized(false) { @@ -25,6 +29,95 @@ void ConfigManager::init(const std::string &filePath) throw std::runtime_error("ConfigManager is already initialized."); } std::cout << "Initializing ConfigManager with file: " << filePath << '\n'; - // parseConfigFile(filePath); + parseConfigFile(filePath); _initialized = true; -} \ No newline at end of file +} + +void removeEmptyLines(std::string &str) +{ + std::istringstream stream(str); + std::string line; + std::string result; + + while (std::getline(stream, line)) + { + if (!trim(line).empty()) + { + result += line + '\n'; + } + } + str = result; +} + +void removeComments(std::string &str) +{ + size_t pos = 0; + while ((pos = str.find('#', pos)) != std::string::npos) + { + size_t end = str.find('\n', pos); + if (end == std::string::npos) + { + str.erase(pos); + } + else + { + str.erase(pos, end - pos); + } + } + removeEmptyLines(str); +} + +void ConfigManager::parseConfigFile(const std::string &filePath) +{ + // Placeholder for actual file parsing logic + std::cout << "Parsing configuration file: " << filePath << '\n'; + // Implement the parsing logic here + + std::ifstream file(filePath); + if (!file.is_open()) + { + throw std::runtime_error("Could not open config file: " + filePath); + } + + std::stringstream buffer; + buffer << file.rdbuf(); + std::string content = buffer.str(); + removeComments(content); + + std::string globalDeclarations; + + size_t pos = 0; + while (true) + { + size_t serverPos = content.find("server", pos); + size_t bracePos = content.find('{', serverPos); + if (serverPos == std::string::npos || bracePos == std::string::npos) + { + // No more server blocks, remaining is global + globalDeclarations += content.substr(pos); + break; + } + // Add global declarations before this server block + globalDeclarations += content.substr(pos, serverPos - pos); + size_t closeBrace = findCorrespondingClosingBrace(content, bracePos); + if (closeBrace == std::string::npos) + { + throw std::runtime_error("Malformed block in config file."); + } + // Optionally parse the server block here + std::string serverBlock = content.substr(bracePos + 1, closeBrace - bracePos - 1); + serverConfigs.emplace_back(serverBlock); + pos = closeBrace + 1; + } + + // parseGlobalDeclarations(globalDeclarations); // Implement this function to handle global config + std::cout << "Global Declarations:\n" << globalDeclarations << '\n'; + file.close(); +} + +void ConfigManager::parseGlobalDeclarations(const std::string &declarations) +{ + // Placeholder for actual global declarations parsing logic + std::cout << "Parsing global declarations:\n" << declarations << '\n'; + // Implement the parsing logic here +} diff --git a/webserv/config/ConfigManager.hpp b/webserv/config/ConfigManager.hpp index 5d88276..64a20ba 100644 --- a/webserv/config/ConfigManager.hpp +++ b/webserv/config/ConfigManager.hpp @@ -1,26 +1,9 @@ #pragma once -#include -#include #include #include -struct LocationConfig -{ - std::string path; - bool autoIndex; - std::string indexFile; - // Add other location-specific configurations as needed -}; - -struct ServerConfig -{ - std::string host; - int port; - std::string root; - // Add other server-specific configurations as needed - std::unique_ptr> locations; -}; +class ServerConfig; class ConfigManager { @@ -39,7 +22,7 @@ class ConfigManager ~ConfigManager(); std::vector serverConfigs; - // void parseConfigFile(const std::string &filePath); - // void parseServerBlock(const std::string &block); - // void parseLocationBlock(const std::string &block, ServerConfig &serverConfig); + void parseConfigFile(const std::string &filePath); + void parseGlobalDeclarations(const std::string &declarations); + }; \ No newline at end of file diff --git a/webserv/config/LocationConfig.cpp b/webserv/config/LocationConfig.cpp index e69de29..336dc57 100644 --- a/webserv/config/LocationConfig.cpp +++ b/webserv/config/LocationConfig.cpp @@ -0,0 +1,57 @@ +#include +#include + + +#include +#include +#include + +LocationConfig::LocationConfig(const std::string &locationBlock) + : path(""), autoIndex(false), indexFile("") +{ + parseLocationBlock(locationBlock); +} + +void LocationConfig::parseLocationBlock(const std::string &block) +{ + // Placeholder for actual location block parsing logic + std::cout << "Parsing location block:\n" << block << '\n'; + // Implement the parsing logic here + parseDirectives(block); + +} +void LocationConfig::parseDirectives(const std::string &declarations) +{ + // Placeholder for actual directives parsing logic + std::cout << "Parsing location directives:\n" << declarations << '\n'; + // Implement the parsing logic here + std::istringstream stream(declarations); + std::string line; + while (std::getline(stream, line)) + { + std::string directive; + std::istringstream ss{trim(line)}; + ss >> directive; + if (!directive.empty()) + { + std::cout << "Directive: " << directive << '\n'; + // Implement the parsing logic here + std::string value; + ss >> value; + if (directive == "autoindex") + { + autoIndex = (value == "on"); + std::cout << "Set autoindex to " << (autoIndex ? "on" : "off") << '\n'; + } + else if (directive == "index") + { + indexFile = value; + std::cout << "Set index file to " << indexFile << '\n'; + } + else + { + directives[directive] = value; + } + } + } +} diff --git a/webserv/config/LocationConfig.hpp b/webserv/config/LocationConfig.hpp index e69de29..e0c1004 100644 --- a/webserv/config/LocationConfig.hpp +++ b/webserv/config/LocationConfig.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + + +class LocationConfig +{ + public: + LocationConfig(const std::string &locationBlock); + + private: + std::string path; + bool autoIndex; + std::string indexFile; + std::map directives; + + void parseLocationBlock(const std::string &block); + void parseDirectives(const std::string &declarations); +}; diff --git a/webserv/config/ServerConfig.cpp b/webserv/config/ServerConfig.cpp index e69de29..31f6fe5 100644 --- a/webserv/config/ServerConfig.cpp +++ b/webserv/config/ServerConfig.cpp @@ -0,0 +1,123 @@ +#include +#include +#include + +#include +#include +#include + +ServerConfig::ServerConfig(std::string const &serverBlock) + : host(""), port(80), root("") +{ + parseServerBlock(serverBlock); +} + + + +void ServerConfig::parseServerBlock(const std::string &block) +{ + // Placeholder for actual server block parsing logic + std::cout << "Parsing server block:\n"; + + // Placeholder for actual file parsing logic + + std::string serverDeclarations; + + size_t pos = 0; + while (true) + { + size_t locationPos = block.find("location", pos); + + size_t bracePos = block.find('{', locationPos); + if (locationPos == std::string::npos || bracePos == std::string::npos) + { + // No more server blocks, remaining is global + serverDeclarations += block.substr(pos); + break; + } + std::string locationPath = trim(block.substr(locationPos, bracePos - (locationPos ))); + // Add global declarations before this server block + serverDeclarations += block.substr(pos, locationPos - pos); + size_t closeBrace = findCorrespondingClosingBrace(block, bracePos); + if (closeBrace == std::string::npos) + { + throw std::runtime_error("Malformed block in config file."); + } + // Optionally parse the server block here + std::string serverBlock = block.substr(bracePos + 1, closeBrace - bracePos - 1); + locations.emplace(locationPath, LocationConfig(serverBlock)); + pos = closeBrace + 1; + } + + // parseGlobalDeclarations(Declarations); // Implement this function to handle global config + parseDirectives(serverDeclarations); +} + +void ServerConfig::parseDirectives(const std::string &declarations) +{ + // Placeholder for actual directives parsing logic + std::cout << "Parsing directives:\n" << declarations << '\n'; + std::string line; + std::istringstream stream(declarations); + while (std::getline(stream, line)) + { + std::string directive; + std::istringstream ss{trim(line)}; + ss >> directive; + if (!directive.empty()) + { + std::cout << "Directive: " << directive << '\n'; + // Implement the parsing logic here + std::string value; + ss >> value; + if (directive == "listen") + { + + port = std::stoi(value); + if (port < 1 || port > 65535) + { + throw std::runtime_error("Invalid port number: " + std::to_string(port)); + } + std::cout << "Set port to " << port << '\n'; + } + else if (directive == "root") + { + root = value; + std::cout << "Set root to " << root << '\n'; + } + else if (directive == "server_name") + { + host = value; + std::cout << "Set server_name to " << host << '\n'; + } + else if (directive == "cgi_pass") + { + cgi_pass = value; + std::cout << "Set cgi_pass to " << cgi_pass << '\n'; + } + else if(directive =="cgi_ext") + { + cgi_ext = value; + std::cout << "Set cgi_ext to " << cgi_ext << '\n'; + } + else if(directive == "index") + { + index_files.clear(); + std::string indexFile; + while (ss >> indexFile) + { + index_files.push_back(indexFile); + std::cout << "Added index file: " << indexFile << '\n'; + } + } + else if (directive == "error_page") + { + int statusCode = std::stoi(value); + std::string errorPagePath; + ss >> errorPagePath; + error_page[statusCode] = errorPagePath; + std::cout << "Set error_page for status " << statusCode << " to " << errorPagePath << '\n'; + } + } + } +} \ No newline at end of file diff --git a/webserv/config/ServerConfig.hpp b/webserv/config/ServerConfig.hpp index e69de29..64b3864 100644 --- a/webserv/config/ServerConfig.hpp +++ b/webserv/config/ServerConfig.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include +#include +#include + +#include + +class ServerConfig +{ + public: + ServerConfig(const std::string &serverBlock); + + [[nodiscard]] LocationConfig getLocation(const std::string &path) const; + + private: + std::string host; + int port; + std::string root; + std::string cgi_pass; + std::string cgi_ext; + std::map error_page; + std::vector index_files; + std::map locations; + + void parseServerBlock(const std::string &block); + void parseDirectives(const std::string &declarations); +}; diff --git a/webserv/config/utils.cpp b/webserv/config/utils.cpp new file mode 100644 index 0000000..f27b32d --- /dev/null +++ b/webserv/config/utils.cpp @@ -0,0 +1,42 @@ +#include + +#include + + +std::string trim(const std::string &str) +{ + size_t first = str.find_first_not_of(" \t\n\r"); + size_t last = str.find_last_not_of(" \t\n\r"); + if (first == std::string::npos || last == std::string::npos) + { + return ""; + } + return str.substr(first, last - first + 1); +} + +size_t findCorrespondingClosingBrace(const std::string &str, size_t openPos) +{ + int braceCount = 1; + if (str[openPos] != '{') + { + return std::string::npos; // Not an opening brace at the given position + } + + for (size_t i = openPos + 1; i < str.size(); ++i) + { + if (str[i] == '{') + { + ++braceCount; + } + else if (str[i] == '}') + { + --braceCount; + } + + if (braceCount == 0) + { + return i; + } + } + return std::string::npos; // No matching closing brace found +} \ No newline at end of file diff --git a/webserv/config/utils.hpp b/webserv/config/utils.hpp new file mode 100644 index 0000000..0b24b58 --- /dev/null +++ b/webserv/config/utils.hpp @@ -0,0 +1,6 @@ +#pragma once + +#include + +std::string trim(const std::string &str); +size_t findCorrespondingClosingBrace(const std::string &str, size_t openPos); diff --git a/webserv/main.cpp b/webserv/main.cpp index b419188..c6fe2b6 100644 --- a/webserv/main.cpp +++ b/webserv/main.cpp @@ -1,9 +1,7 @@ -#include #include #include #include -#include int main(int argc, char **argv) {