From fbaebfb3a2c02be3e6c447466b3890b165602a2d Mon Sep 17 00:00:00 2001 From: Talyx Date: Mon, 7 Feb 2022 14:17:03 +0300 Subject: [PATCH 1/3] add: post and delete method --- src/Client/Client.cpp | 2 +- src/Client/Response.cpp | 257 +++++++++++++++++++++++++++------------- src/Client/Response.hpp | 5 +- 3 files changed, 179 insertions(+), 85 deletions(-) diff --git a/src/Client/Client.cpp b/src/Client/Client.cpp index 797b6dd..aaf65e3 100644 --- a/src/Client/Client.cpp +++ b/src/Client/Client.cpp @@ -165,7 +165,7 @@ std::string Client::generateRespons(serverListen &reqData, std::vectorgetLocations(), _request.getURI()); _response.setData(_request, _config, tmp); - _response.generate(); + _response.generate2(); _headerToSend = _response.getHeader(); _bodyToSend = _response.getBody(); _toSend = _headerToSend + _bodyToSend; diff --git a/src/Client/Response.cpp b/src/Client/Response.cpp index 1894d2b..93006f2 100644 --- a/src/Client/Response.cpp +++ b/src/Client/Response.cpp @@ -5,6 +5,7 @@ Response::Response() { initErrorCode(); + _Autoindex = true; _code = 200; } @@ -48,7 +49,10 @@ void Response::setHeaderBlocks(void) } void Response::setContentType(void) { - _contentType = getContentType(); + if (_request.badCode(_code)) + _contentType = "text/html"; + else + _contentType = getContentType(); } void Response::setContentLength() @@ -86,7 +90,6 @@ void Response::setCacheControl(void) 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()) @@ -96,69 +99,34 @@ void Response::OpenResponseFile(const char *path) file.close(); } else - _body = getErrorPage(403); -} - -void Response::generate() -{ - _fullURI = _request.getFullUri(); - if (_request.badCode(_request.getCode())) - invalidClient(); - else if (_request.getMethod() == "GET") - methodGet(); - // else if (_request.getMethod() == "POST") - // methodPost(); - // else - // methodDelete(); -} - -std::string Response::getFullURI(std::string &str, std::string &str2) -{ - std::string line; - unsigned long pos = str.find_last_of("/"); - if (pos == str.size() - 1) - line = str.substr(0, pos - 1); - line = line + str2; - return (line); -} - -void Response::generate2(void) -{ - _errorPages = _config->getErrorPages(); - _Autoindex = _location->autoindex; - _code = _request.getCode(); - _hostPort.ip = _config->getHost(); - _hostPort.port = _config->getPort(); - _fullURI = getFullURI(_location->root, _request.getURI()); - _method = _request.getMethod(); - - if (_request.badCode(_code)) { - invalidClient(); - return; + _code = 403; + OpenErrorFile(_code); } - if (_method == "GET") - methodGet(); - // else if (_method == "POST") - // methodPost(); - // else - // methodDelete(); - } -//-------------------------------------------------HEADER/BODY--------------------------------------- - -std::string Response::getTime(void) +void Response::OpenErrorFile(int code) { - char buff[1337] = {0}; - struct timeval currTime; - struct tm *t; + std::map::iterator it; + std::stringstream ss; - gettimeofday(&currTime, NULL); - t = gmtime(&currTime.tv_sec); - strftime(buff, 1337, "%a, %d %b %Y %H:%M:%S GMT", t); + it = _errorPages.find(code); + if (it != _errorPages.end()) + { + const char *path = it->second.c_str(); + std::ifstream file(path, std::ifstream::in); - return (buff); + if (file.is_open()) + { + ss << file.rdbuf(); + _body = ss.str(); + file.close(); + } + else + _body = getErrorPage(code); + } + else + _body = getErrorPage(code); } std::string Response::getContentType(void) @@ -195,34 +163,91 @@ std::string Response::getContentType(void) } -void Response::invalidClient(void) +std::string Response::getTime(void) { - std::map::iterator it; + char buff[1337] = {0}; + struct timeval currTime; + struct tm *t; - it = _errorPages.find(_code); - if (it != _errorPages.end()) - OpenResponseFile(it->second.c_str()); - else - _body = getErrorPage(_code); - setHeaderBlocks(); - generateHeader(); + gettimeofday(&currTime, NULL); + t = gmtime(&currTime.tv_sec); + strftime(buff, 1337, "%a, %d %b %Y %H:%M:%S GMT", t); - DBOUT << RED << "Error Method called" << ENDL; + return (buff); +} + +std::string Response::getFullURI(void) +{ + std::string tmp; + bool end = false; + std::string ret = ""; + + if (!_location->directoryFile.empty()) + { + struct dirent *dirEnt; + DIR *dir = opendir(_location->root.c_str()); + + if (dir == NULL) + { + _code = 404; + return ""; + } + for (dirEnt = readdir(dir); !end && dirEnt; dirEnt = readdir(dir)) + { + tmp = dirEnt->d_name; + if (tmp == _location->directoryFile) + { + ret = tmp; + end = true; + } + } + } + if (!end) + { + ret = _location->root; + } + return (ret); } void Response::generateBody(void) { - if (!_request.badCode(_code) && _request.isDir(_request.getFullUri()) == 0) - _body = Autoindex::getPage(_request.getURI(), _request.getFullUri(), _request.getHost()); + if (!_request.badCode(_code) && _request.isDir(_fullURI) == 0) + { + if (_Autoindex) + { + _body = Autoindex::getPage(_request.getURI(), _fullURI, _request.getHost()); + if (_body.empty()) + _code = 404; + } + else + _code = 403; + } 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); + OpenResponseFile(_fullURI.c_str()); + else if (_request.isFile(_fullURI) == -1) + _code = 404; + + if (_request.badCode(_code)) + OpenErrorFile(_code); } +bool Response::allowedMethod(std::string &method) +{ + std::vector::iterator it; + + it = _location->methods.begin(); + + while (it != _location->methods.end()) + { + if (*it == method) + return (true); + it++; + } + _code = 405; + return (false); + +} void Response::generateHeader(void) { std::stringstream ss; @@ -241,18 +266,86 @@ void Response::generateHeader(void) _header = ss.str(); } +void Response::generate() +{ + _fullURI = _request.getFullUri(); + if (_request.badCode(_request.getCode())) + invalidClient(); + else if (_request.getMethod() == "GET") + methodGet(); + // else if (_request.getMethod() == "POST") + // methodPost(); + // else + // methodDelete(); +} + +void Response::generate2(void) +{ + _errorPages = _config->getErrorPages(); + _Autoindex = _location->autoindex; + _code = _request.getCode(); + _hostPort.ip = _config->getHost(); + _hostPort.port = _config->getPort(); + _fullURI = getFullURI(); + _method = _request.getMethod(); + + if (_request.badCode(_code) || !allowedMethod(_method)) + { + invalidClient(); + return; + } + if (_method == "GET") + methodGet(); + else if (_method == "POST") + methodPost(); + else + methodDelete(); + +} + +//-------------------------------------------------HEADER/BODY--------------------------------------- + + +void Response::invalidClient(void) +{ + OpenErrorFile(_code); + setHeaderBlocks(); + generateHeader(); + + DBOUT << RED << "Error Method called" << ENDL; +} + + void Response::methodGet(void) { - generateBody(); setHeaderBlocks(); - DBOUT << RED << _fullURI << ENDL; - DBOUT << _body.size() << ENDL; generateHeader(); std::cout << GREEN << "GET method called\n" << ZERO_C; - - - +} +void Response::methodPost(void) +{ + _code = 204; + setHeaderBlocks(); + generateHeader(); + DBOUT << GREEN << "POST method called" << ENDL; +} +void Response::methodDelete(void) +{ + if (_request.isFile(_fullURI) == 0) + { + if (remove(_fullURI.c_str()) == 0) + _code = 204; + else + _code = 403; + } + else + _code = 404; + if (_code == 404 || _code == 403) + OpenErrorFile(_code); + setHeaderBlocks(); + generateHeader(); + DBOUT << GREEN << "Delete method called" << ENDL; } //-------------------------------------------------GET/SET--------------------------------------- @@ -332,7 +425,7 @@ std::string Response::getErrorPage(int code) ss << "" << code <<" "<< getReasonPhrase(code) <<"" <<"

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

" - << "
poheck/1.0.0 (KDE)
"; + << "
poheck/1.0.0 (genereted)
"; Page = ss.str(); return (Page); } diff --git a/src/Client/Response.hpp b/src/Client/Response.hpp index 7da9125..ade66cb 100644 --- a/src/Client/Response.hpp +++ b/src/Client/Response.hpp @@ -60,13 +60,14 @@ public: static std::string getReasonPhrase(std::string); static std::string getReasonPhrase(int); std::string getErrorPage(int code); - std::string getFullURI(std::string &, std::string &); - + std::string getFullURI(); + bool allowedMethod(std::string &); void setData(Request, ServerConfig *); void setData(Request &, ServerConfig *, location *location); public: void OpenResponseFile(const char *path); + void OpenErrorFile(int code); void initErrorCode(void); void generate(); void generate2(); From a056a923e09bf74b76678907e5475159725e1ac9 Mon Sep 17 00:00:00 2001 From: Talyx Date: Mon, 7 Feb 2022 22:43:14 +0300 Subject: [PATCH 2/3] add: download files --- src/Client/Client.cpp | 11 ++++++++++- src/Client/Client.hpp | 3 ++- src/Client/Request.cpp | 19 +++++++++++-------- src/Client/Request.hpp | 7 ++++++- src/Client/Response.cpp | 18 ++++++++++++------ src/Server/Server.cpp | 11 +++++++---- 6 files changed, 48 insertions(+), 21 deletions(-) diff --git a/src/Client/Client.cpp b/src/Client/Client.cpp index aaf65e3..23a1ca9 100644 --- a/src/Client/Client.cpp +++ b/src/Client/Client.cpp @@ -71,6 +71,11 @@ void Client::setRawData(char *str) this->_buff = str; } +void Client::setRawData(std::string &buf) +{ + _stringBUF = buf; +} + void Client::setFd(int fd) { this->_fd = fd; @@ -80,7 +85,8 @@ void Client::setFd(int fd) int Client::parseRequest(void) { - _request.setData(_buff); + // _request.setData(_buff); + _request.setData(_stringBUF); _ret = _request.parseRequest(); return (_ret); @@ -154,6 +160,9 @@ std::string Client::generateRespons(void) _to_send_char = new char[len + 1]; std::memcpy(_to_send_char, _toSend.c_str(), len + 1); + // DBOUT << "len = " << len << ENDL; + // DBOUT << "strlen = " << strlen(_to_send_char) << ENDL; + // DBOUT << "content_lenth = " << _request.getContentLength() << ENDL; return (_toSend); } diff --git a/src/Client/Client.hpp b/src/Client/Client.hpp index 16c2b79..7de17aa 100644 --- a/src/Client/Client.hpp +++ b/src/Client/Client.hpp @@ -23,7 +23,7 @@ private: unsigned int _sended; char *_buff; - + std::string _stringBUF; std::string _bodyToSend; std::string _headerToSend; std::string _toSend; @@ -51,6 +51,7 @@ public: char *getStrToSend(void); unsigned int getCounter(void) const; void setRawData(char *); + void setRawData(std::string &); void setFd(int); int getFd(void); unsigned int getRecvCounter(void) const; diff --git a/src/Client/Request.cpp b/src/Client/Request.cpp index 78a9b74..7130787 100644 --- a/src/Client/Request.cpp +++ b/src/Client/Request.cpp @@ -105,6 +105,12 @@ void Request::setData(char *str) { this->_data = str; } + +void Request::setData(std::string &str) +{ + _stringBUF = str; +} + void Request::setData(char *str, ServerConfig *config) { _data = str; @@ -152,16 +158,12 @@ int Request::parseStartLine(std::string str) if (_version != "HTTP/1.1") _ret = 505; - else if (_method != "GET" && _method != "POST" - && _method != "DELETE") - _ret = 405; return (_ret); } -void Request::splitData(char *data) +void Request::splitData(std::string &data) { int pos; - std::stringstream ss; std::string str; str = std::string(data); @@ -175,7 +177,7 @@ void Request::splitData(char *data) } _head = str.substr(0, pos) + "\n"; _headerSize = _head.size() + 3; - str.erase(0, pos + 4); + data.erase(0, pos + 4); _head_ok = true; parseHeader(); if (_contentLength == 0) @@ -185,7 +187,8 @@ void Request::splitData(char *data) return ; else if (!_body_ok) { - _body += str; + + _body.insert(_body.end(), data.begin(), data.end()); if ((_received - _headerSize) == _contentLength) { _body_ok = true; @@ -241,7 +244,7 @@ int Request::parseHeader(void) int Request::parseRequest(void) { if (!_head_ok || !_body_ok) - splitData(_data); + splitData(_stringBUF); return (_ret); } diff --git a/src/Client/Request.hpp b/src/Client/Request.hpp index 6bae5ca..241f5df 100644 --- a/src/Client/Request.hpp +++ b/src/Client/Request.hpp @@ -9,6 +9,7 @@ class Request { private: char *_data; + char *_pointerBody; int _ret; int _row; @@ -29,6 +30,7 @@ private: std::string _connection; std::map _headerField; + std::string _stringBUF; ServerConfig *_config; bool _head_ok; bool _body_ok; @@ -49,11 +51,14 @@ public: unsigned int getContentLength(void) const; unsigned int getHeaderSize(void) const; unsigned int getRecved(void)const; + char *getPointerBody(void)const; + std::map getClientFields(void); bool getChunked(void); void setConfig(ServerConfig *config); void setData(char *); + void setData(std::string &); void setData(char *, ServerConfig *); public: @@ -75,7 +80,7 @@ public: bool autoindexOn(void); void copyFromMap(void); void clear(void); - void splitData(char *); + void splitData(std::string &); void increaseRecvCounter(unsigned int n); ~Request(); diff --git a/src/Client/Response.cpp b/src/Client/Response.cpp index 93006f2..2014773 100644 --- a/src/Client/Response.cpp +++ b/src/Client/Response.cpp @@ -49,7 +49,9 @@ void Response::setHeaderBlocks(void) } void Response::setContentType(void) { - if (_request.badCode(_code)) + if (_code == 204) + return ; + else if (_request.badCode(_code)) _contentType = "text/html"; else _contentType = getContentType(); @@ -254,7 +256,8 @@ void Response::generateHeader(void) std::string tmp; ss << "HTTP/1.1" << " " << _code << " " << getReasonPhrase(_code) << "\r\n"; - ss << "Content-Type: " << _contentType << "\r\n"; + if (!_contentType.empty()) + ss << "Content-Type: " << _contentType << "\r\n"; ss << "Content-Length: " << _contentLength << "\r\n"; ss << "Server: " << _server << "\r\n"; if (!_keepAlive.empty()) @@ -273,10 +276,10 @@ void Response::generate() invalidClient(); else if (_request.getMethod() == "GET") methodGet(); - // else if (_request.getMethod() == "POST") - // methodPost(); - // else - // methodDelete(); + else if (_request.getMethod() == "DELETE") + methodDelete(); + else + methodPost(); } void Response::generate2(void) @@ -325,6 +328,9 @@ void Response::methodGet(void) } void Response::methodPost(void) { + std::ofstream outfile(_fullURI.c_str(), std::ios::out | std::ios::binary); + + outfile.write(_request.getBody().data(), _request.getBody().size()); _code = 204; setHeaderBlocks(); generateHeader(); diff --git a/src/Server/Server.cpp b/src/Server/Server.cpp index dbdeabd..30c51b9 100644 --- a/src/Server/Server.cpp +++ b/src/Server/Server.cpp @@ -87,18 +87,21 @@ void Server::readSocket(Client &client, int fd) int status; int bytes_read; - char buf[BUFFSIZE + 1]; + // char buf[BUFFSIZE + 1]; + std::string stringBUF(BUFFSIZE, 0); DBOUT << TURQ << "IN readSocket" << ENDL; DBOUT << "client in readSocket "<< &client << ENDL; - bytes_read = recv(fd, buf, BUFFSIZE, 0); + bytes_read = recv(fd, &stringBUF[0], BUFFSIZE, 0); if (bytes_read == 0) { client.allRead = true; return; } - buf[bytes_read + 1] = '\0'; - client.setRawData(buf); + // buf[bytes_read + 1] = '\0'; + stringBUF.erase(bytes_read, stringBUF.size()); + client.setRawData(stringBUF); + // client.setRawData(buf); client.increaseRecvCounter(bytes_read); status = client.parseRequest(); // client_map[fd].printClientInfo(); From ce3a4d1a5bf60ae6625240af412ab51928068ac6 Mon Sep 17 00:00:00 2001 From: Talyx Date: Tue, 8 Feb 2022 18:57:59 +0300 Subject: [PATCH 3/3] add : chunked --- src/Client/Request.cpp | 43 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/src/Client/Request.cpp b/src/Client/Request.cpp index 7130787..4729399 100644 --- a/src/Client/Request.cpp +++ b/src/Client/Request.cpp @@ -161,6 +161,21 @@ int Request::parseStartLine(std::string str) return (_ret); } +int checkEnd(const std::string& str, const std::string& end) +{ + size_t i = str.size(); + size_t j = end.size(); + + while (j > 0) + { + i--; + j--; + if (i < 0 || str[i] != end[j]) + return (1); + } + return (0); +} + void Request::splitData(std::string &data) { int pos; @@ -176,15 +191,21 @@ void Request::splitData(std::string &data) return; } _head = str.substr(0, pos) + "\n"; - _headerSize = _head.size() + 3; + _headerSize = _head.size() + 3; data.erase(0, pos + 4); _head_ok = true; parseHeader(); - if (_contentLength == 0) + if (_contentLength == 0 && !_chunked) _body_ok = true; } if (badCode(_ret)) return ; + else if (_chunked) + { + _body.insert(_body.end(), data.begin(), data.end()); + if (checkEnd(_body, "0\r\n\r\n") == 0) + _body_ok = true; + } else if (!_body_ok) { @@ -194,6 +215,24 @@ void Request::splitData(std::string &data) _body_ok = true; } } + if (_head_ok && _body_ok && _chunked) + { + std::string &tmp = _body; + std::string subchunk = tmp.substr(0, 100); + std::string newBody = ""; + int chunksize = strtol(subchunk.c_str(), NULL, 16); + size_t i = 0; + + while (chunksize) + { + i = tmp.find("\r\n", i) + 2; + newBody += tmp.substr(i, chunksize); + i += chunksize + 2; + subchunk = tmp.substr(i, 100); + chunksize = strtol(subchunk.c_str(), NULL, 16); + } + _body = newBody; + } } int Request::parseClientfield(std::string str)