diff --git a/includes/Header.hpp b/includes/Header.hpp index c2c4f85..0d093f5 100644 --- a/includes/Header.hpp +++ b/includes/Header.hpp @@ -7,32 +7,43 @@ class Header { private: int _row; + int _ret; + int _fd; char *_buff; std::string _method; std::string _version; std::string _URI; + std::string _query; + std::string _fileToSend; std::map _headerField; + std::map _errorCode; - public: - enum REQ - { - GET, - POST, - DELETE - }; - -public: - std::map getRequest(void); + std::map getRequest(void); std::string getMethod(void); std::string getURI(void); + std::string getReasonPhrase(std::string); + std::string getReasonPhrase(int); + std::string getErrorPage(int code); void setRawData(char *); + void setFd(int); + int getFd(void); + + void initErrorCode(void); + int checkURI(void); + int isFile(std::string); + int isDir(std::string); + void OpenResponsFile(const char *path); + int parseStartLine(std::string); int parseHeaderfield(std::string); void printHeaderInfo(void); int parseRequest(void); + + int sendRespons(int fd); + int sendHeader(int fd); void clear(void); Header(); Header(char *); diff --git a/includes/webserv.hpp b/includes/webserv.hpp index a6f886c..96ed773 100644 --- a/includes/webserv.hpp +++ b/includes/webserv.hpp @@ -27,7 +27,10 @@ #include #include #include +#include +#include #include +#include #include "Socket.hpp" #include "Server.hpp" #include "Header.hpp" diff --git a/src/Header.cpp b/src/Header.cpp index 94cc4b6..a933455 100644 --- a/src/Header.cpp +++ b/src/Header.cpp @@ -3,63 +3,36 @@ Header::Header() { this->_row = 0; + this->_fd = -1; + initErrorCode(); } -// std::string** Header::initErrorCode(void) -// { -// std::string HttpCode [41][2]= {{"100", "Continue"}, -// {"101", "Switching Protocols"}, -// {"200", "OK"}, -// {"201", "Created"}, -// {"202", "Accepted"}, -// {"203", "Non-Authoritative Information"}, -// {"204", "No Content"}, -// {"205", "Reset Content"}, -// {"206", "Partial Content"}, -// {"300", "Multiple Choices"}, -// {"301", "Moved Permanently"}, -// {"302", "Found"}, -// {"303", "See Other"}, -// {"304", "Not Modified"}, -// {"305", "Use Proxy"}, -// {"306", "(Unused)"}, -// {"307", "Temporary Redirect"}, -// {"400", "Bad Request"}, -// {"401", "Unauthorized"}, -// {"402", "Payment Required"}, -// {"403", "Forbidden"}, -// {"404", "Not Found"}, -// {"405", "Method Not Allowed"}, -// {"406", "Not Acceptable"}, -// {"407", "Proxy Authentication Required"}, -// {"408", "Request Timeout"}, -// {"409", "Conflict"}, -// {"410", "Gone"}, -// {"411", "Length Required"}, -// {"412", "Precondition Failed"}, -// {"413", "Request Entity Too Large"}, -// {"414", "Request-URI Too Long"}, -// {"415", "Unsupported Media Type"}, -// {"416", "Requested Range Not Satisfiable"}, -// {"417", "Expectation Failed"}, -// {"500", "Internal Server Error"}, -// {"501", "Not Implemented"}, -// {"502", "Bad Gateway"}, -// {"503", "Service Unavailable"}, -// {"504", "Gateway Timeout"}, -// {"505", "HTTP Version Not Supported"}}; -// return (HttpCode); -// } - Header::Header(char *str) { this->_row = 0; + this->_fd = -1; this->_buff = str; + initErrorCode(); parseRequest(); } + //-------------------------------------------------GET/SET--------------------------------------- + + +std::string Header::getErrorPage(int code) +{ + std::stringstream ss; + std::string Page; + + ss << "" << code <<" "<< getReasonPhrase(code) <<"" + <<"

" << code <<" " << getReasonPhrase(code) <<"

" + << "
poheck/1.0.0 (KDE)
"; + Page = ss.str(); + return (Page); +} + std::map Header::getRequest(void) { return (this->_headerField); @@ -75,11 +48,22 @@ std::string Header::getURI(void) return _URI; } +int Header::getFd(void) +{ + return _fd; +} + void Header::setRawData(char *str) { this->_buff = str; } -//-------------------------------------------------- + +void Header::setFd(int fd) +{ + this->_fd = fd; +} + +//-------------------------------------------------Parsing--------------------------------------- int Header::parseStartLine(std::string str) { @@ -91,14 +75,17 @@ int Header::parseStartLine(std::string str) str = str.erase(0 , str.find(" ") + 1); _version = str; _version.erase(_version.find_last_not_of(" \n\r\t") + 1); - if (_URI == "/") - _URI = "www/index2.html"; - else - _URI = HOME + _URI; if (_version != "HTTP/1.1") return (505); else if (_method != "GET" && _method != "POST" && _method != "DELETE") return (405); + else if (checkURI() < 0) + { + if (isDir(_URI) == 0) + return (403); + else + return (404); + } return 200; } @@ -127,28 +114,200 @@ int Header::parseHeaderfield(std::string str) int Header::parseRequest(void) { std::string line; - int ret; std::stringstream buffStream; buffStream << _buff; - ret = 200; - while (std::getline(buffStream, line, '\n') && ret == 200) + _ret = 200; + while (std::getline(buffStream, line, '\n') && _ret == 200) { if (_row == 0) - ret = parseStartLine(line); + _ret = parseStartLine(line); else - ret = parseHeaderfield(line); + _ret = parseHeaderfield(line); _row++; } - return (200); + return (_ret); } +//-------------------------------------------------FILE--------------------------------------- + +int Header::checkURI(void) +{ + const char *path; + std::string tmp; + int pos; + + tmp = _URI; + pos = _URI.find("?"); + if (pos > 0) + { + _URI = tmp.substr(0, pos); + _query = tmp.erase(0, pos + 1); + } + _URI = HOME + _URI; + path = _URI.c_str(); + if (isFile(_URI) < 0) + return (-1); + return (0); +} + +int Header::isFile(std::string path) +{ + struct stat s; + + if (stat(path.c_str(), &s) == 0) + { + if (s.st_mode & S_IFDIR) + return (-1); + else if (s.st_mode & S_IFREG) + return (0); + } + else + return (-1); + return (-1); +} + +int Header::isDir(std::string path) +{ + struct stat s; + + if (stat(path.c_str(), &s) == 0) + { + if (s.st_mode & S_IFDIR) + return (0); + else if (s.st_mode & S_IFREG) + return (-1); + } + else + return (-1); + return (-1); +} + +void Header::OpenResponsFile(const char *path) +{ + std::stringstream ss; + char buf[BUFFSIZE + 1] = {0}; + std::ifstream file(path); + + if (file.is_open()) + { + while (!file.eof()) + { + file.read(buf, BUFFSIZE); + ss << buf; + memset(buf, 0, BUFFSIZE + 1); + } + _fileToSend = ss.str(); + file.close(); + } + else + _fileToSend = getErrorPage(403); +} + +//-------------------------------------------------SEND--------------------------------------- + +int Header::sendHeader(int fd) +{ + std::stringstream ss; + std::string tmp; + const char *header; + + ss << _version << " " << _ret << " " << getReasonPhrase(_ret) << "\r\nContent-Type: text/html\r\n\r\n"; + tmp = ss.str(); + header = tmp.c_str(); + std::cout << TURGUOISE << "Send Header\n" << YELLOW << tmp << ZERO_C; + send(fd, header, tmp.length(), 0); + return (0); +} + +int Header::sendRespons(int fd) +{ + sendHeader(fd); + if (_ret == 200) + OpenResponsFile(_URI.c_str()); + else + _fileToSend = getErrorPage(_ret); + send(fd, _fileToSend.c_str(), _fileToSend.length(), 0); + + return (0); +} + +//-------------------------------------------------Error--------------------------------------- + +void Header::initErrorCode(void) +{ + _errorCode["100"] = "Continue"; + _errorCode["101"] = "Switching Protocols"; + _errorCode["200"] = "OK"; + _errorCode["201"] = "Created"; + _errorCode["202"] = "Accepted"; + _errorCode["203"] = "Non-Authoritative Information"; + _errorCode["204"] = "No Content"; + _errorCode["205"] = "Reset Content"; + _errorCode["206"] = "Partial Content"; + _errorCode["300"] = "Multiple Choices"; + _errorCode["301"] = "Moved Permanently"; + _errorCode["302"] = "Found"; + _errorCode["303"] = "See Other"; + _errorCode["304"] = "Not Modified"; + _errorCode["305"] = "Use Proxy"; + _errorCode["306"] = "(Unused)"; + _errorCode["307"] = "Temporary Redirect"; + _errorCode["400"] = "Bad Request"; + _errorCode["401"] = "Unauthorized"; + _errorCode["402"] = "Payment Required"; + _errorCode["403"] = "Forbidden"; + _errorCode["404"] = "Not Found"; + _errorCode["405"] = "Method Not Allowed"; + _errorCode["406"] = "Not Acceptable"; + _errorCode["407"] = "Proxy Authentication Required"; + _errorCode["408"] = "Request Timeout"; + _errorCode["409"] = "Conflict"; + _errorCode["410"] = "Gone"; + _errorCode["411"] = "Length Required"; + _errorCode["412"] = "Precondition Failed"; + _errorCode["413"] = "Request Entity Too Large"; + _errorCode["414"] = "Request-URI Too Long"; + _errorCode["415"] = "Unsupported Media Type"; + _errorCode["416"] = "Requested Range Not Satisfiable"; + _errorCode["417"] = "Expectation Failed"; + _errorCode["500"] = "Internal Server Error"; + _errorCode["501"] = "Not Implemented"; + _errorCode["502"] = "Bad Gateway"; + _errorCode["503"] = "Service Unavailable"; + _errorCode["504"] = "Gateway Timeout"; + _errorCode["505"] = "HTTP Version Not Supported"; +} + +std::string Header::getReasonPhrase(std::string code) +{ + std::map::iterator it; + + it = _errorCode.find(code); + return (it->second); +} + +std::string Header::getReasonPhrase(int code) +{ + std::stringstream ss; + std::string nbr; + std::map::iterator it; + + ss << code; + nbr = ss.str(); + it = _errorCode.find(nbr); + return (it->second); +} + +//-------------------------------------------------Other--------------------------------------- + void Header::printHeaderInfo(void) { std::map::iterator it; std::cout << PINK << "request method = " << _method << ZERO_C << std::endl; std::cout << PINK << "request URI = " << _URI << ZERO_C << std::endl; + std::cout << PINK << "request query = " << _query << ZERO_C << std::endl; std::cout << PINK << "request http versioin = " << _version << ZERO_C << std::endl; std::cout << PINK << "request rows = " << _row << ZERO_C << std::endl; std::cout << YELLOW << "request header:\n" << _buff << ZERO_C << std::endl; @@ -163,6 +322,7 @@ void Header::printHeaderInfo(void) void Header::clear(void) { + _fd = -1; _method = ""; _row = 0; _buff = NULL; diff --git a/src/Server.cpp b/src/Server.cpp index fbecc78..06bb1c6 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -14,37 +14,6 @@ Server::Server(std::string path) //----------------------------------------------Send-------------------------------------------------------------------------------------------- -void Server::sendHeader(Header head, int fd) -{ - std::string tmp; - const char *header; - tmp = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"; - header = tmp.c_str(); - std::cout << TURGUOISE << "Send Header\n" << YELLOW << tmp << ZERO_C; - send(fd, header, tmp.length(), 0); - (void)head; -} - -void Server::sendRespons(Header head, int fd) -{ - std::string str = head.getURI(); - const char *path = str.c_str(); - std::ifstream file(path); - char buff[BUFFSIZE + 1] = {0}; - - if (!file.good()) - { - file.open("www/index2.html"); - } - sendHeader(head, fd); - while (!file.eof()) - { - file.read(buff, BUFFSIZE); - send(fd, buff, file.gcount(), 0); - } - (void)path; -} - //----------------------------------------------Configuration----------------------------------------------------------------------------------- void Server::readConfig(void) { @@ -79,6 +48,7 @@ void Server::start(void) char buff[BUFFSIZE + 1] = {0}; Header header; int fd_accept; + int code; checkError(serverSocket.init(MAX_CLIENT), "Socket init"); fd_accept = accept(serverSocket.getSocketFd(), @@ -87,9 +57,10 @@ void Server::start(void) checkError(recv(fd_accept, buff, BUFFSIZE, 0), "Receive msg from client"); std::cout << TURGUOISE << "Receive Header" << ZERO_C << std::endl; header.setRawData(buff); - header.parseRequest(); + code = header.parseRequest(); header.printHeaderInfo(); - sendRespons(header, fd_accept); + header.sendRespons(fd_accept); + std::cout << BLUE << header.getReasonPhrase(code) << ZERO_C << std::endl; close(fd_accept); close(serverSocket.getSocketFd()); //-----------------------------------------------попытка добавить epoll------------------