diff --git a/srcs/ConfigParser.cpp b/srcs/ConfigParser.cpp index 0a44dc4..15d3c0c 100644 --- a/srcs/ConfigParser.cpp +++ b/srcs/ConfigParser.cpp @@ -41,16 +41,16 @@ ConfigParser::ConfigParser(const char* path) std::ifstream file; std::string buf; -// std::string tmp; // maybe there's a reason we redeclare vars... - size_t comment; // just a number so fine to reset + size_t comment; _content.clear(); file.open(path); if (file.is_open()) { + // are there more throws i need to add in case of errors, what would + // those errors be? while (!file.eof()) { -// if we remove the Emtpy lines as well it simplifies things later... getline(file, buf); // remove # comments here. if ((comment = buf.find_first_of("#")) == std::string::npos) @@ -59,11 +59,9 @@ ConfigParser::ConfigParser(const char* path) if ((buf.find_first_not_of(" \t")) != std::string::npos) _content.append(buf + '\n'); } -// else if (comment > 0 && (buf.find_first_not_of(" \t")) != std::string::npos) - // i think this works cuz it will find # no matter what, so it will find - // something else first if there is non comment stuff. else if (comment > 0 && (buf.find_first_not_of(" \t")) < comment) { +// else if (comment > 0 && (buf.find_first_not_of(" \t")) != std::string::npos) // is there a comment at the end of the line std::string tmp = buf.substr(0, comment - 1); _content.append(tmp + '\n'); @@ -92,25 +90,22 @@ ConfigParser & ConfigParser::operator=(const ConfigParser& rhs) */ -// ok what exactly is the benefit of returning a pointer here... -//std::vector * ConfigParser::parse() -std::vector ConfigParser::parse() +std::vector ConfigParser::parse() { - // is this the best way to do this? new? -// std::vector *ret = new std::vector(); std::vector ret; - size_t prev = 0; - size_t curr = _content.find_first_not_of(" \t\n", prev); + size_t start = 0; + size_t curr = _content.find_first_not_of(" \t\n", 0); if (curr == std::string::npos) throw std::invalid_argument("empty config file"); while (curr != std::string::npos) { - // ok i don't love her way of scoping out the "server" strings... - prev = _content.find_first_not_of(" \t\n", curr); - curr = _content.find_first_of(" \t\n", prev); - std::string key = _conent.substr(prev, curr - prev); +// why no checks here +// if not here do i need them elsewhere? + start = _content.find_first_not_of(" \t\n", curr); + curr = _content.find_first_of(" \t\n", start); + std::string key = _conent.substr(start, curr - start); if (key != "server") throw std::invalid_argument("bad config file arguments"); // Server server = parse_server(&curr); @@ -125,20 +120,16 @@ std::vector ConfigParser::parse() ServerConfig ConfigParser::parse_server(size_t *start) { ServerConfig ret; -// size_t key_start; -// size_t value_end; - size_t prev = _content.find_first_not_of(" \t\n", *start); + size_t curr = _content.find_first_not_of(" \t\n", *start); - - if (prev == std::string::npos || _content[prev] != '{') + if (curr == std::string::npos || _content[curr] != '{') throw std::invalid_argument("bad config file syntax"); - size_t curr = _content.find_first_of(" \t\n", ++prev); + curr = _content.find_first_of(" \t\n", curr + 1); // if (curr == std::string::npos) // are there other things to check for? // throw std::invalid_argument("bad config file syntax"); while (curr != std::string::npos) // here curr == { + 1 { - // so this moves curr to past the word... std::string key = _get_first_word(&curr); // now curr is on space after 1st word. @@ -149,15 +140,14 @@ ServerConfig ConfigParser::parse_server(size_t *start) *start = _content.find_first_not_of(" \t\n" curr + 1); break ; case "location": - // this does assume we have locations in Server... we could change - // the name but it's so clear... - ret.location.push_back(parse_location(&curr)); + // this does assume we have locations in Server... + // could change the name but it's so clear... + ret.location.push_back(_parse_location(&curr)); default: std::string values = _get_rest_of_line(&curr); // curr now should be \n // checking for ; in _set_value, check key and value - - _set_server_values(&ret, key, values); // it handles the throws + _set_server_values(&ret, key, values); // handles the throws } } return (ret); @@ -165,17 +155,15 @@ ServerConfig ConfigParser::parse_server(size_t *start) -LocationConfig ConfigParser::parse_location(size_t *start) +LocationConfig ConfigParser::_parse_location(size_t *start) { LocationConfig ret; - size_t key_start; - size_t value_end; - size_t prev = _content.find_first_not_of(" \t\n", *start); + size_t curr = _content.find_first_not_of(" \t\n", *start); - if (prev == std::string::npos || _content[prev] != '{') + if (curr == std::string::npos || _content[curr] != '{') throw std::invalid_argument("bad config file syntax"); - size_t curr = _content.find_first_of(" \t\n", ++prev); + size_t curr = _content.find_first_of(" \t\n", curr + 1); // if (curr == std::string::npos) // are there other things to check for? // throw std::invalid_argument("bad config file syntax"); while (curr != std::string::npos) @@ -183,7 +171,6 @@ LocationConfig ConfigParser::parse_location(size_t *start) // so this moves curr to past the word... std::string key = _get_first_word(&curr); // now curr is on space after 1st word. - switch (key) { case "}": @@ -194,7 +181,7 @@ LocationConfig ConfigParser::parse_location(size_t *start) // curr now should be \n // checking for ; in _set_value, check key and value - _set_location_values(&ret, key, values); // it handles the throws + _set_location_values(&ret, key, values); //handles the throws } } return (ret); @@ -206,7 +193,8 @@ LocationConfig ConfigParser::parse_location(size_t *start) -void ConfigParser::_set_server_values(Server *server, const std::string key, const std::string value) +void ConfigParser::_set_server_values(ServerConfig *server, \ + const std::string key, std::string value) { // check key for ; @@ -231,84 +219,88 @@ void ConfigParser::_set_server_values(Server *server, const std::string key, con // we Trim value. // is this valid? + // would it be better to shove the result directly in tmp_val? + // like call substr in split? value = value.substr(0, i - 1); - std::vector tmp = ::split(value, ' '); + std::vector tmp_val = ::split(value, ' '); - if (tmp.size() == 1) + if (tmp_val.size() == 1) { switch (key) { case "server_name": - server->server_name = value; + server->server_name = tmp_val[0]; case "listen": - // ok yea i don't get this one anymore.. - if (value.find_first_of(":") == std::string::npos) + if (tmp_val[0].find_first_of(":") == std::string::npos) { // why not store as vector [4] ? server->host = "0.0.0.0"; - server->value = value; + server->value = tmp_val[0]; } else { // maybe do this differently? - std::vector tmp2 = split(value, ':'); + std::vector tmp2 = split(tmp_val[0], ':'); // i might take issue with this, will see if (server->host != "" && server->host != tmp2[0]) throw std::invalid_argument("bad listen"); - server->host = tmp[0]; - server->port = tmp[1]; + server->host = tmp2[0]; + server->port = tmp2[1]; } case "root": - server->root = value; + server->root = tmp_val[0]; case "autoindex": - server->autoindex = (value == "on" ? true : false); + server->autoindex = (tmp_val[0] == "on" ? true : false); case "client_body_limit": - server->client_body_limit = atoi(value.c_str()); + server->client_body_limit = atoi(tmp_val[0].c_str()); + case "recv_timeout": // what is tv_sec and do i need it? - server->recv_timeout.tv_sec = atoi(value.c_str()); + // ok so i don't fully understand this part but ok, keep for now... + server->recv_timeout.tv_sec = atoi(tmp_val[0].c_str()); case "send_timeout": - server->send_timeout.tv_sec = atoi(value.c_str()); + server->send_timeout.tv_sec = atoi(tmp_val[0].c_str()); + default : throw std::invalid_argument("should only have 1 value"); // yea ok but it could also be something else like too many // args } } - else if (tmp.size() > 1) + else if (tmp_val.size() > 1) { switch (key) { case "index": // could run more tests on value content but meh... - for (unsigned long i = 0; i != tmp.size(); i++) - server->index.push_back(tmp[i]); + for (unsigned long i = 0; i != tmp_val.size(); i++) + server->index.push_back(tmp_val[i]); case "allow_methods": // might do something different here // like change how methods are stored? - for (unsigned long i = 0; i != tmp.size(); i++) - server->allow_methods.push_back(str_to_method_type(tmp[i])); + for (unsigned long i = 0; i != tmp_val.size(); i++) + server->allow_methods.push_back(_str_to_method_type(tmp_val[i])); case "return": // could run more checks here too - // like tmp.size() must be 2 - // and tmp[0] should be a number and tmp[1] a string? - server->redirect_status = atoi(tmp[0].c_str()); - server->redirect_uri = tmp[1]; + // like tmp_val.size() must be 2 + // and tmp_val[0] should be a number and tmp_val[1] a string? + server->redirect_status = atoi(tmp_val[0].c_str()); + server->redirect_uri = tmp_val[1]; case "error_page": // something more complicated? // like make sure ints then 1 string? - std::string path = tmp[tmp.size() - 1]; - for (unsigned long i = 0; i != tmp.size() - 1; i++) + std::string path = tmp_val[tmp_val.size() - 1]; + for (unsigned long i = 0; i != tmp_val.size() - 1; i++) { - int status_code = atoi(tmp[i].c_str()); + int status_code = atoi(tmp_val[i].c_str()); // yea IDK i might not want to store this like that... if (server->error_pages.find(status_code) != server->error_pages.end()) continue ; server->error_pages[status_code] = path; } default : - throw std::invalid_argument("bad config file arguments"); + throw std::invalid_argument("wrong number of values"); } } else @@ -317,7 +309,8 @@ void ConfigParser::_set_server_values(Server *server, const std::string key, con } // again not sure i want an int ret -int ConfigParser::_set_location_values(Location *location, const std::string key, const std::string value) +int ConfigParser::_set_location_values(LocationConfig *location, \ + const std::string key, std::string value) { // check key for ; // check values for ; at end and right number of words depending on key @@ -341,41 +334,39 @@ int ConfigParser::_set_location_values(Location *location, const std::string key // we Trim value. // is this valid? + // could do like above? value = value.substr(0, i - 1); - std::vector tmp = ::split(value, ' '); + std::vector tmp_val = ::split(value, ' '); - if (tmp.size() == 1) + if (tmp_val.size() == 1) { switch (key) { case "root": - location->root = value; + location->root = tmp_val[0]; case "client_body_limit": - location->client_body_limit = atoi(value.c_str()); + location->client_body_limit = atoi(tmp_val[0].c_str()); default : throw std::invalid_argument("should only have 1 argument"); - } } - else if (tmp.size() > 1) + else if (tmp_val.size() > 1) { switch (key) { case "index": - std::vector tmp = split(value, ' '); - for (unsigned long i = 0; i != tmp.size(); i++) - location->index.push_back(tmp[i]); + for (unsigned long i = 0; i != tmp_val.size(); i++) + location->index.push_back(tmp_val[i]); case "allow_methods": - std::vector tmp = split(value, ' '); - for (unsigned long i = 0; i != tmp.size(); i++) - location->allow_methods.push_back(str_to_methodtype(tmp[i])); + for (unsigned long i = 0; i != tmp_val.size(); i++) + location->allow_methods.push_back(_str_to_methodtype(tmp_val[i])); case "cgi_info": - // ok wtf is all this even doing, figure that out +// ok wtf is all this even doing, figure that out unsigned long i = value.find_first_of(" "); if (i == std::string::npos) throw std::invalid_argument("bad config file arguments"); - // ok why an int now, we gotta be more consistent! + // ok why an int now, we gotta be more consistent! int j = value.find_first_not_of(" ", i); location->cgi_info[value.substr(0, i)] = value.substr(j, value.length()); default : @@ -421,6 +412,22 @@ std::string ConfigParser::_get_rest_of_line(size_t *curr) } +MethodType ConfigParser::_str_to_methodtype(std::string str) +{ + switch (str) + { + case ("GET"): + return GET; + case ("POST"): + return POST; + case ("DELETE"): + return DELETE; + default : + return INVALID; + } +} + + void ConfigParser::_print_content() const { diff --git a/srcs/ConfigParser.hpp b/srcs/ConfigParser.hpp index 378f987..8ef686a 100644 --- a/srcs/ConfigParser.hpp +++ b/srcs/ConfigParser.hpp @@ -14,6 +14,7 @@ # define CONFIGPARSER_HPP # include "Webserv.hpp" // easier to just do this? +// add includes properly // This is gonna be temporary cuz i don't konw if i like it @@ -44,7 +45,8 @@ public: // ConfigParser & operator=(const ConfigParser& rhs); // void parse(); // return void cuz throw exceptions. - std::vector * parse(); // const? + //std::vector * parse(); // const? + std::vector parse(); // const? // other parses? @@ -58,9 +60,20 @@ private: // should this be in private since it always needs a path? - void _check_proper_line_end(size_t prev, size_t curr); // const? + ServerConfig _parse_server(size_t *start); + LocationConfig _parse_location(size_t *start); - int _check_for_semicolon(std::string line); // const? + + void _set_server_values(ServerConfig *server, const std::string key, std::string value); + void _set_location_values(LocationConfig *location, const std::string key, std::string value); + + + std::string _get_first_word(size_t *curr); // const? + std::string _get_rest_of_line(size_t *curr); // const? + + + // why static? it's an enum... + static MethodType _str_to_method_type(std::string str); // just for testing purposes void _print_content() const; diff --git a/srcs/LocationConfig.hpp b/srcs/LocationConfig.hpp index 0f6b345..72ab187 100644 --- a/srcs/LocationConfig.hpp +++ b/srcs/LocationConfig.hpp @@ -14,6 +14,10 @@ # define LOCATIONCONFIG_HPP // includes + // add includes properly +# include +# include +# include # include "Webserv.hpp" // again, struct instead? @@ -31,10 +35,6 @@ public: std::map cgi_info; - - - - }; diff --git a/srcs/ServerConfig.hpp b/srcs/ServerConfig.hpp index 6935720..a6cdc6b 100644 --- a/srcs/ServerConfig.hpp +++ b/srcs/ServerConfig.hpp @@ -13,8 +13,9 @@ #ifndef SERVERCONFIG_HPP # define SERVERCONFIG_HPP +// add includes properly... +# include "Webserv.hpp" # include "LocationConfig.hpp" -//other includes // a class that's all public? just so we have options? class ServerConfig @@ -51,6 +52,38 @@ public: std::string host; std::string port; + + // do i need a print all for testing? + + + void print_all() + { + std::cout << "PRINTING A FULL SERVER CONFIG\n\n"; + + std::cout << "Server_name: " << server_name << '\n'; + std::cout << "root: " << root << '\n'; + std::cout << "index: "; + for (int i = 0; i < index.size(); i++) + std::cout << index[i] << " "; + std::cout << "\nerror_pages: "; + for (int i = 0; i < error_pages.size(); i++) + std::cout << error_pages.first << "--" << error_pages.second << " "; + std::cout << "\nallow_methods: "; + for (int i = 0; i < allow_methods.size(); i++) + std::cout << allow_methods[i] << " "; + std::cout << "\nskiping Locations for now...\n"; + std::cout << "also skiping send_timeout and recv\n"; + std::cout << "autoindex: " << autoindex << '\n'; + std::cout << "client_body_limit: " << client_body_limit << '\n'; + std::cout << "redirect_status: " << redirect_status << '\n'; + std::cout << "redirect_uri: " << redirect_uri << '\n'; + std::cout << "host: " << host << '\n'; + std::cout << "port: " << port << '\n'; + + std::cout << "\n----------\n"; + } + + }; diff --git a/srcs/main.cpp b/srcs/main.cpp index c9e1df7..7cf49d9 100644 --- a/srcs/main.cpp +++ b/srcs/main.cpp @@ -17,11 +17,19 @@ int main(int ac, char **av) // is there a better way? ConfigParser configParser(config.c_str()); - Webserv serv(configParser.parse()); + + configParser._print_content(); + + std::vector servers = configParser.parse(); + + for (int i = 0; i < server.size(); i++) + servers[i].print_all(); + +// Webserv serv(configParser.parse()); // is this better or worse than using - serv.init_virtual_servers(); - serv.start(); +// serv.init_virtual_servers(); +// serv.start(); } catch (std::exception& e) {