From 3eda24edb1c45c7a84b76e584c25d560bd2d9e76 Mon Sep 17 00:00:00 2001 From: Talyx Date: Sun, 30 Jan 2022 11:48:44 +0300 Subject: [PATCH 01/11] bug fix --- src/Client/Client.cpp | 6 +++--- src/Client/Request.cpp | 3 +++ src/Client/Response.cpp | 11 ++++++----- src/Client/Response.hpp | 4 ++-- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/Client/Client.cpp b/src/Client/Client.cpp index d871ab1..3bf095a 100644 --- a/src/Client/Client.cpp +++ b/src/Client/Client.cpp @@ -99,7 +99,7 @@ int Client::sendResponse(int fd) { _response.setData(_request, _config); _response.generate(); - _headerToSend = _response.getClient(); + _headerToSend = _response.getHeader(); _bodyToSend = _response.getBody(); _ret = sendData(fd, _headerToSend + _bodyToSend); @@ -110,7 +110,7 @@ std::string Client::generateRespons(void) { _response.setData(_request, _config); _response.generate(); - _headerToSend = _response.getClient(); + _headerToSend = _response.getHeader(); _bodyToSend = _response.getBody(); _toSend = _headerToSend + _bodyToSend; @@ -138,7 +138,7 @@ void Client::printClientInfo(void) std::cout << PINK << "host = " << _request.getHost() << ZERO_C << std::endl; std::cout << PINK << "request query = " << _request.getQuery() << ZERO_C << std::endl; std::cout << PINK << "request http versioin = " << _request.getVersion() << ZERO_C << std::endl; - // std::cout << YELLOW << "request Client:\n" << _buff << ZERO_C << std::endl; + std::cout << YELLOW << "request Client:\n" << _buff << ZERO_C << std::endl; std::cout << TURGUOISE << "Client MAP" << ZERO_C << std::endl; for ( it = map.begin(); it != map.end() ; it++) diff --git a/src/Client/Request.cpp b/src/Client/Request.cpp index b4a60fd..e16445b 100644 --- a/src/Client/Request.cpp +++ b/src/Client/Request.cpp @@ -8,6 +8,9 @@ Request::Request() _ret = 200; _contentLength = 0; _chunked = false; + _head_ok = false; + _body_ok = false; + } Request::Request(char *str) diff --git a/src/Client/Response.cpp b/src/Client/Response.cpp index 6fe6661..2620833 100644 --- a/src/Client/Response.cpp +++ b/src/Client/Response.cpp @@ -9,9 +9,9 @@ Response::Response() //-------------------------------------------------GET/SET--------------------------------------- -std::string Response::getClient(void) +std::string Response::getHeader(void) { - return (_Client); + return (_header); } std::string Response::getBody(void) { @@ -65,13 +65,14 @@ void Response::invalidClient(void) { std::stringstream ss; std::string tmp; - //Client + //Header ss << _request.getVersion() << " " << _request.getCode() << " " << getReasonPhrase(_request.getCode()) << "\r\nContent-Type: text/html\r\n\r\n"; - _Client = ss.str(); + _header = ss.str(); //body _body = getErrorPage(_request.getCode()); std::cout << RED << "Invalid Client method called\nCODE: " << _request.getCode() << " " << getReasonPhrase(_request.getCode()) << ZERO_C << std::endl; + std::cout << _header << std::endl << _body << std::endl; } void Response::methodGet(void) @@ -80,7 +81,7 @@ void Response::methodGet(void) std::string tmp; //Client ss << _request.getVersion() << " " << _request.getCode() << " " << getReasonPhrase(_request.getCode()) << "\r\nContent-Type: text/html\r\n\r\n"; - _Client = ss.str(); + _header = ss.str(); //body if (!_request.badCode(_request.getCode()) && _request.isDir(_request.getFullUri()) == 0) _body = Autoindex::getPage(_request.getURI(), _request.getFullUri(), _request.getHost()); diff --git a/src/Client/Response.hpp b/src/Client/Response.hpp index 5c2b7b5..3b60915 100644 --- a/src/Client/Response.hpp +++ b/src/Client/Response.hpp @@ -9,7 +9,7 @@ class Response { private: std::string _body; - std::string _Client; + std::string _header; Request _request; ServerConfig *_config; @@ -23,7 +23,7 @@ private: void invalidClient(void); public: - std::string getClient(void); + std::string getHeader(void); std::string getBody(void); static std::string getReasonPhrase(std::string); static std::string getReasonPhrase(int); From d3425e88a35fe50e090dd85f6030294e1584e3e6 Mon Sep 17 00:00:00 2001 From: Talyx Date: Tue, 1 Feb 2022 15:58:30 +0300 Subject: [PATCH 02/11] fix: endless loading for non txt files --- src/Client/Client.cpp | 39 +++++++++++++++++---------------------- src/Client/Client.hpp | 1 - src/Client/Request.cpp | 35 +++++++++++++++++++++++++++++------ src/Client/Request.hpp | 5 +++++ src/Server/Server.cpp | 10 +++++----- 5 files changed, 56 insertions(+), 34 deletions(-) diff --git a/src/Client/Client.cpp b/src/Client/Client.cpp index 010342c..57833c3 100644 --- a/src/Client/Client.cpp +++ b/src/Client/Client.cpp @@ -5,7 +5,6 @@ Client::Client() { allRead = false; - _received = 0; this->_fd = -1; this->_sended = 0; } @@ -13,7 +12,6 @@ Client::Client() Client::Client(char *str) { allRead = false; - _received = 0; this->_fd = -1; this->_buff = str; this->_sended = 0; @@ -23,7 +21,6 @@ Client::Client(char *str) Client::Client(char *str, ServerConfig *config) { allRead = false; - _received = 0; this->_fd = -1; this->_config = config; this->_buff = str; @@ -60,7 +57,7 @@ unsigned int Client::getCounter(void) const unsigned int Client::getRecvCounter(void) const { - return _received; + return _request.getRecved(); } void Client::setRawData(char *str) @@ -107,14 +104,8 @@ bool Client::allSended(void) bool Client::allRecved(void) { - if (_request.getContentLength() == _received) - { - std::cout << "contentLength, _received " - << _request.getContentLength() - << " " << - _received << std::endl; + if (_request.getContentLength() == (_request.getRecved() - _request.getHeaderSize())) return (true); - } else return (false); } @@ -126,9 +117,7 @@ void Client::increaseCounter(void) void Client::increaseRecvCounter(unsigned int n) { - if (_received == 0) - _received -= _request.getHeaderSize(); - _received += n; + _request.increaseRecvCounter(n); } //Генерирует response. Далее респонс можно получить через функцию getStrToSend() @@ -170,20 +159,26 @@ void Client::printClientInfo(void) std::map::iterator it1; map = _request.getClientFields(); + std::cout << TURQ << "Parsed request" << ZERO_C << std::endl; std::cout << PINK << "request method = " << _request.getMethod() << ZERO_C << std::endl; std::cout << PINK << "request URI = " << _request.getURI() << ZERO_C << std::endl; std::cout << PINK << "host = " << _request.getHost() << ZERO_C << std::endl; std::cout << PINK << "request query = " << _request.getQuery() << ZERO_C << std::endl; std::cout << PINK << "request http versioin = " << _request.getVersion() << ZERO_C << std::endl; - std::cout << YELLOW << "request Client:\n" << _buff << ZERO_C << std::endl; + std::cout << PINK << "content-length = " << _request.getContentLength() << ZERO_C << std::endl; + std::cout << PINK << "connection type = " << _request.getConnection() << ZERO_C << std::endl; + + std::cout << TURQ << "Parsed response" << ZERO_C << std::endl; + std::cout << BLUE << _response.getHeader() << ZERO_C << std::endl; - std::cout << TURGUOISE << "Client MAP" << ZERO_C << std::endl; - for ( it = map.begin(); it != map.end() ; it++) - { - std::cout << PINK << it->first << BLUE << it->second << ZERO_C << std::endl; - } - std::cout << TURGUOISE << "Client BODY" << ZERO_C << std::endl; - std::cout << GREEN << _request.getBody().size() << ZERO_C << std::endl; + // std::cout << YELLOW << "request Client:\n" << _buff << ZERO_C << std::endl; + // std::cout << TURGUOISE << "Client MAP" << ZERO_C << std::endl; + // for ( it = map.begin(); it != map.end() ; it++) + // { + // std::cout << PINK << it->first << BLUE << it->second << ZERO_C << std::endl; + // } + // std::cout << TURGUOISE << "Client BODY" << ZERO_C << std::endl; + // std::cout << GREEN << _request.getBody().size() << ZERO_C << std::endl; /* std::cout << BLUE << _request.getBody() << ZERO_C << std::endl; */ } diff --git a/src/Client/Client.hpp b/src/Client/Client.hpp index fcc290f..d5cddd1 100644 --- a/src/Client/Client.hpp +++ b/src/Client/Client.hpp @@ -18,7 +18,6 @@ private: int _ret; int _fd; unsigned int _sended; - unsigned int _received; char *_buff; diff --git a/src/Client/Request.cpp b/src/Client/Request.cpp index 7664df1..b8bbe13 100644 --- a/src/Client/Request.cpp +++ b/src/Client/Request.cpp @@ -10,6 +10,8 @@ Request::Request() _chunked = false; _head_ok = false; _body_ok = false; + _received = 0; + } Request::Request(char *str) @@ -19,6 +21,7 @@ Request::Request(char *str) _data = str; _head_ok = false; _body_ok = false; + _received = 0; _chunked = false; _contentLength = 0; } @@ -57,6 +60,10 @@ std::string Request::getLocation(void) { return (_location); } +std::string Request::getConnection(void) +{ + return (_connection); +} ServerConfig *Request::getConfig(void) { return (_config); @@ -82,7 +89,10 @@ unsigned int Request::getHeaderSize(void) const { return (_headerSize); } - +unsigned int Request::getRecved(void) const +{ + return (_received); +} void Request::setData(char *str) { this->_data = str; @@ -99,7 +109,10 @@ void Request::setConfig(ServerConfig *config) //-------------------------------------------------Parsing--------------------------------------- - +void Request::increaseRecvCounter(unsigned int n) +{ + _received += n; +} void Request::parseURI(std::string str) { std::string tmp; @@ -142,9 +155,10 @@ int Request::parseStartLine(std::string str) void Request::splitData(char *data) { int pos; + std::stringstream ss; std::string str; - str = data; + str = std::string(data); if (!_head_ok) { pos = str.find("\r\n\r\n"); @@ -165,9 +179,11 @@ void Request::splitData(char *data) return ; else if (!_body_ok) { - _body += str.substr(0, str.size()); - if (_body.size() >= _contentLength) + _body += str.substr(0, _received - _headerSize); + if ((_received - _headerSize) == _contentLength) + { _body_ok = true; + } } } @@ -231,8 +247,11 @@ void Request::copyFromMap() { std::map::iterator it; int pos; + //host - _host = _headerField.find("host")->second; + it = _headerField.find("host"); + if (it != _headerField.end()) + _host = it->second; //content-lenght it = _headerField.find("content-length"); @@ -246,6 +265,10 @@ void Request::copyFromMap() if ( pos != -1) _chunked = true; } + //connection + it = _headerField.find("connection"); + if (it != _headerField.end()) + _connection = it->second; } diff --git a/src/Client/Request.hpp b/src/Client/Request.hpp index 56528d4..b0441d5 100644 --- a/src/Client/Request.hpp +++ b/src/Client/Request.hpp @@ -13,6 +13,7 @@ private: int _ret; int _row; unsigned int _contentLength; + unsigned int _received; unsigned int _headerSize; std::string _URI; @@ -24,6 +25,7 @@ private: std::string _fullURI; std::string _version; std::string _location; + std::string _connection; std::map _headerField; ServerConfig *_config; @@ -39,10 +41,12 @@ public: std::string getFullUri(void); std::string getVersion(void); std::string getLocation(void); + std::string getConnection(void); ServerConfig *getConfig(void); int getCode(void); unsigned int getContentLength(void) const; unsigned int getHeaderSize(void) const; + unsigned int getRecved(void)const; std::map getClientFields(void); bool getChunked(void); @@ -71,6 +75,7 @@ public: void clear(void); void splitData(char *); + void increaseRecvCounter(unsigned int n); ~Request(); }; diff --git a/src/Server/Server.cpp b/src/Server/Server.cpp index 7f69826..9b8d0cc 100644 --- a/src/Server/Server.cpp +++ b/src/Server/Server.cpp @@ -82,19 +82,18 @@ void Server::readSocket(int fd, std::map &client_map) return; } client_map[fd].setRawData(buf); - status = client_map[fd].parseRequest(); client_map[fd].increaseRecvCounter(bytes_read); - client_map[fd].printClientInfo(); + status = client_map[fd].parseRequest(); + // client_map[fd].printClientInfo(); if ((bytes_read < BUFFSIZE) && client_map[fd].allRecved()) { client_map[fd].allRead = true; } - std::cerr << "bytes_read " << bytes_read << std::endl;; - std::cerr << "recvCounter " << client_map[fd].getRecvCounter() << std::endl;; + std::cerr << "recvCounter " << client_map[fd].getRecvCounter() << std::endl; std::cerr << "contentLength " << client_map[fd].getRequest().getContentLength() << std::endl; - std::cerr << "allRead " << client_map[fd].allRead << std::endl;; + std::cerr << "allRead " << client_map[fd].allRead << std::endl; std::cout << BLUE << "status is " << Response::getReasonPhrase(status) << RESET << std::endl; bzero(buf, BUFFSIZE); @@ -171,6 +170,7 @@ void Server::start(void) if (client.readyToSend() && client.allSended()) { + client_map[fd].printClientInfo(); close(client_it->first); std::cerr << RED << "deleting client " From 4e673e46fbe7ac8dbac9e257fe7477dc607c8b14 Mon Sep 17 00:00:00 2001 From: Talyx Date: Tue, 1 Feb 2022 16:41:41 +0300 Subject: [PATCH 03/11] add: content-length, server --- src/Client/Response.cpp | 54 +++++++++++++++++++++++++++-------------- src/Client/Response.hpp | 4 ++- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/src/Client/Response.cpp b/src/Client/Response.cpp index 2620833..f729122 100644 --- a/src/Client/Response.cpp +++ b/src/Client/Response.cpp @@ -5,6 +5,7 @@ Response::Response() { initErrorCode(); + _code = 200; } //-------------------------------------------------GET/SET--------------------------------------- @@ -21,6 +22,7 @@ std::string Response::getBody(void) void Response::setData(Request request, ServerConfig *config) { _request = request; + _code = request.getCode(); _config = config; } @@ -65,32 +67,48 @@ void Response::invalidClient(void) { std::stringstream ss; std::string tmp; - //Header - ss << _request.getVersion() << " " << _request.getCode() << " " << getReasonPhrase(_request.getCode()) << "\r\nContent-Type: text/html\r\n\r\n"; - _header = ss.str(); //body - _body = getErrorPage(_request.getCode()); - std::cout << RED << "Invalid Client method called\nCODE: " << _request.getCode() << " " << getReasonPhrase(_request.getCode()) << ZERO_C << std::endl; - std::cout << _header << std::endl << _body << std::endl; + // _body = getErrorPage(_code); + // std::cout << RED << "Invalid Client method called\nCODE: " << _code << " " << getReasonPhrase(_code) << ZERO_C << std::endl; + generateBody(); + //Header + generateHeader(); +} + +void Response::generateBody(void) +{ + if (!_request.badCode(_code) && _request.isDir(_request.getFullUri()) == 0) + _body = Autoindex::getPage(_request.getURI(), _request.getFullUri(), _request.getHost()); + else if (!_request.badCode(_code) && _request.isFile(_request.getFullUri()) == 0) + OpenResponseFile(_request.getFullUri().c_str()); + else + _body = getErrorPage(_code); + +} + +void Response::generateHeader(void) +{ + std::stringstream ss; + std::string tmp; + + ss << "HTTP/1.1" << " " << _request.getCode() << " " << getReasonPhrase(_request.getCode()) + << "\r\nContent-Type: text/html" + << "\r\nContent-Length: " << _body.size() + << "\r\nServer: poheck" + << "\r\n\r\n"; + _header = ss.str(); } void Response::methodGet(void) { - std::stringstream ss; - std::string tmp; - //Client - ss << _request.getVersion() << " " << _request.getCode() << " " << getReasonPhrase(_request.getCode()) << "\r\nContent-Type: text/html\r\n\r\n"; - _header = ss.str(); - //body - if (!_request.badCode(_request.getCode()) && _request.isDir(_request.getFullUri()) == 0) - _body = Autoindex::getPage(_request.getURI(), _request.getFullUri(), _request.getHost()); - else if (!_request.badCode(_request.getCode())) - OpenResponseFile(_request.getFullUri().c_str()); - else - _body = getErrorPage(_request.getCode()); + + generateBody(); + generateHeader(); std::cout << GREEN << "GET method called\n" << ZERO_C; + + } //-------------------------------------------------GET/SET--------------------------------------- diff --git a/src/Client/Response.hpp b/src/Client/Response.hpp index 3b60915..43dfbb3 100644 --- a/src/Client/Response.hpp +++ b/src/Client/Response.hpp @@ -12,6 +12,7 @@ private: std::string _header; Request _request; ServerConfig *_config; + int _code; private: static std::map _errorCode; @@ -21,7 +22,8 @@ private: // void methodPost(void); // void methodDelete(void); void invalidClient(void); - + void generateHeader(void); + void generateBody(void); public: std::string getHeader(void); std::string getBody(void); From d63e1227784f8ffe01f14f319d5f3df9fa9f8746 Mon Sep 17 00:00:00 2001 From: Talyx Date: Tue, 1 Feb 2022 16:42:38 +0300 Subject: [PATCH 04/11] minor changes --- src/Client/Client.cpp | 20 ++++++++++---------- src/Client/Request.cpp | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Client/Client.cpp b/src/Client/Client.cpp index 57833c3..693e19b 100644 --- a/src/Client/Client.cpp +++ b/src/Client/Client.cpp @@ -159,17 +159,17 @@ void Client::printClientInfo(void) std::map::iterator it1; map = _request.getClientFields(); - std::cout << TURQ << "Parsed request" << ZERO_C << std::endl; - std::cout << PINK << "request method = " << _request.getMethod() << ZERO_C << std::endl; - std::cout << PINK << "request URI = " << _request.getURI() << ZERO_C << std::endl; - std::cout << PINK << "host = " << _request.getHost() << ZERO_C << std::endl; - std::cout << PINK << "request query = " << _request.getQuery() << ZERO_C << std::endl; - std::cout << PINK << "request http versioin = " << _request.getVersion() << ZERO_C << std::endl; - std::cout << PINK << "content-length = " << _request.getContentLength() << ZERO_C << std::endl; - std::cout << PINK << "connection type = " << _request.getConnection() << ZERO_C << std::endl; + std::cout << BLUE << std::endl << "PARSED REQUEST" << ZERO_C << std::endl << std::endl; + std::cout << GREEN << "request method = " << _request.getMethod() << ZERO_C << std::endl; + std::cout << GREEN << "request URI = " << _request.getURI() << ZERO_C << std::endl; + std::cout << GREEN << "host = " << _request.getHost() << ZERO_C << std::endl; + std::cout << GREEN << "request query = " << _request.getQuery() << ZERO_C << std::endl; + std::cout << GREEN << "request http versioin = " << _request.getVersion() << ZERO_C << std::endl; + std::cout << GREEN << "content-length = " << _request.getContentLength() << ZERO_C << std::endl; + std::cout << GREEN << "connection type = " << _request.getConnection() << ZERO_C << std::endl; - std::cout << TURQ << "Parsed response" << ZERO_C << std::endl; - std::cout << BLUE << _response.getHeader() << ZERO_C << std::endl; + std::cout << BLUE << std::endl << "RESPONSE" << ZERO_C << std::endl << std::endl; + std::cout << GREEN << _response.getHeader() << ZERO_C << std::endl; // std::cout << YELLOW << "request Client:\n" << _buff << ZERO_C << std::endl; // std::cout << TURGUOISE << "Client MAP" << ZERO_C << std::endl; diff --git a/src/Client/Request.cpp b/src/Client/Request.cpp index b8bbe13..e61e19e 100644 --- a/src/Client/Request.cpp +++ b/src/Client/Request.cpp @@ -179,7 +179,7 @@ void Request::splitData(char *data) return ; else if (!_body_ok) { - _body += str.substr(0, _received - _headerSize); + _body += str; if ((_received - _headerSize) == _contentLength) { _body_ok = true; From f8343098e857f2e92e433eceac04a96897b88605 Mon Sep 17 00:00:00 2001 From: Talyx Date: Tue, 1 Feb 2022 17:39:45 +0300 Subject: [PATCH 05/11] fix: delete client, if he empty --- src/Client/Client.cpp | 14 +++++++++++++- src/Client/Client.hpp | 4 ++-- src/Client/Request.cpp | 2 ++ src/Server/Server.cpp | 4 ++-- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/Client/Client.cpp b/src/Client/Client.cpp index 693e19b..ba0603a 100644 --- a/src/Client/Client.cpp +++ b/src/Client/Client.cpp @@ -149,7 +149,10 @@ std::string Client::generateRespons(void) bool Client::readyToSend(void) { - return(_request.ok()); + if (_request.ok()) + return(_request.ok()); + else + return false; } void Client::printClientInfo(void) @@ -183,6 +186,15 @@ void Client::printClientInfo(void) } +bool Client::isEmpty(void) +{ + if (!_request.ok() && _request.getHeaderSize() == 0 + && _request.getContentLength() == 0) + return (true); + else + return (false); +} + void Client::clear(void) { _fd = -1; diff --git a/src/Client/Client.hpp b/src/Client/Client.hpp index d5cddd1..65a0857 100644 --- a/src/Client/Client.hpp +++ b/src/Client/Client.hpp @@ -37,8 +37,8 @@ public: void setRawData(char *); void setFd(int); int getFd(void); - unsigned int getRecvCounter(void) const; - + unsigned int getRecvCounter(void) const; + bool isEmpty(void); public: int parseRequest(void); diff --git a/src/Client/Request.cpp b/src/Client/Request.cpp index e61e19e..e1201bb 100644 --- a/src/Client/Request.cpp +++ b/src/Client/Request.cpp @@ -11,6 +11,7 @@ Request::Request() _head_ok = false; _body_ok = false; _received = 0; + _headerSize = 0; } @@ -24,6 +25,7 @@ Request::Request(char *str) _received = 0; _chunked = false; _contentLength = 0; + _headerSize = 0; } //-------------------------------------------------Get/Set--------------------------------------- diff --git a/src/Server/Server.cpp b/src/Server/Server.cpp index 9b8d0cc..2937470 100644 --- a/src/Server/Server.cpp +++ b/src/Server/Server.cpp @@ -154,7 +154,7 @@ void Server::start(void) std::cout << TURQ << "IN SEND LOOP" << RESET << std::endl; Client &client = client_it->second; - if (!client.allRead) + if (!client.allRead && !client.isEmpty()) { readSocket(client_it->first, client_map); } @@ -168,7 +168,7 @@ void Server::start(void) } - if (client.readyToSend() && client.allSended()) + if ((client.readyToSend() && client.allSended()) || client.isEmpty()) { client_map[fd].printClientInfo(); close(client_it->first); From 0efe9d1bc324a38a60af6ccf97f689bb9a17a541 Mon Sep 17 00:00:00 2001 From: Talyx Date: Tue, 1 Feb 2022 18:34:50 +0300 Subject: [PATCH 06/11] add: struct timeval in Client class, and lifeTime in Request --- includes/webserv.hpp | 1 + src/Client/Client.cpp | 16 ++++++++++++++++ src/Client/Client.hpp | 4 +++- src/Client/Request.cpp | 6 ++++++ src/Client/Request.hpp | 2 ++ 5 files changed, 28 insertions(+), 1 deletion(-) diff --git a/includes/webserv.hpp b/includes/webserv.hpp index 8fbdda7..8639449 100644 --- a/includes/webserv.hpp +++ b/includes/webserv.hpp @@ -27,6 +27,7 @@ #include #include #include +#include #include diff --git a/src/Client/Client.cpp b/src/Client/Client.cpp index ba0603a..cda7671 100644 --- a/src/Client/Client.cpp +++ b/src/Client/Client.cpp @@ -195,6 +195,22 @@ bool Client::isEmpty(void) return (false); } +bool Client::TimeToDie(void) +{ + struct timeval curTime; + + gettimeofday(&curTime, NULL); + if ((curTime.tv_sec - _time.tv_sec) >= _request.getLifeTime()) + return (true); + else + return (false); +} + +void Client::updateTimeToDie(void) +{ + gettimeofday(&_time, NULL); +} + void Client::clear(void) { _fd = -1; diff --git a/src/Client/Client.hpp b/src/Client/Client.hpp index 65a0857..dcd92c5 100644 --- a/src/Client/Client.hpp +++ b/src/Client/Client.hpp @@ -17,6 +17,7 @@ private: private: int _ret; int _fd; + struct timeval _time; unsigned int _sended; char *_buff; @@ -39,7 +40,8 @@ public: int getFd(void); unsigned int getRecvCounter(void) const; bool isEmpty(void); - + bool TimeToDie(void); + void updateTimeToDie(void); public: int parseRequest(void); diff --git a/src/Client/Request.cpp b/src/Client/Request.cpp index e1201bb..8e78362 100644 --- a/src/Client/Request.cpp +++ b/src/Client/Request.cpp @@ -12,6 +12,7 @@ Request::Request() _body_ok = false; _received = 0; _headerSize = 0; + _lifeTime = 5; } @@ -26,6 +27,7 @@ Request::Request(char *str) _chunked = false; _contentLength = 0; _headerSize = 0; + _lifeTime = 5; } //-------------------------------------------------Get/Set--------------------------------------- @@ -74,6 +76,10 @@ int Request::getCode(void) { return (_ret); } +int Request::getLifeTime(void) +{ + return (_lifeTime); +} std::map Request::getClientFields(void) { return (_headerField); diff --git a/src/Client/Request.hpp b/src/Client/Request.hpp index b0441d5..c68f1e2 100644 --- a/src/Client/Request.hpp +++ b/src/Client/Request.hpp @@ -12,6 +12,7 @@ private: int _ret; int _row; + int _lifeTime; unsigned int _contentLength; unsigned int _received; unsigned int _headerSize; @@ -44,6 +45,7 @@ public: std::string getConnection(void); ServerConfig *getConfig(void); int getCode(void); + int getLifeTime(void); unsigned int getContentLength(void) const; unsigned int getHeaderSize(void) const; unsigned int getRecved(void)const; From 5afc1e7e83864e5dbdee40d9e68a639266a21d35 Mon Sep 17 00:00:00 2001 From: Talyx Date: Tue, 1 Feb 2022 19:13:48 +0300 Subject: [PATCH 07/11] support for new data types --- src/Client/Response.cpp | 64 +++++++++++++++++++++++++++++++--------- src/Client/Response.hpp | 6 ++-- www/images/images.jpeg | Bin 0 -> 10981 bytes www/images/images1.jpeg | Bin 0 -> 9786 bytes www/images/images2.jpeg | Bin 0 -> 6180 bytes www/images/images3.jpeg | Bin 0 -> 9863 bytes www/images/images4.jpeg | Bin 0 -> 6378 bytes www/images/images5.jpeg | Bin 0 -> 6985 bytes www/images/index.jpeg | Bin 0 -> 5595 bytes 9 files changed, 54 insertions(+), 16 deletions(-) create mode 100644 www/images/images.jpeg create mode 100644 www/images/images1.jpeg create mode 100644 www/images/images2.jpeg create mode 100644 www/images/images3.jpeg create mode 100644 www/images/images4.jpeg create mode 100644 www/images/images5.jpeg create mode 100644 www/images/index.jpeg diff --git a/src/Client/Response.cpp b/src/Client/Response.cpp index f729122..690f90c 100644 --- a/src/Client/Response.cpp +++ b/src/Client/Response.cpp @@ -31,17 +31,11 @@ void Response::setData(Request request, ServerConfig *config) void Response::OpenResponseFile(const char *path) { std::stringstream ss; - char buf[BUFFSIZE + 1] = {0}; - std::ifstream file(path); + std::ifstream file(path, std::ifstream::in); if (file.is_open()) { - while (!file.eof()) - { - file.read(buf, BUFFSIZE); - ss << buf; - memset(buf, 0, BUFFSIZE + 1); - } + ss << file.rdbuf(); _body = ss.str(); file.close(); } @@ -61,7 +55,44 @@ void Response::generate() // methodDelete(); } -//-------------------------------------------------GET/SET--------------------------------------- +//-------------------------------------------------HEADER/BODY--------------------------------------- + +std::string Response::getTime(void) +{ + char buff[1337] = {0}; + struct timeval currTime; + struct tm *t; + + gettimeofday(&currTime, NULL); + t = gmtime(&currTime.tv_sec); + strftime(buff, 1337, "%a, %d %b %Y %H:%M:%S GTM", t); + + return (buff); +} + +std::string Response::getContentType(void) +{ + std::string path = _request.getFullUri(); + std::string type = path.substr(path.rfind(".") + 1, path.size() - path.rfind(".")); + + if (_request.isDir(path) == 0) + return ("text/html"); + else if (type == "html") + return ("text/html"); + else if (type == "css") + return ("text/css"); + else if (type == "js") + return ("text/javascript"); + else if (type == "jpeg" || type == "jpg") + return ("image/jpeg"); + else if (type == "png") + return ("image/png"); + else if (type == "bmp") + return ( "image/bmp"); + else + return ("text/plain"); + +} void Response::invalidClient(void) { @@ -82,6 +113,8 @@ void Response::generateBody(void) _body = Autoindex::getPage(_request.getURI(), _request.getFullUri(), _request.getHost()); else if (!_request.badCode(_code) && _request.isFile(_request.getFullUri()) == 0) OpenResponseFile(_request.getFullUri().c_str()); + else if (_request.isFile(_request.getFullUri()) == -1) + _body = getErrorPage(404); else _body = getErrorPage(_code); @@ -92,11 +125,14 @@ void Response::generateHeader(void) std::stringstream ss; std::string tmp; - ss << "HTTP/1.1" << " " << _request.getCode() << " " << getReasonPhrase(_request.getCode()) - << "\r\nContent-Type: text/html" - << "\r\nContent-Length: " << _body.size() - << "\r\nServer: poheck" - << "\r\n\r\n"; + ss << "HTTP/1.1" << " " << _request.getCode() << " " << getReasonPhrase(_request.getCode()) << "\r\n"; + ss << "Content-Type: " << getContentType() << "\r\n"; + ss << "Content-Length: " << _body.size() << "\r\n"; + ss << "Server: poheck\r\n"; + if (_request.getConnection() == "keep-alive") + ss << "Keep-Alive: timeout=" << _request.getLifeTime() << "\r\n"; + ss << "Date: " << getTime() << "\r\n"; + ss << "\r\n"; _header = ss.str(); } diff --git a/src/Client/Response.hpp b/src/Client/Response.hpp index 43dfbb3..b9fce3e 100644 --- a/src/Client/Response.hpp +++ b/src/Client/Response.hpp @@ -22,8 +22,10 @@ private: // void methodPost(void); // void methodDelete(void); void invalidClient(void); - void generateHeader(void); - void generateBody(void); + void generateHeader(void); + void generateBody(void); + std::string getTime(void); + std::string getContentType(void); public: std::string getHeader(void); std::string getBody(void); diff --git a/www/images/images.jpeg b/www/images/images.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..c2ef91c759306d65f61e0e129a20b0b78745dece GIT binary patch literal 10981 zcmaiZWmMG9_y2q8?nXMLq(izxLOK?Z?pi6xd05Rpctl#rjF z2j6r4&;EBF%$&LB#+);A?(22uapiFfAkk9OR0BXD008|Pz~dSa4d7y7larHCl9Q2B zQBhLS&`{D)(@;}WQq#~-QBwbte;W+k%rtZy43v~CLM$9lc?ARnsF_40MffGS`2~1E zczAe3ghX^CBy{}DOicX$6W;$V{(tl1AV7)()PnfXL9758DF~eu^f(MW0RS{K^#4-* zpI~63V*wyEY@B~uSrPyZgpQ7eiH3oJj*a=>fzU_+bQTOUAxuRqa#np?VJ`}$h%`0> zyE5#dpOjQ0k*#y*?8@Hd+v)$zX+gk0*Z+_2|LoB*F#oC8NdLt}L;o-M{{sJWO~!&Q zq)2XyK_RT9|A+zz&_Vw)MJEO1f#&sjhF>cdX)wU%%d&v9*LX9(xeIgRa$eH)6t}$E zc244A7rkq4Zkca@tp*!wTzkVh(LQB?E<*jed*doA#$4=gE?3qp_a|ekD!v0xT{ou1 zJ3VNEEzCxA_?B6o3gx@MR@uC2uVx>TZ2YwnO(#p9&YoM1Uy~h&km~BN<9^X~0Vve@ zc>5E!5S2LyeuFXI3Tmt|&)sO_pt4JGalFZN{dJAdyuU2ZIX$lY8J7-3B);?5GmuAj}OaLapF zA$t7@?Wt^YNvbKu=`d*8`$BZ{oj+mi!QlBc=5H4l(NBAgSP0cdQ1nd|HOI<+)Fku0 zQI(A;)r+jSvYVD6%6f+v3O5mkRuy!658GDSu&=iXpTa~)Rjub9Niif0LTerQ0_ z$Y2hl-yaO=YhZ4~V-UcKk8ar$=QqUra{wFt+rr^otb$0+h{;5Iv1|w*!-8s4qJ5`h zAF!MIyRNepba0-55M5YjdRbNkdTnbE-U5h`o3;{|ny_+~b^qwZ1$pzhn})=?%cw9p zB(=Hd=oV{7DX;gwp`@xYFtW>LruBt<>r}{5+^e8V`n+ft>ny@hpXov-Vw6 z8yhy0Cs4{PyBG1X`dJzbMbLR|-22X;`)@IDqKs;pazHl;4iQNoRP_c7lwb#c(&yE( zIl3whaAc4LgMVr6p=A&U3q9jy8kS%nWIW=o7)h1zsdw7^tKHX%q~jr@ycE3)+M#6L zC7Ea2()m`;%?T*u!TGT-!Cpfs0)Ki1^0UPJc_GLeX6xUC&%M&DlWQFfyCS_LBKN8+ zrNv%Ya@d^$%dB<1sfs)rNzxF))4Un!U0=VHA`>cBV_QGBqDV!cAkRPMPoX!cR(KSxMSS`+DxDkpd9&Z@SLuS4CCju{QKPU`J_U!J#1aj|vDzzCaPNy*+XDZwF$^q%vaE2qEm-8< z$DRH^N|0k1SHP(h<)>DUWvbWw0YTe|28gn`J}Qt~nB8)91MZs!2fO0Szoj(`<`-(( zwj-GMbpvSSOH_nxu&8sOj!>VGXJucAl16*4vK@asU(@Y05TOeek!-S*;i#6`eN}gs9Dr*0EW}- z&Y5DCp#__?T4?xlAGt#pnm6wkxr{1tMUJ0Bwk*e+FY|pm(&dmZl2i@JmG5K~HSnZr zv&?fdV6WVUm5CN18=m;)6Vh}1nDDq0{wae=6DY4&lv=1PJgJ6ZAKd%S1hasmg8B<{ zU$$jPl8*CPeme3I5Dlqy&xcgz2^oIKjTHEHRpw9iT7M^^ubI9l-!ZJxnnz%T^`Wh- z3bfAdK=Ff#{DR`AMJ4*TW8i1!gnpjn+T#fs5xUSXE-a08 z67RBs8h)pu+1Lwx8LAi=Qol@cPR&unsfi^Wz$CZ0p@}b}P~kfup$}OJRR4fOfP-c8 zOWHW0+&7pmhUG*uVBH8B#lv386>%V_J?3@n`hknf3R7f8Orm*Rnx9QNn42%m)`Xbw z4Z4+A!4w<ggv}3;GZx8#5k+6aBll*f>u34&PG~Z! zKrS2fuEFEhY&dCdopg4*K1{K_xxF4+-<2N~4*!((BNl~C#;W=Irh1e79A6ltKU$FF zDE^gCN?pi@r^PiI&GiKo`i@# z(HVA2tzZ2-!5)a=&=OZ2X0CWzj0-SzKe!`g^tLDSbu>Fb+@pTgDRtloHu{Jmrklnd z`*O49MQv3wm|gMjUH-J{`54eK_^M^MbIgvo8!IfR3AO0o95~b*t;-iF>_%@ACq`UE zIlXLqSobnChG5xX4l6oX*G+J0QVbVqX|2m^)?~o#=&Z0_%sm<8JJDJ>T3_f?j&xu7 z?#?yJ`9deL+4s9S%8fUjLe;B0#K7|x-iy+paCQ7JCa7B6G!@0TFb`wkdxmCdrm`CTTKEi2t4hHkxq@nqT6 zSDW0t*07H=UewfFid2lV`G`VjGsnGCX*J!c(De}*4z6$bsAr4xl#hnlN72N?++iCj zq_1_poZ8@thRznOLJ;juTAO>0K>; zfU;~RHHBk;ceez=S>m2>sC$S{H7c~IPDgNk>Mc?+H?km7BR58}u9GfvRRFzq`$LZM z+9E;3bz1(bx#y=IedN4lOJq>+tO#;|U5@Ct=zkZ}4SPtnrmj4vccHBT(40%-ESEkoXP8Iqv zi7r#8*`~=V< zVqR^;1_wU^%X{^7yxoqyrOYnM%$5c;SuVR8#TYQz=UcAuS6-Kqw2`d@p;huaLtja} z&WytOulkmQWkkc1>Br~Xp@)X07W-g&8$dxoz5&VSX2tPpw;z`7-^ z;U0?|XVP3bdiGOYRIf0(w##!jgkNM`P{s$Pna>BpO5Q6%{Nxyt&J$k^G?3>v z>kYYb{8f~!uO)R^jL^P`qJ0DgxEA)C!D&wW+ zs_WOACYYz-?r?yzDU*E)ivZ(Eu>ycFY20sYc-qq_65zl5>P0w#Vya5g7ca@{a&UDI zJW8(tyvB|h0A$hNwTTygV-=RI1!PTQd{GV4A*Yt=oOElsUA;DllYSM3{_A@1Z)K}J zN;+@_7Zjba&3=h!bMq?Ti@N|=AU`cY+u4&9l_~7_x6xY<8|K`y_Um+|S0GFVOEc!1 zTT!XPS)q}b&6~{zt;4D2DsxQ}>{K-zQKuAq0ubc^GM|f|yiY$ZMU&+4pCfSVTbV~G=r@XaU(`7wlwyy8 zHC<;mO0ftm8k;$|7|XC=9pil3l&WD)xYG4?1Xf~KC^ngkv`q?x4LRy^+ z8kjqk3+}lH<*0I(*8vJl#XJvNVd$L> zl0|oluI;QmH7GMsCj(_`{Xh{nFiZYkL60`}|q+uLQ zdngS+@~$=|ocKv+8#>OLvx={iZOqnnCo%>CcAf5)&F!vnQzu-W?B}x{cMJHFPQS8I zhZq@qypUWO%SYfc1qKRoL+^2vOmFQBzi(oG54B+$Fkx{TY1`Q_0!!eNSTdWlP|qXO z9UlRG1CCbo2}W>7v=atf$9J=MgU?L4OfbBe=I=#GzLH)bTGApj+Q{aJ(x|C$5vgj6 zfzYZkKK>1ZwLwR5cm|M-vu&-gr&;_dUx7Yor0nF_oh?vgPiu%bEgXyuBR6Q)%U&8% zyozJV93MOO!cv&=fl)2>S8UbCt&>2z#V=w5g-$RY_CMY|Jo-+-c)B##7H};l&|yh;*`xK`-J9##nnM2Gt`orX; zMwl<&zxlM8;YQ^swXtufG=&9~l_649p6l0ryW)P=Xql&HkS0Xz8a+%SBH7Sox}VQ) zRhr+Rg-EHYanGg!#Br`+7xJ{1y#9GIrTcZf?OrA%D#C)Z2j{njpfjsEDC!Q6I*0iz>vZa7QP1tFM!>|&J<;k+H;!MO?&LKZ~|@q%_r; za`T;<|I`muU!RS10OM6r1MBn^mYl)pk^YK5iu>p~(}KD9sd&-My0&3{3x$Opotk?a zB6laI<%>&#wk`;^Qu*m}SNKF`nJ!6^UEOU`lO|v6I9#gn){fl0scs^fcR=oe@1EVPKzXhR|wPkbH$i>AZg@$S!V(gMdqjJd3=D!HZae=B~EL!!(ir30}OLFWja z1*+4uEjN$0pYvJ_!$cG;xhEI7)vSbmNm>whMW(|sTRiF5;`?y9OZ9i6H_u33n}@_z zCeG~H12$nsqb)m4giF@6tNQ%n94GG^aia>0fpr@%;JT#rcZ?PEDITf#2ojzDgYHl| zv(HbLFQk4tqGs5h9SZCL^rkLjrEn}MX zyJ7@2Emwv}h%im2h#L{_m{v#17>3X)40`lEX>37%n_^?F{_*Dh(Q~TmlN|w4*|mJ*cf6xbS(`vf=778eh z_P0C&h`{D3#kvKzm;?tZ$BlCm?HwB&u{FOC)uZD^CzNe?R0pvl%OJ*{-hpO(y)2tr zUG2h}sH@1H1LgPWU1%w-dLjHcmDpzI{3C$U=FP&Fi@jZFD}6bQYQMPL%Gm7 z0~b)i>ZL;ET@Um-cPA1LsDGPD8AvYw!na)DHz-^>q9#49Wyk-3U+;Q_4%w$;$TjPt*&yQSkl0JW!Q%I%uT0yk>f2B6`Q8>kai(CN?viCBann&vVdl=muBa15B z$>zSNi-%$UXNsn<&( zT1F{5V8%z_Pet#mtopXE??7}CflB@*ArUE+_g;xcUnq3nh50sY!H&#*Tt`%OZ#8=T zy&XuOFu5GNd`N~g6a)wdHU}E`JAK!-dTqiK?uCMh4}ro(v^%K`bP;IL^M@E&jqC4S z-bwG1UFR(K?eti&GktWEH>fmn+gz8h$O2WxR8ICZy-ICql5+R_#2 z*3y$?KpL0%OZb37zE{vO*p2B$1HDRZep{Y#4}!W<)7q|PVO1HD;4N9!F?k?Xrol~0 zxp89gDN5Oc#oeE8N>5D8PGjT2W?O~S^6(4_FuKWqLd=ORSX_yj!1nQ`hx*a;FZqe0 z8e9!LR{Co-hW@f@o(^h1+h^^+Mn-ir?ljAy8!x`MVpLt58svi?^E6}qdumQ1IuZK= zh6V;}&rkW;g4YO2M=_wB*qqq*Mt?i~nrR6AjMaO9yPLZU6GC;XZt@98&eanteQvJZ z?UFrW$-3SEo%9;R&b1OA;4&SfFfKmoy3uVjiCC6_Jn-_AYnMu7b}{wy-9iy{^m_^M zObxjnBaxLHdZ?Go`=Fk~Guij54J?YIKNm-zq*wgNxOj29S#}bnc9%k)vb{zl)VoV7 zxApc8x2g=!bm*EdY59H24c;$|yY`DaBa7zt>NbS0h2yjPiM|4c=})+ow|B#E0r>H@ z%{9~PI9ag4T5rM`-m~s4Phl_swD=4guhjmiUmti|x@gT7j7gP>Hm^s@wT_$Lb;!^4 zVr~`A7u)AI^4*;8*dhMx;MHdPCu?jffvTf-Av<1u3HJSufMqDs<=nXQvYn(7`f{|@ zg)xiPUq<1_POVaicy7~2aTHlJ$s`E1l8(=FLnAqD3jO`|c@v_y3&Qk(pf9WD=o^L~ex!72RxE^yVNUvgt#PNLqY1kYmgET-Ux+>#Dx;=<_m*6yT*cPMl&-{b)NHR3$;S%|%@vHnizG zP>WNx0y<=yPb~$fdWTlvdFy~0_RELV5uK{wqyy=sDS!^#vp$DXrCoTQ)#+ZLwcK0^ zSr!mpe{BfJ0%;w?io5D=yn2h5PW&-FLAyIE=yt6cJ>zzoOkCXv)sy%$554UTM}z=j z#c%0IJgdvhG|ZRHT5%+v{}9m?oiSVhbz!oOHhj`uDIja0&Um$V`=KJ}>?K$tPpfG< zoI8dLhn?s?EpKOl+;lDsf4+E_>}^BtsDODz@!H2u@o4_@(bxt38tP*!Y6|jhXjGao zHsP(Y7GkNZM(ryREu<%nUc;_iHs1Kb4YBoLSK!u+4z_E8)V(s)--}Qr}^?C%g?~T7!`^88!gY7hWS|d!i7uBvr_HB$p z^F)kY!>J8eAK;7SF&`mtHzOilpy#HLDG+-zGr@mtnXxwzX=#S6kogk;X_I3$PT-9k z$kk)qGS;^ye)ELf^1gP$#cl?>=7J7abjwgs^O1f|v9EDR`prWt0*;I18*6;|xRql<#Vr{QjSX=(& z2MZh8y$BIpH_vTuy7VWdwC`Fd@!-kbi)*jyiGWx9a53*N77LM?8g-*XewY&rg(jY) z3sF8({PIUa2BD;Z5mM71aA*8%OsCQ!0~#YozmK9XHu&1^y>TU%cC=cXk@PujEiPBg z?_)zJL?>$n2AT@=&rF#pQ?E__akd$Sboa|KL2Kihfl7GXFu7TyXi_B6-l#~~AB+FO zKC$>oYT6A4aI$p@gqHb5cFi+r%H^^cMQ~yZE1-2F zEka^m+fVy})E$hS;srU?2lN&*IrGf6vLa*%cJ#c`Lv4(+Y%Ju;mmvl2(l?YBl552Z zxkAEb_x1y%RbQwVL^qvp&8S@?*g>h%xJ>K>2;zn5z96UGa!<(9NPHoV_+s@v`6i>F z<(J5rawMD`%lIV)G_n~;We12?G=E2^Vzz;U+;eCM6FjrIZLzkTC|fWZa70i(XQr=- ze~Y@t4+PsfW@BifI)L4DZ?({`o3TIrl4O&3x#119DE$;ZZ#}M5uM`+Pf^NRP&3w&6 zk&7+ufabx@2JcCx8ZGi3?6e}MabclNhF3bv?EMv$?F$ZIJUY5Mx#t(o27WRzb3f5Q z3q3cs(rNp32NmA7VSv$&P_&F_jvkmWJ!xN=v-nc`DVl#=V3&M+eD;qqmz@h!h2NR9 zX@Gvv%w4KH0fC1KtJ*4)d0O#m(?Mszm4Kgw(~9~f=nAN2pY?WFmSwA{O7pPttX^6o z(3l!r;ktm@{JZ>D{5lUhUmv(~6MX*&yqh-~CjhTRK%c}ON+ZW;5D;H;J&V8sbN38w@6>?@Sy5KbRtOr*3h{-sWa%L ztt;)L{>E9=fj$RP%8F8eqSLa6Z;aNI{Sa|=eg+eH2#Sifm=7IK^17rlsOm zuh)d5FD}LnWPgQedDZ_qI}pG~QIOVqtrS@ul02t!+4S7HCD|q+uJXOjAzn7=XYD1K z!g`5Im0aw2v4l_roU~h1@a%H?-N-*iGkIYwt1lFh|1qqsX>?(Phc|?EefF|NXKdkQtOY6eA zk^iYjW3W-cF;tKmHhb+DLU7^u^ZUpkR_`O=Uu5>ywE6%NrcD=nn%VL1+o)BVI!4g< zMTvgyPU*nbz=(h0L;Y3te2=9kcl5$KtAD;;Nty?%x{rmKqB$(y4?nF7yW{1!H@)ni zri7Li%9$E2IAUdFsm}jAnFoJ4Gex89be*Bq9C}AESp7XD{IgyipiJBeMUF>yC#&-G zgv4i9VUMM|_`I$b-Ip-mljNFmeDz(qC3H*kK}UJvfiV>*{!y}c)5KYUEnnrjo-RIk z7Zo?|O88L!O=|p9`S_^Tb)3y>UCoGb_~ti)=NxU|XWZvGj}s^5L-yt^@t**O^WV&A zX!dx7&{QttT*~d2$r?U0skA;4v^o-iJ@~%FZNr=U&IxAZ$!Ff~hKP+P_jI1u6yns? zUD|Qanmg&9>XQ&5dwH5pS)}}wQ)(*Mz{*)!-}7DfnG0|Vb%fOC7462S_1NzPJCxPE zXv`ThhQD3L$mofbLxzNt)3|*5^~=jj-@kEA_Q|WCcWcD{sL#?D~_J%60FEX$>6)Y1*qdcY?hhO^yJNsfcb|$j zdD>{@#hIaFnS{!mHI+H7@>=)!K3|)eaE9FIJR7P}*1jsCw?jgFx`mPJf&_R7uY3wU zDTw#Feh1&JBfOU&QQ!mpt%zEGIbaA5J*^sY1V^Z!Tddj~miuSTYzBkAid8yr#{A_v z$mz^4gH8pS4B7nv(nK&Wp6F59{p`|Gtbtpc{)A>p*qLmt()h=}RG{B_;5y|kGWgV) zYCfA^U%%!6Wp@I$oo||aW9W*=%|E`OG#uc+foI=fXC-QDjPC{`zq^>tL5^-0;T5{| zq^F``0z6k@8S4x=i5Z2&?&F)T>u5^x?Dj{ zA!IwUepXr`F)p3Z{r-j10CbESevJ!h)W{t)znPJ{+~MRqc+k^dd|nnDfLD&aw$5Lc z{5u2B=j(}y9>!5}J#tXJeB`&k-PG}2;*W!ueG2I7`RGHnz1BH(y?10+U#^=JuF@xg z)@#fUgXrtXf=_hr7IOLiMaND@=T}NwpxhXAu{y4tH|;OHzh4=X2`4a2nB#=x27DycP1%en^~A5wii>T?o!ig;dJXi@{KQP3S`SGnXhFQ9ivTo{T1u$ zZB-iB2K-^pxla}`QaN!OJKq$l8YFy(E$2SZr-y5BK{}ZS;F*9VIS zv{ml_ir;fqa1(NHFT*7?^x0eEY6f0u?v)wb8NKj2mK2(O1UgL?d`Sicu^oHXWID#3 zQkKGkP7{#~q(K6xCaacf{yKqW>~gu>J+mLQyZ5FR2?k0$E6-3MC-dD1+S?C2UE9rZ zrvBHE$#xfvNC5QFRyr)Gb!8!wTBkJ!pu%WWxna^CJ43~Y*`~fXF6|z5TyV7SAbJEy z^!~azFHpBXYY!=%(0(x40TmBB7rTM;Ap%9=!EU>WJsbsIgBfM5(u8i37vB%_ z@P(-B27p^W2XV9stQ+GMz_Rdg&hiEmjqNKAXp@@{r5sJA71=rWv+X2Dwy@Xr{mw;-~Rzr1`$ulM<$TR^&={PA>tlBYksJI6p=&AQq9^o>Ie|`j3!Zviwn0A+$vvWG8AroOt= zTL!FQBo8Q)Py0`XbD@>_9}_y;|1Gb;4#H#qfel;z!TE0EIM`%tG>DqMmy&GOwV5+o zmANoowq9W>7-6`xa)9}4)a?`dPj_BkBe1hAj-d2nfQOEwqwXuEu{=mj#8~a?+B~$j zwt}25Rtx~E_B6!!%}!feMs_cG+I-Cnk1G0rqoWKQPwhSCp3u3aCA{>fil;j-cMh*L z;n?X$*3g+1xCI|a_7QlMj_K$qsRJj?@c2hJ+I8CR%{g&XG=x5=g^aM3z!aBMfAquR z@LAKVthZQqv0OvNV~uAd|8wtAIaifeHRpCF_(7{^auQL8vxWk*6*wknZgx^5vArSNT@NFh73v*E7?wPRt*@@ckkDAR$)pF{I zaSktbT5PUd672Dt#>PhHfBgjx@%Ve`?Zs9|=FOyk_HNh5!8^k{qPY4}rQ}UyR#tQm zLtc-dK-xm~To1q`Gzkcyr^@$~3-Fcbv2nJwwf!jwCQmEXUe+3z328Mq*U?E3R|913 zmikLIg+t}sjWaK7)0Vyj-`_2AXpc|%H#XK8dYFsEl9sGpHG_R^U=tHnbD{JZ0Hcnr h!JF3uZf()moa1~7-m3(VUIYb^-lQl> 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�DFPfNAWr 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 bcegxMlBF%zrQR6MZ{|yv3S-g#yYznmi;Ctf literal 0 HcmV?d00001 diff --git a/www/images/images5.jpeg b/www/images/images5.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..7a4f8b4dd46853a69edde8610d54575d6c02aa75 GIT binary patch literal 6985 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 dNmMb^DeC+gT`vqrh`x+7?+(QBi85Zz{2yoRBn Date: Tue, 1 Feb 2022 21:46:52 +0300 Subject: [PATCH 08/11] add: aplication/pdf --- config/simple.toml.tmp1 | 70 ++++++++++++++++++++++++++++++++++++++++ src/Client/Response.cpp | 5 ++- www/rfc2818.pdf | Bin 0 -> 25390 bytes 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 config/simple.toml.tmp1 create mode 100644 www/rfc2818.pdf diff --git a/config/simple.toml.tmp1 b/config/simple.toml.tmp1 new file mode 100644 index 0000000..97957bd --- /dev/null +++ b/config/simple.toml.tmp1 @@ -0,0 +1,70 @@ +[[server]] + name = "Edu" + host = "127.0.0.1" + port = 8080 + body_size_limit = 100000 + [server.error_page] + 400 = "/var/www/poheck/Edu/errorPages/error_400.html" + 403 = "/var/www/poheck/Edu/errorPages/error_403.html" + 404 = "/var/www/poheck/Edu/errorPages/error_404.html" + [[server.location]] + location = "/" + root = "/var/www/poheck/Edu/" + methods = ["GET"] + autoindex = false + directory_file = "index.html" + [[server.location]] + location = "/errorlist" + root = "/var/www/poheck/Edu/errorPages/" + methods = ["GET"] + autoindex = false + directory_file = "this.html" + [[server.location]] + location = "/images" + root = "/var/www/poheck/Edu/images/" + methods = ["GET", "POST", "DELETE"] + autoindex = true + directory_file = "oops.html" + [[server.location]] + location = "/cats" + root = "/var/www/poheck/Edu/images/cats/" + methods = ["GET", "POST", "DELETE"] + autoindex = true + [[server.location]] + location = "/dogs" + root = "/var/www/poheck/Edu/images/dogs/" + methods = ["GET", "POST", "DELETE"] + autoindex = true + [[server.location]] + location = "/docs" + root = "/var/www/poheck/Edu/docs/" + redirect = ["301","http::/127.0.0.1::8080/documents"] + [[server.location]] + location = "/documents" + root = "/var/www/poheck/Edu/documents/" + methods = ["GET", "DELETE"] + autoindex = true + upload_accept = true + upload_dir = "/var/www/poheck/Edu/upload/" + [[server.location]] + location = "/upload" + root = "/var/www/poheck/Edu/upload/" + methods = ["POST", "DELETE"] + autoindex = true + upload_accept = true + upload_dir = "/var/www/poheck/Edu/upload/" +[[server]] + name = "2222" + host = "localhost" + port = 8081 + body_size_limit = 65356 + [server.error_page] + 404 = "/var/www/poheck/errorPages/error_404.html" + [[server.location]] + location = "/root2/" + root = "/var/www/html/jopa.html" + methods = ["GET", "POST"] + autoindex = true + directory_file = "its_a_directory.html" + upload_accept = false + upload_dir = "/var/www/html/upload" diff --git a/src/Client/Response.cpp b/src/Client/Response.cpp index 690f90c..245192d 100644 --- a/src/Client/Response.cpp +++ b/src/Client/Response.cpp @@ -31,6 +31,7 @@ void Response::setData(Request request, ServerConfig *config) void Response::OpenResponseFile(const char *path) { std::stringstream ss; + // char buf[BUFFSIZE + 1] = {0}; std::ifstream file(path, std::ifstream::in); if (file.is_open()) @@ -88,7 +89,9 @@ std::string Response::getContentType(void) else if (type == "png") return ("image/png"); else if (type == "bmp") - return ( "image/bmp"); + return ("image/bmp"); + else if (type == "pdf") + return ("application/pdf"); else return ("text/plain"); diff --git a/www/rfc2818.pdf b/www/rfc2818.pdf new file mode 100644 index 0000000000000000000000000000000000000000..cbed8b4ad123204cff11d583c6d4cafc6b8f67e5 GIT binary patch literal 25390 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 m{)5E6I_h&WA|8A^}f|1pj*s5w)G_%>NJ6PK{gu literal 0 HcmV?d00001 From d6ef4d242dc5bb5b11972bf6296474b050f256f8 Mon Sep 17 00:00:00 2001 From: Talyx Date: Wed, 2 Feb 2022 14:10:42 +0300 Subject: [PATCH 09/11] Makefile: add flag --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e7e4a18..f0d37a4 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ SANFLAGS = -fsanitize=address # SANFLAGS = -fsanitize=leak -CXXFLAGS = -Wall -Wextra -Werror -g -std=c++98 $(SANFLAGS) +CXXFLAGS = -Wall -Wextra -Werror -g -std=c++98 -fno-limit-debug-info $(SANFLAGS) CPPFLAGS += -MD -MP From 52b7e214cb45e21c834922504c2a7dc68759ccfc Mon Sep 17 00:00:00 2001 From: Talyx Date: Wed, 2 Feb 2022 14:11:20 +0300 Subject: [PATCH 10/11] add: new mime-types --- src/Client/Response.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Client/Response.cpp b/src/Client/Response.cpp index 245192d..e254282 100644 --- a/src/Client/Response.cpp +++ b/src/Client/Response.cpp @@ -84,6 +84,14 @@ std::string Response::getContentType(void) return ("text/css"); else if (type == "js") return ("text/javascript"); + else if (type == "json") + return ("application/json"); + else if (type == "woff") + return ("application/x-font-woff"); + else if (type == "mp4" || type == "m4v" || type == " f4v") + return ("video/mp4"); + else if (type == "ico") + return ("image/x-icon"); else if (type == "jpeg" || type == "jpg") return ("image/jpeg"); else if (type == "png") @@ -103,8 +111,6 @@ void Response::invalidClient(void) std::string tmp; //body - // _body = getErrorPage(_code); - // std::cout << RED << "Invalid Client method called\nCODE: " << _code << " " << getReasonPhrase(_code) << ZERO_C << std::endl; generateBody(); //Header generateHeader(); From 842033b4bcb911c4a9fe0a79bacff39fdd292245 Mon Sep 17 00:00:00 2001 From: Talyx Date: Wed, 2 Feb 2022 14:12:30 +0300 Subject: [PATCH 11/11] fix: ServerConfig segv --- src/Server/Server.cpp | 10 +++++++++ src/Server/ServerConfig.cpp | 44 ++++++++++++++++++------------------- src/Server/ServerConfig.hpp | 6 ++--- 3 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/Server/Server.cpp b/src/Server/Server.cpp index 2937470..2bfe5f2 100644 --- a/src/Server/Server.cpp +++ b/src/Server/Server.cpp @@ -225,15 +225,25 @@ void Server::start(void) void Server::end(void) { std::vector::iterator pri; + std::vector::iterator loc; + std::vector< location *> l; pri = _configs.begin(); while (pri != _configs.end()) { (*pri)->printFields(); + l = (*pri)->getLocations(); + loc = l.begin(); + while (loc != l.end()) + { + delete *loc; + loc++; + } delete *pri; pri++; } } + //----------------------------------------------Other------------------------------------------------------------------------------------------------ void Server::checkError(int fd, std::string str) { diff --git a/src/Server/ServerConfig.cpp b/src/Server/ServerConfig.cpp index 947df84..91e531d 100644 --- a/src/Server/ServerConfig.cpp +++ b/src/Server/ServerConfig.cpp @@ -33,7 +33,7 @@ int ServerConfig::getClientBodySize(void) return (_clientBodySize); } -std::vector ServerConfig::getLocations(void) +std::vector ServerConfig::getLocations(void) { return (_locations); } @@ -73,7 +73,7 @@ void ServerConfig::setErrorPages(std::map pages) _errorPages = pages; } -void ServerConfig::setLocations(std::vector locations) +void ServerConfig::setLocations(std::vector locations) { _locations = locations; } @@ -142,7 +142,7 @@ int ServerConfig::putLocation(toml_node *node) TOMLMapArray::iterator it = arr->begin(); TOMLMap *map; TOMLMap::iterator it1; - location tmp; + location *tmp; TOMLArray::iterator it2; TOMLArray Array; @@ -151,43 +151,44 @@ int ServerConfig::putLocation(toml_node *node) { map = *it; it1 = map->begin(); + tmp = new location; while (it1 != map->end()) { if (it1->first == "location") { if (it1->second->get_type() != toml_node::STRING) return (1); - tmp.location = *it1->second->getString(); + tmp->location = *it1->second->getString(); } else if (it1->first == "root") { if (it1->second->get_type() != toml_node::STRING) return (1); - tmp.root = *it1->second->getString(); + tmp->root = *it1->second->getString(); } else if (it1->first == "autoindex") { if (it1->second->get_type() != toml_node::BOOL) return (1); - tmp.autoindex = it1->second->getBool(); + tmp->autoindex = it1->second->getBool(); } else if (it1->first == "upload_accept") { if (it1->second->get_type() != toml_node::BOOL) return (1); - tmp.uploadAccept = it1->second->getBool(); + tmp->uploadAccept = it1->second->getBool(); } else if (it1->first == "upload_dir") { if (it1->second->get_type() != toml_node::STRING) return (1); - tmp.uploadDir = *it1->second->getString(); + tmp->uploadDir = *it1->second->getString(); } else if (it1->first == "directory_file") { if (it1->second->get_type() != toml_node::STRING) return (1); - tmp.directoryFile = *it1->second->getString(); + tmp->directoryFile = *it1->second->getString(); } else if (it1->first == "methods") { @@ -199,7 +200,7 @@ int ServerConfig::putLocation(toml_node *node) { if ((*it2)->get_type() != toml_node::STRING) return (1); - tmp.methods.push_back(*((*it2)->getString())); + tmp->methods.push_back(*((*it2)->getString())); ++it2; } @@ -212,14 +213,13 @@ int ServerConfig::putLocation(toml_node *node) it2 = Array.begin(); str = *(*it2)->getString(); ++it2; - tmp.redirect[atoi(str.c_str())] = *(*it2)->getString(); + tmp->redirect.insert(std::make_pair(atoi(str.c_str()), *(*it2)->getString())); } else std::cout << RED << it1->first << ZERO_C << std::endl; it1++; } _locations.push_back(tmp); - memset(&tmp, 0, sizeof(tmp)); it++; } return (0); @@ -259,7 +259,7 @@ void ServerConfig::fillFields(void) void ServerConfig::printFields(void) { - std::vector::iterator it; + std::vector::iterator it; std::map::iterator it1; std::vector::iterator it2; std::map::iterator it3; @@ -275,21 +275,21 @@ void ServerConfig::printFields(void) while (it != _locations.end()) { std::cout << PINK << "------------------------------------------------\n"; - std::cout << YELLOW << "location " << BLUE << (*it).location <location <root <directoryFile <uploadDir <autoindex <uploadAccept <methods.begin(); + while (it2 != (*it)->methods.end()) { std::cout << BLUE << *it2 << " "; it2++; } std::cout << std::endl; - it3 = (*it).redirect.begin(); + it3 = (*it)->redirect.begin(); std::cout << YELLOW << "redirection" << RED << " " << it3->first << " " << BLUE << it3->second << std::endl; ++it; std::cout << PINK << "------------------------------------------------\n"; diff --git a/src/Server/ServerConfig.hpp b/src/Server/ServerConfig.hpp index 39be2d4..9749b5a 100644 --- a/src/Server/ServerConfig.hpp +++ b/src/Server/ServerConfig.hpp @@ -28,7 +28,7 @@ private: int _clientBodySize; std::map _errorPages; - std::vector _locations; + std::vector _locations; public: void setServerName(std::string); @@ -36,14 +36,14 @@ public: void setPort(int); void setClientBodySize(int); void setErrorPages(std::map); - void setLocations(std::vector); + void setLocations(std::vector); void setRoot(TOMLMap *); std::string getServerName(void); std::string getHost(void); int getPort(void); int getClientBodySize(void); - std::vector getLocations(void); + std::vector getLocations(void); std::map getErrorPages(void); TOMLMap *getRoot(void);